当前位置: 首页 > 面试题库 >

PHP DomDocument无法处理utf-8字符(☆)

夏兴生
2023-03-14
问题内容

网络服务器使用utf-8编码提供响应,所有文件都使用utf-8编码保存,我所知的所有设置都已设置为utf-8编码。

这是一个快速程序,用于测试输出是否有效:

<?php
$html = <<<HTML
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>Test!</title>
</head>
<body>
    <h1>☆ Hello ☆ World ☆</h1>
</body>
</html>
HTML;

$dom = new DomDocument("1.0", "utf-8");
$dom->loadHTML($html);

header("Content-Type: text/html; charset=utf-8");
echo($dom->saveHTML());

该程序的输出为:

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>Test!</title></head><body>
    <h1>&acirc;&#152;&#134; Hello &acirc;&#152;&#134; World &acirc;&#152;&#134;</h1>
</body></html>

呈现为:

我可能做错了什么?我必须告诉DomDocument正确处理utf-8的具体程度是多少?


问题答案:

DOMDocument::loadHTML()需要一个HTML字符串。

HTML ISO-8859-1根据其规范使用默认的编码(ISO拉丁字母1号)。那是因为更长,请参见 6.1。
HTML文档字符集
。实际上,这更是Windows-1252常见的Web浏览器的默认支持。

我之所以回去很远,是因为PHP的DOMDocument基于libxml,并且带来了专为HTML4.0设计的HTMLparser。

我想可以假设您可以加载ISO-8859-1编码的字符串。

您的字符串已UTF-8编码。将所有高于127/h7F的字符转换为HTML实体,就可以了。如果您不想自己做,mb_convert_encoding那么HTML-ENTITIES目标编码就是这样:

  • 那些已命名实体的字符将获得命名实体。 € -> &euro;
  • 其他人得到他们的数字(十进制)实体,例如 ☆ -> &#9734;

以下是一个代码示例,该示例通过使用回调函数使进度更加明显:

$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);

您的字符串的以下示例输出:

☆ -> &#9734;
☆ -> &#9734;
☆ -> &#9734;

无论如何,那只是为了更深入地研究您的字符串。您希望将其转换为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。对于无法通过Web服务器获得的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>


 类似资料:
  • 问题内容: 下面是测试程序,包括一个汉字: 以下是结果,请看json.dumps将utf-8转换为原始数字! 为什么这坏了?还是我错了? 问题答案: 您应该阅读json.org。完整的JSON规范在右侧的白框中。 生成的JSON没有错。允许生成器生成UTF-8字符串或纯ASCII字符串,在这些字符串中使用符号转义字符。在您的情况下,Python 模块决定转义,并使用转义符号。 顺便说一句:任何符合

  • 问题内容: 我正在寻找有关如何处理来自用户的无效UTF-8输入的一般策略/建议。 即使我的Web应用程序使用UTF-8,还是有些用户输入了无效字符。这会导致PHP的json_encode()错误,并且总体而言似乎是个坏主意。 W3C I18N常见问题解答:多语言形式说:“如果接收到非UTF-8数据,则应将错误消息发送回去。”。 在整个站点中有数十个可以输入数据的站点中,实际上该怎么做呢? 您如何以

  • 问题内容: 为了找出C ++是否适合我的项目,我想测试UTF-8功能。根据参考,我构建了以下示例: 但是,当我输入UTF-8字符时,它的行为不正确: 它不仅不打印,而且立即退出。告诉我没有坠机事故,但出口正常,但是我很难相信。 问题答案: 在Linux上不要使用wstring。 std :: wstring VS std :: string 看看第一个答案。我确定它能回答您的问题。 什么时候应该在

  • 但是现在,当将与预期的序列化对象进行比较时,如果对象中有任何特殊字符,仍然会出现不匹配。默认情况下,方法似乎没有使用UTF-8字符编码。 如何获得UTF-8编码的?

  • 我正在使用组织。simplejavamail:outlook邮件分析器库: 和输出是: Outlook的原始邮件包含以下正文:“Testiviestin sisältö”。 你可以访问该组织。simplejavamail:outlook消息分析器库是否处理UTF-8字符?

  • 问题内容: 昨天我对一个问题的回答之一是建议我确保我的数据库可以正确处理UTF-8字符。我该如何使用MySQL? 问题答案: 更新: 简短答案-您几乎应该始终使用字符集和排序规则。 更改数据库: 看到: 亚伦对此答案的评论如何使MySQL正确处理UTF-8 utf8_general_ci和utf8_unicode_ci有什么区别 转换指南:https : //dev.mysql.com/doc/r