PHP DOM: Как получить дочерние элементы по имени тега элегантным способом?

Я разбираю XML с расширением PHP DOM, чтобы хранить данные в другой форме. Совершенно неудивительно, когда я разбираю элемент, мне довольно часто нужно получить все дочерние элементы какого-то имени. Существует метод DOMElement::getElementsByTagName($name) , но он возвращает всех потомков с этим именем, а не только непосредственно детей. Существует также свойство DOMNode::$childNodes но (1) оно содержит список узлов, а не список элементов, и даже если мне удалось превратить элементы списка в элементы (2), мне все равно нужно будет проверить все их для имя. Неужели нет элегантного решения, чтобы получить только детей определенного имени или я чего-то не хватает в документации?

Некоторые иллюстрации:

 <?php DOMDocument(); $document->loadXML(<<<EndOfXML <a> <b>1</b> <b>2</b> <c> <b>3</b> <b>4</b> </c> </a> EndOfXML ); $bs = $document ->getElementsByTagName('a') ->item(0) ->getElementsByTagName('b'); foreach($bs as $b){ echo $b->nodeValue . "\n"; } // Returns: // 1 // 2 // 3 // 4 // I'd like to obtain only: // 1 // 2 ?> 

Элегантная манера, которую я могу себе представить, будет использовать FilterIterator , подходящий для работы. Примерный, который способен работать над таким упомянутым DOMNodeList и (необязательно) принимать тэг для фильтрации в качестве примерного DOMElementFilter из Iterator Garden :

 $a = $doc->getElementsByTagName('a')->item(0); $bs = new DOMElementFilter($a->childNodes, 'b'); foreach($bs as $b){ echo $b->nodeValue . "\n"; } 

Это даст результаты, которые вы ищете:

 1 2 

DOMElementFilter вы можете найти DOMElementFilter в ветке разработки . Возможно, стоит разрешить * для любого тэга, как это возможно, с getElementsByTagName("*") . Но это лишь некоторые комментарии.

Hier – пример рабочего использования онлайн: https://eval.in/57170

простой процесс итерации

  $parent = $p->parentNode; foreach ( $parent->childNodes as $pp ) { if ( $pp->nodeName == 'p' ) { if ( strlen( $pp->nodeValue ) ) { echo "{$pp->nodeValue}\n"; } } }