PHP DomDocument无法处理utf-8字符(☆)如何解决?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (50)

网络服务器使用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?

提问于
用户回答回答于

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

$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。对于不能通过网络服务器访问的HTML字符串(例如,保存在磁盘上或在您的示例中保存在字符串中),这也是最佳做法。Web服务器通常设置为响应头。

如果你不关心错误的警告,你可以将它添加到字符串的前面:

$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>
用户回答回答于

在DOMDocument中加载你的html文档后,你只需设置(或者更好地说重置)原始编码,就可以更快地解决这个问题。以下是一个示例代码:

$dom = new DOMDocument();
$dom->loadHTML('<?xml encoding="UTF-8">' . $html);

foreach ($dom->childNodes as $item)
    if ($item->nodeType == XML_PI_NODE)
        $dom->removeChild($item);
$dom->encoding = 'UTF-8'; // reset original encoding

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励