【问题标题】:XML DOMDocument optimizationXML DOM文档优化
【发布时间】:2011-11-10 03:03:09
【问题描述】:

我有一个 5MB 的 XML 文件

我正在使用以下代码获取所有nodeValue

$dom = new DomDocument('1.0', 'UTF-8');
if(!$dom->load($url))
    return;

$games = $dom->getElementsByTagName("game");
foreach($games as $game)
{
            
}

这需要 76 秒,大约有 2000 个games 标签。是否有任何优化或其他解决方案来获取数据?

【问题讨论】:

  • 如果不知道循环的作用,我无法想象优化循环。
  • 查看此链接 [在此处输入链接描述][1] [1]:stackoverflow.com/questions/188414/best-xml-parser-for-php
  • @steve:也许您可以详细说明并以答案的形式提出。 SimpleXML 如何加快循环以获取数据?
  • 您可以在此 [link][1] [1] 中找到一些有用的建议:stackoverflow.com/questions/188414/best-xml-parser-for-php
  • SimpleXML(正如其他人所建议的那样)可能会加快检索速度,但 2000 年的迭代循环是您的性能问题的来源。了解您想对数据做什么会有所帮助。

标签: php xml domdocument


【解决方案1】:

您可以使用DOMXpath 进行查询,这比DOMDocument:: getElementsByTagName() 方法快得多。

<?php
$xpath = new \DOMXpath($dom);
$games = $xpath->query("//game");

foreach ($games as $game) {
    // Code here
}

在我对一个相当大的文件的测试中,这种方法花费了 DOMDocument:: getElementsByTagName() 方法花费了大约 27 分钟(迭代到下一个对象所花费的时间是指数级的)。

【讨论】:

    【解决方案2】:

    您不应该在大型 XML 文件上使用文档对象模型,它适用于人类可读的文档,而不是大型数据集!

    如果您想要快速访问,您应该使用 XMLReader 或 SimpleXML。

    XMLReader 非常适合解析整个文档,SimpleXML 有一个很好的 XPath 函数可以快速检索数据。

    对于 XMLReader,您可以使用以下代码:

    <?php
    
    // Parsing a large document with XMLReader with Expand - DOM/DOMXpath 
    $reader = new XMLReader();
    
    $reader->open("tooBig.xml");
    
    while ($reader->read()) {
        switch ($reader->nodeType) {
            case (XMLREADER::ELEMENT):
            if ($reader->localName == "game") {
                 $node = $reader->expand();
                 $dom = new DomDocument();
                 $n = $dom->importNode($node,true);
                 $dom->appendChild($n);
                 $xp = new DomXpath($dom);
                 $res = $xp->query("/game/title"); // this is an example
                 echo $res->item(0)->nodeValue;
            }
        }
    }
    ?>
    

    以上将输出所有游戏标题(假设您有/game/title XML 结构)。

    对于 SimpleXML,您可以使用:

    $xml = file_get_contents($url);
    $sxml = new SimpleXML($xml);
    $games = $sxml->xpath('/game'); // returns an array of SXML nodes
    foreach ($games as $game)
    {
       print $game->nodeValue;
    }
    

    【讨论】:

    • 感谢您的帮助。我有两个问题,比赛前的斜线是什么。以及如何获取此元素中的字符串: object(SimpleXMLElement)[8991] string 'Handball' (length=8), I want the handball
    • 没有问题.../game 中的斜线表示文档的根目录。这就是 XPath 的工作原理(Google XPath 了解更多信息)。为了回答您的第二个问题,我需要查看您正在使用的 XML 示例。如果您编辑您的问题并将其粘贴进去,我可以看到它。
    • SimpleXML 也会加载整个文件,这绝对不会带来任何速度提升。 DOM 本身也支持 XPath。
    • @cweiske - 你没有注意到我首先建议使用 XMLReader 吗?这更快。致 OP:请通读这些页面,了解有关 PHP 和 XML 的所有信息ibm.com/developerworks/xml/library/x-xmlphp1/index.html
    【解决方案3】:

    我曾经写过一篇关于loading huge XML files with XMLReader 的博客文章——你可能会用到其中的一些。

    使用 DOM 或 SimpleXML 是不可行的,因为两者都将整个文档加载到内存中。

    【讨论】:

    • SimpleXml 相当不错,我在一个 xml 文件上测试过,DOM 用了大约 30 秒,SimpleXML 用了 1 秒:)
    • SimpleXML 已被证明对 OP 非常有用,而 DOM 太慢了——正如我所建议的那样。 XMLReader 与 SAX 一起最快。
    猜你喜欢
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多