如何解析大型XML文件

时间:2014-12-17 21:52:36

标签: php xml

我有以下代码,它将根据某个子值从XML文件中检索数据。

<?php
$dom = new DOMDocument();
$dom->load('file.xml');
$xpath = new DOMXPath($dom);
echo $xpath->evaluate('string(//Book[BookCode = "AD0WNR"] /Subject)');
?>

如果我有几行,代码就可以了。但主要的xml文件超过200mb,它不会检索任何东西。你能告诉我我做错了什么吗?小文件和大文件都具有相同的结构。

1 个答案:

答案 0 :(得分:2)

为了解析像这样的大型文档,我建议使用像XMLReader这样的流式解析器,它允许您解析XML而无需立即将整个文件加载到内存中。通过使用其expand()方法,可以轻松地将其与DOM API一起使用。

像DOM这样的基于树的解析器速度非常快,但由于必须加载整个文档,因此占用更多内存。像XMLReader这样的流式解析器可以减少内存使用量,因为您一次只能抓取一些文档,但权衡时间更长。

通过使用两者,您可以调整串联使用的方式,以便在最小化处理时间的同时获得内存限制等任何硬边界。


实施例

$dom    = new DOMDocument();
$xpath  = new DOMXPath($dom);
$reader = new XMLReader();
$reader->open('file.xml');

while ($reader->read()) {
    if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'Book') {
        $node = $dom->importNode($reader->expand(), true);
        $result = $xpath->evaluate(
            'string(self::Book[BookCode = "AD0WNR"]/Subject)',
            $node
        );
        if ($result) {
            echo $result;
            $reader->close();
            break;
        }
    }
}

这是在迭代XML中的节点。每当它遇到元素<Book>时,我们:

  1. 将其导入DOM。
  2. 评估XPath表达式 *
  3. 如果XPath表达式找到了我们正在寻找的内容:

    1. 打印结果。
    2. 关闭文件。
    3. 打破阅读循环。
    4. #2和#3我们这样做是因为我们只寻找一个结果。如果您想要找到更多,请删除它们并继续运输。


      (*我将XPath表达式中的初始双正斜杠替换为self::,以作为第二个参数传递给evaluate()的上下文节点执行操作 - 谢谢,{{3 }})

相关问题