使用这个XML片段:
<title>Foos’ bar</title>
当我解析完整的文档与PHP的DOMDocument:
<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadXML($xml);
$dom->saveHTML(); // Output: <title>Foos’ bar</title>
?>
我可以看到一切如预期,HTML符号在标题。
然后我想提取标题文本:
<?php
$xpath = new DOMXpath($dom);
$xpath->query('//title')->item(0)->nodeValue); // Output: Foos bar
?>
即使当我调试和检查$xpath->query('//title')->item(0)
对象时,我也看不到那里的HTML符号。我试图改变编码,XML版本和解析选项,但没有运气。
另外,我不确定XML标记解释的规则是什么,但我有一种预感,html符号被解析出来是因为它是一个有意义的标记。如果我手动更改XML为:
<title><![CDATA[Foos’ bar]]></title>
那么一切都是完美的,我可以访问我的HTML符号在最后的结果。不幸的是,在这种情况下,我无法控制XML源代码。
你知道吗?除了使用正则表达式来取代解析之前的符号吗?
你试过utf8_decode吗?
<?php
$xml = "<title>Foos’ bar</title>";
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadXML($xml);
$dom->saveHTML(); // Output: <title>Foos’ bar</title>
$xpath = new DOMXpath($dom);
$value = $xpath->query('//title')->item(0)->nodeValue;
echo utf8_decode($value); // Output: Foo's Bar
?>
更多细节可以在这个stackoverflow答案中找到
’
是无效的数字字符引用。你得把它换掉。
但是,好消息是,您不需要自己替换它。
这些数字实体早于HTML/XML中与这些数字字符引用相关的字符集没有全局定义的时间。由于HTML 4和XML 1.0就是这种情况,因此使用Unicode的通用字符集(UCS)的代码点。
如果您有这样的损坏或旧的数据,您可以让Tidy为您做清理工作:
$xml = '<title>Foos’ bar</title>';
$config = [
'input-xml' => true,
'output-xml' => true,
'newline' => 'LF',
];
$xml = tidy_parse_string($xml, $config);
$dom = new DOMDocument();
$dom->loadXML($xml);
echo $dom->saveHTML();
输出:<title>Foos’ bar</title>
Tidy对象也带有一个警告;
警告:替换无效的数字字符引用146
这正是我们使用它的原因。
如果你想了解更多,此页列出的电子邮件可能会让你感兴趣。如果Tidy不能为您工作,这也可以告诉您如何自己做。