【问题标题】:simplexml_load_string errors on big files occur on one system but not another大文件上的 simplexml_load_string 错误发生在一个系统上,而不是另一个系统上
【发布时间】:2025-11-28 11:45:01
【问题描述】:

我正在处理一个我无法编辑的第三方 PHP 库,它已经运行了将近一年。它在来自远程服务器的响应中使用simplexml_load_string。最近它一直在大响应中窒息。这是房地产列表的数据馈送,格式如下所示:

<?xml version="1.0"?>
<RETS ReplyCode="0" ReplyText="Operation Successful Reference ID: 9bac803e-b507-49b7-ac7c-d8e8e3f3aa89">
<COUNT Records="9506" />
<DELIMITER value="09" />
<COLUMNS>   sysid   1   2   3   4   5   6   </COLUMNS>
<DATA>  252370080   Residential 0.160   No  ADDR0   06051</DATA>
<DATA>  252370081   Residential 0.440   Yes ADDR0   06043</DATA>
<DATA>  252370082   Residential 1.010   No  ADDR0   06023</DATA>
<DATA>More tab delimited text</DATA>
<!-- snip 9000+ lines -->
</RETS>

我下载了响应的示例文件(大约 22MB),这是我最终调试和理智的地方。两台服务器都运行 PHP 版本 5.3.8,但请注意不同的结果。我可以确定这两个文件是相同的(我想不同的文件大小、strlen 和最后 50 个字符可以通过具有额外回车符的 Windows 换行符来解释)。测试脚本:

error_reporting(-1);
ini_set('display_errors', 1);
$file = 'error-example.xml';
$xml = file_get_contents($file);

echo 'filesize:              ';
var_dump(filesize($file));

echo 'strlen:                ';
var_dump(strlen($xml));

echo 'simplexml object?      ';
var_dump(is_object(simplexml_load_string($xml)));

echo 'Last 50 characters:    ';
var_dump(substr($xml, -50));

在 Windows 上本地输出:

filesize:              int(21893604)
strlen:                int(21893604)
simplexml object?      bool(true)
Last 50 characters:    string(50) "RD DR    CT  Watertown   203-555-5555            </DATA>
</RETS>"

远程 UNIX 服务器上的输出:

filesize:              int(21884093)
strlen:                int(21884093)
simplexml object?      
Warning: simplexml_load_string(): Entity: line 9511: parser error : internal error in /path/to/test.php on line 19

Warning: simplexml_load_string(): AULTED CEILING IN FOYER, BRICK FP IN FR, NEW FLOORING IN LR DR FR FOYER KITCHEN  in /path/to/test.php on line 19

Warning: simplexml_load_string():                                                                                ^ in /path/to/test.php on line 19

Warning: simplexml_load_string(): Entity: line 9511: parser error : Extra content at the end of the document in /path/to/test.php on line 19

Warning: simplexml_load_string(): AULTED CEILING IN FOYER, BRICK FP IN FR, NEW FLOORING IN LR DR FR FOYER KITCHEN  in /path/to/test.php on line 19

Warning: simplexml_load_string():                                                                                ^ in /path/to/test.php on line 19
bool(false)
Last 50 characters:    string(50) "ORD DR   CT  Watertown   203-555-5555            </DATA>
</RETS>"

对 cme​​ts 的一些回复和其他信息:

  • 据我所知,XML 本身似乎是有效的(它确实在我的系统上工作)。

  • magic_quotes_runtime 肯定关闭了。

  • 工作服务器具有 libxml 版本 2.7.7,而另一个具有 2.7.6。这真的能有所作为吗?我找不到 libxml 更改日志,但似乎不太可能。

  • 这似乎只发生在响应/文件超过一定大小时,并且错误总是发生在倒数第二行。

  • 我没有遇到内存问题,测试脚本会立即运行。

如果我知道哪些是相关的,我可以发布这些 PHP 配置的差异。知道问题可能是什么,或者知道我可能想要检查的其他任何内容吗?

【问题讨论】:

  • 只是猜测:如果设置了magic_quotes_runtime,你可以在做file_get_contents(...)之后再做$xml=stripslashes($xml);
  • 可能是 error_reportingdisplay_errorsOfficial Docs。另外,请检查memory_limit,因为听起来您的脚本可能会超出默认限制。
  • 另外,即使您收到不同的错误消息,看起来您在两者上都遇到了相同的一般问题,所以我倾向于使用无效的 xml 文件。
  • @neelsg 我对其中一个没有任何问题,所以我不知道您的意思是什么?
  • 其中一个系统运行 32 位库而另一个运行 64 位库吗?

标签: php xml simplexml


【解决方案1】:

libxml2 changelog 包含"608773 add a missing check in xmlGROW (Daniel Veillard)",这似乎与输入缓冲有关。请注意,我对 libxml2 的内部结构一无所知任何事情,但可以想象您已经解决了 2.7.7 中修复的 2.7.6 错误。

检查直接使用simplexml_load_file()时行为是否有任何不同,并尝试设置libxml解析器相关选项,例如

simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_COMPACT | LIBXML_PARSEHUGE)

具体来说,您可能想试试LIBXML_PARSEHUGE 标志。

http://php.net/manual/en/libxml.constants.php
XML_PARSE_HUGE 标志放宽解析器的任何硬编码限制。这会影响文档的最大深度或实体递归等限制,以及文本节点大小的限制。

【讨论】:

  • 今晚我会看看这个答案和你的 cmets(现在忙于工作),非常感谢您的回复,很抱歉匆忙/不专心。
  • 所有迹象似乎都指向我们需要升级 libxml 的想法。据我所读,我认为我们需要重新编译 PHP。很抱歉没注意这篇文章,我在前面还有其他事情。
  • 首先我将尝试降级我的本地 libxml,看看是否可以重现错误。
  • 哦,伙计,LIBXML_PARSEHUGE 是它!我不知道怎么做,但我之前错过了。谢谢,再次抱歉成为太空箱。
  • 值得注意的是,这适用于其他基于 libxml 的功能,例如 XMLReader。
【解决方案2】:

我的 XMLSpy 确认您的 XML 文件(我从您提供的链接下载的)没有问题并且格式正确。

然而,一个潜在的问题是 XML 序言中缺少“编码”属性这一事实:根据您的 libxml2 版本,我猜可能会出现以下情况: 服务器检查编码属性,如果缺少哪个服务器回退到某个默认值(配置设置)。也许较旧的库版本不检查 BOM。

另请参阅此链接,他们与 libxml 有类似的编码问题: https://*.com/questions/4724241/utf-8-problems-with-php-dom-on-debian-server

其本质是升级你的 libxml 库确实可以解决问题。或者,可能值得检查配置中的默认编码设置。

根据我的 XMLSpy,该文件是 utf-8 编码的 - 作为测试,也许值得检查是否指定

<?xml version="1.0" encoding="UTF-8"?>

因为文件序言阻止您的 Unix 服务器阻塞。

【讨论】:

  • 不幸的是,这不是治愈方法!我唯一能想到的是 libxml 版本,这就是我接下来要检查的内容(我一直在努力避免它)。由于错误似乎只在输入超出一定大小时发生,我猜测/希望这是一个可以通过升级解决的错误。
【解决方案3】:

您的 XML 无效,在这两种情况下都会导致问题。

你只需要一个根。

即。一切都应该在您的标签内:

<?xml version="1.0"?>
<RETS>
    ...
</RETS>

您的 XML 中有多个根,这将导致问题 :-)

尝试将其全部包装在根节点中,看看是否有效。

<?xml version="1.0"?>
<rootNode>
    <RETS>
    ...
    </RETS>
    <count bla="99" />
</rootNode>

我不确定这是否是 libxml 中的差异,或者是不同级别的错误报告允许它在一个而不是另一个上工作,但这对我来说似乎是个问题。

【讨论】:

  • 不幸的是,这不是治愈方法!我唯一能想到的是libxml版本,这就是我接下来要检查的(我一直在努力避免它)。
最近更新 更多