Оптимизация XML DomDocument - PullRequest
       13

Оптимизация XML DomDocument

3 голосов
/ 04 сентября 2011

У меня есть 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 тегов.Есть ли оптимизация или другое решение для получения данных?

Ответы [ 3 ]

1 голос
/ 05 сентября 2011

Я однажды написал статью в блоге о загрузке огромных файлов XML с помощью XMLReader - вы, вероятно, можете использовать некоторые из них.

Использование DOM или SimpleXML не допускается, поскольку оба загружают весь документ в память.

0 голосов
/ 22 июня 2017

Вы можете использовать DOMXpath для запросов, что намного быстрее, чем метод DOMDocument:: getElementsByTagName().

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

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

В одном из моих тестов с довольно большим файлом этот подход занял <1 сек.завершите итерацию 24k элементов, в то время как метод <code>DOMDocument:: getElementsByTagName() занимал ~ 27 мин (а время, необходимое для итерации до следующего объекта было экспоненциальным).

0 голосов
/ 04 сентября 2011

Вы не должны использовать объектную модель документа в больших 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;
}
...