在使用DOMDocument函数进行处理之前,在PHP中修复格式错误的XML

前端之家收集整理的这篇文章主要介绍了在使用DOMDocument函数进行处理之前,在PHP中修复格式错误的XML前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要将 XML文档加载到来自外部源的 PHP中. XML没有声明它的编码并包含非法字符,例如&amp ;.如果我尝试直接在浏览器中加载XML文档,我会收到类似“在文本内容中找到无效字符”的错误,当在PHP中加载文件时,我会收到很多警告:xmlParseEntityRef:实体中没有名称,输入不是正确的UTF-8,表示编码!字节:0x9C 0x31 0x21 0x3C.

很明显,XML格式不正确,并且包含应转换为XML实体的非法字符.

这是因为XML提要由许多其他用户提供的数据组成,显然它在我获得之前没有经过验证或重新格式化.

我已经与XML Feed的供应商交谈了,他们说他们正试图让内容提供商对其进行排序,但这看起来很愚蠢,因为他们应该首先验证输入.

我基本上需要修复XML纠正任何编码错误并将任何非法字符转换为XML实体,以便在使用PHP的DOMDocument函数时XML加载问题.

我的代码目前看起来像:

$FeedURL = '3704017_14022010_050004.xml';
  $dom = new DOMDocument();
  $dom->load($FeedURL);

显示编码问题的示例XML文件(单击下载):feed.xml

包含尚未转换为XML实体的字符的示例XML:

<?xml version="1.0"?>
<Feed>
<RECORD>
<ID>117387</ID>
<ADVERTISERNAME>Test</ADVERTISERNAME>
<AID>10544740</AID>
<NAME>This & This</NAME>
<DESCRIPTION>For one day only this is > than this.</DESCRIPTION>
</RECORD>
</Feed>
尝试使用Tidy库,它可用于清理错误的HTML和XML
http://php.net/manual/en/book.tidy.php

一个纯PHP解决方案来修复这样的XML:

<?xml version="1.0"?>
<Feed>
<RECORD>
<ID>117387</ID>
<ADVERTISERNAME>Test < texter</ADVERTISERNAME>
<AID>10544740</AID>
<NAME>This & This</NAME>
<DESCRIPTION>For one day only this is > than this.</DESCRIPTION>
</RECORD>
</Feed>

会是这样的:

function cleanupXML($xml) {
    $xmlOut = '';
    $inTag = false;
    $xmlLen = strlen($xml);
    for($i=0; $i < $xmlLen; ++$i) {
        $char = $xml[$i];
        // $nextChar = $xml[$i+1];
        switch ($char) {
        case '<':
          if (!$inTag) {
              // Seek forward for the next tag boundry
              for($j = $i+1; $j < $xmlLen; ++$j) {
                 $nextChar = $xml[$j];
                 switch($nextChar) {
                 case '<':  // Means a < in text
                   $char = htmlentities($char);
                   break 2;
                 case '>':  // Means we are in a tag
                   $inTag = true;
                   break 2;
                 }
              }
          } else {
             $char = htmlentities($char);
          }
          break;
        case '>':
          if (!$inTag) {  // No need to seek ahead here
             $char = htmlentities($char);
          } else {
             $inTag = false;
          }
          break;
        default:
          if (!$inTag) {
             $char = htmlentities($char);
          }
          break;
        }
        $xmlOut .= $char;
    }
    return $xmlOut;
  }

这是一个简单的状态机,指出我们是否在标签中,如果没有,则使用htmlentities对文本进行编码.

值得注意的是,这将是大型文件的内存需求,因此您可能希望将其重写为流插件或预处理器.

猜你在找的PHP相关文章