php - 大文件上的 simplexml_load_string 错误发生在一个系统上,但不会发生在另一个系统上

标签 php xml simplexml

我正在处理一个我无法编辑的第三方 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>"

对评论和附加信息的一些回复:

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

  • magic_quotes_runtime 绝对关闭。

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

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

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

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

最佳答案

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 flag relaxes any hardcoded limit from the parser. This affects limits like maximum depth of a document or the entity recursion, as well as limits of the size of text nodes.

关于php - 大文件上的 simplexml_load_string 错误发生在一个系统上,但不会发生在另一个系统上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14950589/

相关文章:

php - 从 docker 容器中的 laravel 应用程序连接到主机中的 Postgresql?

php - MySQL - 使用 mysql_fetch_assoc 移动到下一个结果

XML 两个同名标签

android - 性能不佳的 Lint 警告 - 80+ 次查看

php - 使用 PHP 和 xpath 获取祖先节点

php - 使用 Redis 的速率限制 laravel 队列

php - 如何在 PHP 中保护我的 $_GET?

xml - 如何将 xml 节点捕获到哈希中?

php - 如何迭代 SimpleXMLElement 对象的 XML 值

php - 如何解析具有ns2元素的xml