我有一个大的XML文件(大约400MB),我需要确保在开始处理之前格式良好。
我尝试过的第一件事就是下面的内容,这很棒,因为我可以看出XML是否格式不正确以及XML的哪些部分是“坏”
$doc = simplexml_load_string($xmlstr);
if (!$doc) {
$errors = libxml_get_errors();
foreach ($errors as $error) {
echo display_xml_error($error);
}
libxml_clear_errors();
}
还试过......
$doc->load( $tempFileName, LIBXML_DTDLOAD|LIBXML_DTDVALID )
我用大约60MB的文件测试了这个,但是任何更大的东西(~400MB)都会让我感到陌生的“oom杀手”在看起来像30秒之后开始并终止脚本。
我认为我可能需要增加脚本的内存,以便在处理60MB时计算出峰值使用率,并相应地调整它的大小,并将脚本时间限制关闭以防万一。
set_time_limit(0);
ini_set('memory_limit', '512M');
不幸的是,这不起作用,因为如果内存负载(即使是正确的术语?)一直很高,那么oom杀手似乎是一个linux的东西。
如果我能以某种方式加载xml,这将是很好的,因为我想这将减少内存负载,以便oom杀手不会粘住它的胖鼻子并杀死我的进程。
有没有人有任何验证大型XML文件和捕获错误形成错误的经验,我读过很多帖子都指向可能解决我问题的SAX和XMLReader。
更新 所以@chiborg对我来说几乎解决了这个问题...这个方法唯一的缺点就是我没有看到文件中的所有错误,只是第一个失败,我认为这是有意义的,因为我认为它无法解析失败的第一个点。
当使用simplexml时...它能够捕获文件中的大部分问题,并在最后显示我很好。
答案 0 :(得分:6)
由于SimpleXML和DOM API将始终将文档加载到内存中,因此使用SAX或XMLReader等流式解析器是更好的方法。
使用example page中的代码,它可能如下所示:
$xml_parser = xml_parser_create();
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
$errors[] = array(
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser));
}
}
xml_parser_free($xml_parser);
答案 1 :(得分:0)
对于大文件,完美使用XMLReader类。
但如果喜欢simplexml语法:https://github.com/dkrnl/SimpleXMLReader/blob/master/library/SimpleXMLReader.php 用法示例:http://github.com/dkrnl/SimpleXMLReader/blob/master/examples/example1.php