PHP XMLReader получает родительский узел? - PullRequest
2 голосов
/ 05 февраля 2009

При синтаксическом анализе файла XML с использованием метода XMLReader, как получить родительский узел элемента?

$xml = new XMLReader();
$xml->XML($xmlString);
while($xml->read())
{

$xml->localName; // gives tag name
$xml->value; // gives tag value

// how do I access the parent of this element 
}

Ответы [ 3 ]

10 голосов
/ 05 февраля 2009

Короткая версия: По крайней мере, напрямую. Программист должен кодировать контекст в свой алгоритм синтаксического анализа с XMLReader.

Длинная версия: PHPReader XML - это то, что называется pull-парсер . Парсеры Pull отличаются от парсеров на основе дерева / домена тем, что они могут работать с текстовыми потоками. Другими словами, они могут начать анализ документа, прежде чем они получат весь документ. Это отличается от синтаксического анализатора на основе дерева / DOM, такого как SimpleXML или DOMDocument, который должен загрузить весь документ в память, прежде чем он сможет что-либо делать.

Преимущество заключается в том, что если у вас есть XML-файл размером 75 МБ, вам не требуется 75 МБ свободной оперативной памяти для его обработки (как если бы вы использовали синтаксический анализатор на основе дерева). Компромисс в том, что синтаксические парсеры никогда не имеют контекста всего документа. Единственный контекст имеет какой-либо узел, который они обрабатывают в данный момент.

Еще один способ думать об этом - парсер, основанный на дереве / домене, должен знать о каждой части документа, потому что он не знает, о чем вы его попросите. Тем не менее, вы и парсер pull сделали другое соглашение. Он будет продолжать бросать в вас узлы и предоставит вам возможность разобраться с их содержимым.

Вот пример кода, который (надеюсь) близок к тому, что вы ищете.

$xml = new XMLReader(); 
$xml->open('example.xml');
$last_node_at_depth = array();
while($xml->read())
{               
    //stash the XML of the entire node in an array indexed by depth
    //you're probably better off stashing exactly what you need from
    $last_node_at_depth[$xml->depth] = $xml->readOuterXML();

    $xml->localName; // gives tag name
    $xml->value;     // gives tag value     

    //so, right now we're at depth n in the XML document.  depth n-1 
    //would be our parent node
    if ($xml->depth > 0) {
        //gives the fragment that starts with the parent node       
        $last_node_at_depth[($xml->depth-1)];   
    }
}
1 голос
/ 06 февраля 2009

Я начал использовать функцию расширения () XMLReader. Это дает DOM представление текущего тега xml. Я использовал expand () на родительском узле, он дал мне элемент DOM родительского тега, затем с помощью обычного способа анализа DOMDocument () извлек дочерние значения.

//usage
$xml = new XMLReader();
$xml = $xml->XML($xmlResponse);
while($xml->read())
{
$parent = $xml->expand();

$firstChildValue = $parent->getElementsByTagName('child')->item(0)->nodeValue;
}

Использование функции расширения загружает только большую часть XML в память, а не загружает весь XML в память.

0 голосов
/ 05 февраля 2009

Я думаю, что вы хотите: XMLReader :: moveToElement

...