繁体   English   中英

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

[英]load DOMDocument with HTML Special Characters (php)

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


$dom = new DomDocument('1.0', 'UTF-8'); $dom->resolveExternals = false; $dom->load($_FILES["file"]["tmp_name"]); 
 <?xml version="1.0" encoding="UTF-8"?> <Data> <value>1796563</value> <value>Verliebt! &rsquo;</value> </Data> 

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

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

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

你的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);

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

它肯定比在整个文档上调用html_entity_decode更好,这也会弄乱任何XML实体引用,导致文档在存在的情况下中断&amp; 或者&lt;

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM