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

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

Вы не должны использовать Document Object Model на больших 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; } 

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

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

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

 <?php $xpath = new \DOMXpath($dom); $games = $xpath->query("//game"); foreach ($games as $game) { // Code here } 

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