使用HTML特殊字符加载DOMDocument(php)

时间:2010-10-08 22:09:20

标签: php xml dom load domdocument

我有一个问题,用PHP加载一个xml文件。我使用DOMDocument,因为我需要函数getElementsByTagName 我用这个代码。

$dom = new DomDocument('1.0', 'UTF-8');
$dom->resolveExternals = false;
$dom->load($_FILES["file"]["tmp_name"]);

$dom = new DomDocument('1.0', 'UTF-8'); $dom->resolveExternals = false; $dom->load($_FILES["file"]["tmp_name"]);

的ErrorMessage:
警告:DOMDocument :: load()[domdocument.load]:实体'rsquo'未在/ tmp / php1VRb3N中定义,第4行/www/htdocs/bla/upload.php中第4行

3 个答案:

答案 0 :(得分:2)

为了使用该实体,必须在DTD中定义它。否则它是无效的XML。如果您没有DTD,则应在使用DOM加载XML之前对实体进行解码:

$dom->load(
    html_entity_decode(
        file_get_contents($_FILES["file"]["tmp_name"]), 
        ENT_COMPAT, 'UTF-8'));

答案 1 :(得分:1)

您的XML解析器没有说谎。这是一个无效(甚至没有格式良好)的文档,你将无法加载任何东西。

rsquo是HTML中的预定义实体,但不是XML。在XML文档中,如果您想使用除最基本的内置实体(ampltgtquotapos)以外的任何内容,必须在<!DOCTYPE>声明引用的DTD中定义它们。 (这就是XHTML如何做到的。)

您需要找出输入的来源并修复负责创建输入的内容,因为目前它根本不是XML。使用字符引用(&#8217;)或仅使用UTF-8编码的普通文字字符

作为最后的手段如果你真的不得不接受这个输入错误的废话,你可以对文件进行令人讨厌的字符串替换:

$xml= file_get_contents($_FILES['file']['tmp_name']);
$xml= str_replace('&rsquo;', '&#8217;', $xml);
$dom->loadXML(xml);

如果您需要为所有非XML HTML实体执行此操作,而不仅仅rsquo这样做有点棘手。你可以做一个正则表达式替换:

function only_html_entity_decode($match) {
    if (in_array($match[1], array('amp', 'lt', 'gt', 'quot', 'apos')))
        return $match[0];
    else
        return html_entity_decode($match[0], ENT_COMPAT, 'UTF-8');
}
$xml= preg_replace_callback('/&(\w+);/', 'only_html_entity_decode', $xml);

这仍然不是很好,因为它会在评论,CDATA部分和PI之类的地方发送任何&\w+;字符序列,这实际上并不意味着实体引用。但考虑到这种破坏的输入,它可能是你能做的最好的事情。

这肯定比在整个文档上调用html_entity_decode更好,这也会弄乱任何XML实体引用,导致文档在存在&amp;&lt;时中断。 / p>

另一个以不同方式存在疑问的黑客是使用loadHTML()加载文档。

答案 2 :(得分:0)

在bobince的帮助下我的解决方案是:

    $xml= file_get_contents($_FILES['file']['tmp_name']);
    $xml= preg_replace('/&(\w+);/', '', $xml);
    $dom = new DomDocument();
    $dom->loadXML($xml);