I'm parsing some XML with PHP DOM extension in order to store the data in some other form. Quite unsurprisingly, when I parse an element I pretty often need to obtain all children elements of some name. There is the method DOMElement::getElementsByTagName($name)
, but it returns all descendants with that name, not just immediate children. There is also the property DOMNode::$childNodes
but (1) it contains node list, not element list, and even if I managed to turn the list items into elements (2) I'd still need to check all of them for the name. Is there really no elegant solution to get only the children of some specific name or am I missing something in the documentation?
Some illustration:
<?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
?>
HTML DOM Element hasChildNodes() The hasChildNodes() method returns true if the specified node has any child nodes, otherwise false.
The children property returns a collection of an element's child elements.
simple iteration process
$parent = $p->parentNode;
foreach ( $parent->childNodes as $pp ) {
if ( $pp->nodeName == 'p' ) {
if ( strlen( $pp->nodeValue ) ) {
echo "{$pp->nodeValue}\n";
}
}
}
An elegant manner I can imagine would be using a FilterIterator
that is suitable for the job. Exemplary one that is able to work on such a said DOMNodeList
and (optionally) accepting a tagname to filter for as an exemplary DOMElementFilter
from the Iterator Garden does:
$a = $doc->getElementsByTagName('a')->item(0);
$bs = new DOMElementFilter($a->childNodes, 'b');
foreach($bs as $b){
echo $b->nodeValue . "\n";
}
This will give the results you're looking for:
1
2
You can find DOMElementFilter
in the Development branch now. It's perhaps worth to allow *
for any tagname as it's possible with getElementsByTagName("*")
as well. But that's just some commentary.
Hier is a working usage example online: https://eval.in/57170
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With