Cam*_*oft 8 php xml domdocument
我需要将XML文档加载到来自外部源的PHP中.XML没有声明它的编码并包含非法字符&
.如果我尝试直接在浏览器中加载XML文档,我会收到类似"在文本内容中找到无效字符"的错误,当在PHP中加载文件时,我会收到很多警告,例如:xmlParseEntityRef: no name in Entity
和Input is not proper UTF-8, indicate encoding ! Bytes: 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);
Run Code Online (Sandbox Code Playgroud)
示例编码问题的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>
Run Code Online (Sandbox Code Playgroud)
小智 11
为了解决这个问题,设置的DomDocument恢复属性来TRUE
加载XML文档之前
$dom->recover = TRUE;
试试这段代码:
$feedURL = '3704017_14022010_050004.xml';
$dom = new DOMDocument();
$dom->recover = TRUE;
$dom->load($feedURL);
Run Code Online (Sandbox Code Playgroud)
尝试使用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>
Run Code Online (Sandbox Code Playgroud)
会是这样的:
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;
}
Run Code Online (Sandbox Code Playgroud)
这是一个简单的状态机,指出我们是否在标签中,如果没有,则使用htmlentities对文本进行编码.
值得注意的是,这将是大型文件的内存需求,因此您可能希望将其重写为流插件或预处理器.