在PHP中验证大型XML文件~400MB

Car*_*ton 5 php xml xmlreader out-of-memory xml-parsing

我有一个大的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();
}
Run Code Online (Sandbox Code Playgroud)

还试过......

$doc->load( $tempFileName, LIBXML_DTDLOAD|LIBXML_DTDVALID )
Run Code Online (Sandbox Code Playgroud)

我用一个大约60MB的文件测试了这个,但是任何更大的东西(~400MB)都会导致一些对我来说是"新鲜杀手"的东西,在看起来像是30秒之后终止脚本.

我以为我可能需要增加脚本的内存,以便在处理60MB时找出峰值使用量,并相应地调整大小,并且还会关闭脚本时间限制以防万一.

set_time_limit(0);
ini_set('memory_limit', '512M');
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不起作用,因为如果内存负载(即使是正确的术语?)一直很高,那么oom杀手似乎是一个linux的东西.

如果我能以某种方式加载xml,这将是很好的,因为我想这将减少内存负载,以便oom杀手不会坚持它的肥胖鼻子并杀死我的过程.

有没有人有任何验证大型XML文件和捕获错误形成错误的经验,我读过很多帖子都指向可能解决我问题的SAX和XMLReader.

更新 所以@chiborg几乎为我解决了这个问题...这个方法唯一的缺点就是我没有看到文件中的所有错误,只是第一个失败,我认为这是有意义的,因为我认为它无法解析失败的第一个点.

当使用simplexml时...它能够捕获文件中的大部分问题并在最后向我展示这很好.

chi*_*org 6

由于SimpleXML和DOM API将始终将文档加载到内存中,因此使用SAX或XMLReader等流式解析器是更好的方法.

通过示例页面中的代码,它可能如下所示:

$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);
Run Code Online (Sandbox Code Playgroud)