PHP - SimpleXML解析错误

时间:2010-12-27 16:21:01

标签: php xml simplexml

在底部查看编辑以显示更准确的错误输出

我使用SimpleXML首次使用PHP解析一些大(~15MB)的XML文件。这些文件是航班搜索结果,所以它们有很长的属性(链接回Kayak;例如:
       “/book/flightcode=1238917408.NxJI6G.0.F.ORBITZAIR,ORBITZAIR.0.f36f1ea92513977249aa695112410052&sid=26-Vu01v7ilzhSAjPVLZ3Ul”

解析时,SimpleXML会抛出此错误:

“实体:第10行:解析器错误:EntityRef:expecting';'在“然后;

“38917408.NxJI6G.0.F.ORBITZAIR,ORBITZAIR.0.f36f1ea92513977249aa695112410052& sid in” 然后;

“simplexml_load_string()[function.simplexml-load-string]:^ in,”

对于存在这些网址的每一行,

等等。

我发现SimpleXML并不喜欢php.net上没有解决方案的长属性。我宁愿现在只使用和学习SimpleXML,如果有一个非常轻松,有点简单的解决方法,可以解决这个错误。

有没有人有解决方案?提前谢谢!

我尝试输入XML的前13行,但它只输出没有XML的信息....所以如果有帮助的话,我可以这样做。我不确定使用另一个解析器/扩展是否会降低功能或易用性,但如果没有解决方法,请随意建议另一个(DOM或XMLReader可能是我想的)。

以下编辑包括较少的误操作输出:

http://dl.dropbox.com/u/10206237/stack_overflow_xml.xml

错误1:

simplexml_load_string() [<a href='function.simplexml-load-string'>function.simplexml-load-string</a>]: Entity: line 10: parser error : EntityRef: expecting ';' in 

错误2 :(我认为XML很好,因为它适用于使用DOM的Python脚本;我正在将它转换为PHP,因为我不知道Python)。我不知道浏览器中的输出会有所不同。感谢您的耐心等待。)

<a href='function.simplexml-load-string'>function.simplexml-load-string</a>]: 38917408.Pt8rW8.0.F.ORBITZAIR,ORBITZAIR.0.f36f1ea92513977249aa695112410052&amp;_sid_ in 

错误3:

function.simplexml-load-string</a>]:                                                                                ^ in     

(所有这些空间都在那里)

4 个答案:

答案 0 :(得分:12)

正如其他答案和评论中所提到的,您的源XML是已破坏,并且XML解析器应该拒绝无效输入。 libxml有一个“恢复”模式,可以让你加载这个破碎的XML,但是你会失去“&amp; sid”部分,所以它无济于事。

如果你很幸运而且你喜欢冒险,你可以尝试以某种方式通过修复输入来使其工作。您可以使用一些字符串替换来转义看起来像是在URL的查询部分中的&符号。

$xml = file_get_contents('broken.xml');
// replace '&' followed by a bunch of letters, numbers
// and underscores and an equal sign with &amp;
$xml = preg_replace('#&(?=[a-z_0-9]+=)#', '&amp;', $xml);
$sxe = simplexml_load_string($xml);

当然,这只是只是黑客攻击,解决问题的唯一好方法是让XML提供商修复他们的生成器。因为如果它生成了破碎的XML,谁知道其他错误会被忽视?

答案 1 :(得分:3)

达里尔对于为什么在上面的评论中发生这种情况有正确的答案。解决这个问题的一种方法是使用str_replace()替换所有'&amp;' &amp; amp;&amp; amp;'在XML中。根据{{​​3}},您还可以使用此正则表达式将&符号替换为其实体:

$s = preg_replace('/&[^; ]{0,6}.?/e', "((substr('\\0',-1) == ';') ? '\\0' : '&amp;'.substr('\\0',1))", 

答案 2 :(得分:0)

对于解析器,解析的xml文件可能太大了。但是您可以尝试将LIBXML_PARSEHUGE作为选项传递 - 这在我的案例中有所帮助。

答案 3 :(得分:0)

我遇到了13MB文件的问题,并通过包含LIBXML_PARSEHUGE参数:

解决了这个问题
$xml = new SimpleXMLElement($contents, LIBXML_PARSEHUGE);

注意:在1GB下使用ini_set并没有解决我的问题,因为PARSED内容占用的数量超过了这个数量。

更激进的方法是将其他库用于STREAM而不是LOAD WHOLE FILE(SAX解析器与DOM解析器),如XML Streamer