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 c
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
My solution used in a production:
Finds a needle (node) in a haystack (DOM)
function getAttachableNodeByAttributeName(\DOMElement $parent = null, string $elementTagName = null, string $attributeName = null, string $attributeValue = null)
{
$returnNode = null;
$needleDOMNode = $parent->getElementsByTagName($elementTagName);
$length = $needleDOMNode->length;
//traverse through each existing given node object
for ($i = $length; --$i >= 0;) {
$needle = $needleDOMNode->item($i);
//only one DOM node and no attributes specified?
if (!$attributeName && !$attributeValue && 1 === $length) return $needle;
//multiple nodes and attributes are specified
elseif ($attributeName && $attributeValue && $needle->getAttribute($attributeName) === $attributeValue) return $needle;
}
return $returnNode;
}
Usage:
$countryNode = getAttachableNodeByAttributeName($countriesNode, 'country', 'iso', 'NL');
Returns DOM element from parent countries node by specified attribute iso
using country ISO code 'NL', basically like a real search would do. Find a certain country by it's name in an array / object.
Another usage example:
$productNode = getAttachableNodeByAttributeName($products, 'partner-products');
Returns DOM node element containing only single (root) node, without searching by any attribute.
Note: for this you must make sure that root nodes are unique by elements' tag name, e.g. countries->country[ISO]
- countries
node here is unique and parent to all child nodes.
simple iteration process
$parent = $p->parentNode;
foreach ( $parent->childNodes as $pp ) {
if ( $pp->nodeName == 'p' ) {
if ( strlen( $pp->nodeValue ) ) {
echo "{$pp->nodeValue}\n";
}
}
}