【问题标题】:load DOMDocument with HTML Special Characters (php)加载带有 HTML 特殊字符的 DOMDocument (php)
【发布时间】:2011-04-23 02:53:40
【问题描述】:

我在用 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]: Entity 'rsquo' not defined in /tmp/php1VRb3N, line: 4 in /www/htdocs/bla/upload.php on line 51

【问题讨论】:

    标签: php xml dom load domdocument


    【解决方案1】:

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

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

    【讨论】:

    • 这也将丢弃所有 XML 预定义实体引用,例如 &amp;amp;&amp;lt;。你确定要这样做吗?
    • 是的,没关系。在我的文件中没有像 &amp;amp;&amp;lt; 这样的 XML 预定义实体引用。
    【解决方案2】:

    您的 XML 解析器没有说谎。这是一个无效的(甚至不是格式正确的)文档,您将无法加载任何内容。

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

    您需要找出输入的来源并修复造成它的原因,因为目前它根本不是 XML。在 UTF-8 编码中使用字符引用 (&amp;#8217;) 或仅使用纯文字字符

    作为最后的手段,如果您真的必须接受这种格式错误的无意义输入,您可以对文件进行令人讨厌的字符串替换:

    $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);
    

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2013-08-25
        • 2013-10-14
        • 2011-09-28
        • 2019-07-08
        • 2018-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多