PHP DomDocument无法处理utf-8字符(☆)
networking服务器以utf-8编码提供响应,所有文件都以utf-8编码保存,我所知道的设置已经被设置为utf-8编码。
这里有一个快速的程序,来testing输出是否工作:
<?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());
该scheme的输出是:
<!DOCTYPE html> <html><head><meta charset="utf-8"><title>Test!</title></head><body> <h1>â Hello â World â</h1> </body></html>
其中呈现为:
★你好††世界††
我可能做错了什么? 我必须告诉DomDocument正确处理utf-8多less具体的内容?
DOMDocument::loadHTML()
需要一个HTMLstring。
根据规格,HTML使用ISO-8859-1
编码(ISO拉丁字母1)作为默认值。 这是因为更长,见6.1。 HTML文档字符集 。 实际上,这更多的是普通网页浏览器对Windows-1252
的默认支持。
因为PHP的DOMDocument是基于libxml的,并且带来了专为HTML 4.0devise的HTMLparser ,
我会说,假设你可以加载ISO-8859-1
编码的string是安全的。
你的string是UTF-8
编码。 把所有高于127 / h7F的字符转换成HTML实体 ,你没事的。 如果你不想这样做,那么mb_convert_encoding
与HTML-ENTITIES
目标编码是一样的:
- 那些具有命名实体的angular色将获得命名实体。
€ -> €
- 其他人得到他们的数字(十进制)实体,例如
☆ -> ☆
以下是一个代码示例,通过使用callback函数使进度更加可见:
$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);
这个string的输出示例如下:
☆ -> ☆ ☆ -> ☆ ☆ -> ☆
无论如何,这只是为了更深入地观察你的string。 你想要它可以转换成一个编码loadHTML
可以处理。 这可以通过将US-ASCII
所有外部转换为HTML实体来完成:
$us_ascii = mb_convert_encoding($utf_8, 'HTML-ENTITIES', 'UTF-8');
注意你的input实际上是UTF-8编码的。 如果您甚至有混合编码(可能会发生一些input),则mb_convert_encoding
只能处理每个string的一个编码。 我已经在上面概述了如何在正则expression式的帮助下更具体地进行stringreplace,所以我现在留下进一步的细节。
另一种select是提示编码。 这可以通过修改文档并添加一个
<meta http-equiv="content-type" content="text/html; charset=utf-8">
这是一个指定字符集的Content-Type。 对于不能通过networking服务器访问的HTMLstring(例如,保存在磁盘上或像在你的例子中的string内),这也是最好的做法。 Web服务器通常设置为响应头。
如果你不关心错误的警告,你可以把它添加到string的前面:
$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>
有一个更快的解决scheme,在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
<?php header("Content-type: text/html; charset=utf-8"); $html = <<<HTML <!doctype html> <html> <head> <meta charset="utf-8"> <title>Test!</title> </head> <body> <h1>☆ Hello ☆ World ☆</h1> </body> </html> HTML; $html = mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8"); $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>☆ Hello ☆ World ☆</h1> </body></html>