PHP DOMElement :: getElementsByTagName – В любом случае, чтобы получить сразу же подходящих детей?

есть способ получить только немедленных детей, найденных при вызове DOMElement :: getElementsByTagName? Например, у меня есть документ XML, который имеет элемент категории. Этот элемент категории имеет элементы подкатегории (которые имеют одинаковую структуру), например:

<category> <id>1</id> <name>Top Level Category Name</name> <subCategory> <id>2</id> <name>Sub Category Name</name> </subCategory> ... </category> 

Если у меня есть DOMElement, представляющий категорию верхнего уровня,

 $topLevelCategoryElement->getElementsByTagName('id'); 

вернет список с узлами для всех элементов «id», где я хочу только один из верхнего уровня. Любой способ сделать это за пределами использования XPath?

Боюсь, что нет. Вам придется проходить через детей или использовать XPath.

 for ($n = $parent->firstChild; $n !== null; $n = $n->nextSibling) { if ($n instanceof DOMElement && $n->tagName == "xxx") { //... } } 

Пример с XPath и вашим XML-файлом:

 $xml = ...; $d = new DOMDocument(); $d->loadXML($xml); $cat = $d->getElementsByTagName("subCategory")->item(0); $xp = new DOMXpath($d); $q = $xp->query("id", $cat); //note the second argument echo $q->item(0)->textContent; 

дает 2 .

Что-то вроде этого должно делать

 /** * Traverse an elements children and collect those nodes that * have the tagname specified in $tagName. Non-recursive * * @param DOMElement $element * @param string $tagName * @return array */ function getImmediateChildrenByTagName(DOMElement $element, $tagName) { $result = array(); foreach($element->childNodes as $child) { if($child instanceof DOMElement && $child->tagName == $tagName) { $result[] = $child; } } return $result; } 

edit : добавлен экземпляр проверки DOMElement

Я не использую PHP, но если PHP на самом деле реализует DOM API, как указано в W3C , для любого объекта Node требуется свойство childNodes. Вы должны иметь возможность перебирать всех прямых детей и тестировать их имя тега, чтобы узнать, является ли он тем, кого вы ищете. В зависимости от того, как выглядит ваше дерево, это может быть медленнее, чем получение всех элементов по имени тегов и проверка их позиции в дереве, или это может быть значительно быстрее.

Вы можете сравнивать элементы с помощью ===. Это позволит избежать создания экземпляра объекта Xpath.

 $dom = new DOMDocument(); $dom->loadXML($xmlString); $return = array(); //find your top level element $topLevelElement = $dom->getElementsByTagName('category'); //find all `id` child elements recursively $idElements = $topLevelElement->getElementsByTagName('id'); if ($idElements->length > 0) { foreach ($idElements as $idElement) { if ($idElement->parentNode === $topLevelElement) { $return[] = $idElement; } } } //$return now holds non nested child elements 

В зависимости от размера вашего документа XML вы можете обнаружить, что Xpath работает лучше. Однако с точки зрения элегантности это решение является более чистым.