DOMDocument::loadHTML()
需要一个 HTML 字符串。
HTMLISO-8859-1
根据其规范默认使用编码(ISO 拉丁字母编号 1)。那是因为更长,见6.1。HTML 文档字符集。实际上,这更多的是对Windows-1252
普通网络浏览器的默认支持。
我回溯到那么远是因为 PHP 的 DOMDocument 基于 libxml,并且带来了专为 HTML 4.0 设计的HTMLparser 。
我会说可以安全地假设您可以加载ISO-8859-1
编码的字符串。
您的字符串已UTF-8
编码。将所有高于 127 / h7F 的字符转换为HTML 实体就可以了。如果您不想自己做,那就是mb_convert_encoding
目标HTML-ENTITIES
编码的作用:
- 那些具有命名实体的角色将获得命名实体。
€ -> €
- 其他人得到他们的数字(十进制)实体,例如
☆ -> ☆
下面是一个代码示例,它通过使用回调函数使进度更加明显:
$html = preg_replace_callback('/[\x{80}-\x{10FFFF}]/u', function($match) {
list($utf8) = $match;
$entity = mb_convert_encoding($utf8, 'HTML-ENTITIES', 'UTF-8');
printf("%s -> %s\n", $utf8, $entity);
return $entity;
}, $html);
您的字符串的此示例输出:
☆ -> ☆
☆ -> ☆
☆ -> ☆
无论如何,这只是为了更深入地了解您的字符串。你想让它要么转换成编码loadHTML
就可以处理。这可以通过将所有外部转换US-ASCII
为 HTML 实体来完成:
$us_ascii = mb_convert_encoding($utf_8, 'HTML-ENTITIES', 'UTF-8');
请注意您的输入实际上是 UTF-8 编码的。如果您甚至有混合编码(某些输入可能会发生这种情况),mb_convert_encoding
则每个字符串只能处理一种编码。我已经在上面概述了如何在正则表达式的帮助下更具体地进行字符串替换,所以我现在留下更多细节。
另一种选择是提示编码。这可以通过修改文档并添加
<meta http-equiv="content-type" content="text/html; charset=utf-8">
这是一个指定字符集的 Content-Type。对于无法通过网络服务器获得的 HTML 字符串(例如,保存在磁盘上或在您的示例中的字符串中),这也是最佳实践。网络服务器通常将其设置为响应标头。
如果您不在乎放错位置的警告,您可以将其添加到字符串前面:
$dom = new DomDocument();
$dom->loadHTML('<meta http-equiv="content-type" content="text/html; charset=utf-8">'.$html);
根据 HTML 2.0 规范,只能出现在<head>
文档部分中的元素将自动放置在那里。这也是这里发生的事情。输出(漂亮的打印):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta charset="utf-8">
<title>Test!</title>
</head>
<body>
<h1>☆ Hello ☆ World ☆</h1>
</body>
</html>