解析XML中的HTML符号

时间:2014-07-01 15:46:37

标签: php xml regex xpath domdocument

获取此XML代码段:

<title>Foos&#146; bar</title>

当我使用PHP的DOMDocument解析整个文档时:

<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadXML($xml);
$dom->saveHTML(); // Output: <title>Foos&#146; 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标记解释的规则是什么,但我有一种预感,即HMLT符号被解析出来,因为它是一个有意义的标记。如果我手动将XML更改为:

<title><![CDATA[Foos&#146; bar]]></title>

然后一切都很完美,我可以在最终结果中访问我的HTML符号。不幸的是,在这种情况下,我无法控制XML源。

你知道吗?除了在解析之前使用正则表达式替换符号?

2 个答案:

答案 0 :(得分:1)

你试过utf8_decode吗?

<?php
$xml = "<title>Foos&#146; bar</title>";
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadXML($xml);
$dom->saveHTML(); // Output: <title>Foos&#146; bar</title>
$xpath = new DOMXpath($dom);
$value = $xpath->query('//title')->item(0)->nodeValue;
echo utf8_decode($value); // Output: Foo's Bar
?>

更多细节可以在at this stackoverflow answer.

找到

答案 1 :(得分:0)

&#146;是无效的数字字符引用。你需要更换它。

然而,好消息是,你不需要自己更换它。

这些数字实体在HTML / XML中的某个时间之前的日期,其中与这些数字字符引用相关的字符集未全局定义。由于HTML 4和XML 1.0就是这种情况,因此使用Unicode的通用字符集(UCS)的代码点。

如果你有这样的破碎或旧数据,你可以让Tidy为你做清理工作:

$xml = '<title>Foos&#146; 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&rsquo; bar</title>

整洁对象也带有一个警告;

  

警告:替换无效的数字字符引用146

这正是我们使用它的原因。

如果您想了解更多信息,列出的on this page电子邮件可能会让您感兴趣。如果Tidy不适合你,这也可能会告诉你如何自己动手。