2009-02-04 4 views
2

При анализе XML-файла с использованием метода XMLReader, как получить родительский узел элемента?PHP 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 
} 

ответ

9

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

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

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

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

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

$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

«Если у вас есть 75-мегабайтный XML-файл, вам не нужен 75 МБ свободной оперативной памяти», это утверждение может быть немного ошибочным. Вам все равно потребуется 75 МБ ОЗУ, если вы используете функцию 'file_get_contents' в большом файле размером 75 МБ. На самом деле, используя DOMDocument, вам понадобится гораздо больше 75 МБ. –

+0

. Вместо этого вы должны использовать '$ xml-> open ('example.xml');'! –

+0

@Petr Я понятия не имею, о чем я думал в 2009 году. Спасибо за исправление! –

1

Я начал использовать функцию expand() 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; 
} 

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

+0

Я тоже использую этот подход, так как это намного проще, чем использование XMLReader для чтения всего документа, но это довольно медленно. – julio