(PHP 5, PHP 7, PHP 8)
Represents a live list of nodes.
The number of nodes in the list. The range of valid child node indices is 0 tolength - 1 inclusive.
| Version | Description |
|---|---|
| 8.0.0 | DOMNodeList implementsIteratorAggregate now. Previously,Traversable was implemented instead. |
| 7.2.0 | TheCountable interface is implemented and returns the value of thelength property. |
Note: Nodes in the list can be accessed by array syntax.
If you want to recurse over a DOM then this might help:<?php/** * PHP's DOM classes are recursive but don't provide an implementation of * RecursiveIterator. This class provides a RecursiveIterator for looping over DOMNodeList */classDOMNodeRecursiveIteratorextendsArrayIteratorimplementsRecursiveIterator{ public function__construct(DOMNodeList $node_list) {$nodes= array(); foreach($node_listas$node) {$nodes[] =$node; }parent::__construct($nodes); } public functiongetRecursiveIterator(){ return newRecursiveIteratorIterator($this,RecursiveIteratorIterator::SELF_FIRST); } public functionhasChildren() { return$this->current()->hasChildNodes(); } public functiongetChildren() { return newself($this->current()->childNodes); } }?>In PHP 5.2.5 (Windows) it is not possible to iterate correctly over the DOMNodeList object returned by DOMNode->childNodes using foreach. Instead I had to use the for loop in conjunction with the item() method of DOMNodeList for iterating over all child nodes correctly.I don't know whether this is really a bug, but apparently it is.It's worth to mention that DOMNodeList is not an Array, so you have to convert first to an array before to use for, foreach or array_map, array_filter, array_walk functions.Use iterator_to_array to make the conversion ( since PHP 5.1.0 ) .<code> /* @ suppress warning var_dump not yet implemented for class */@array_walk( iterator_to_array( $Some_NodeList ), 'var_dump' ) );foreach( iterator_to_array( $Some_NodeList ) as $node ) @var_dump( $node );</code>Hope is usefull.Note that $length is calculated (php5.3.2).Iterating over a large NodeList may be time expensive.Prefer :$nb = $nodelist->length;for($pos=0; $pos<$nb; $pos++)Than:for($pos=0; $pos<$nodelist->length; $pos++)I had a hard time figuring that out...You can modify, and even delete, nodes from a DOMNodeList if you iterate backwards:$els = $document->getElementsByTagName('input');for ($i = $els->length; --$i >= 0; ) { $el = $els->item($i); switch ($el->getAttribute('name')) { case 'MAX_FILE_SIZE' : $el->parentNode->removeChild($el); break; case 'inputfile' : $el->setAttribute('type', 'text'); //break; }}I have done some testing and have found 2 results:(My System: Win XP with PHP 5.2.1)1) Iteration with foreach does function correctly as "james dot j dot hackett at gmail dot com" writes, _if_ you only do readonly stuff with foreach or minor writings of some attributes.2) foreach does not function, if you are doing some DOM-Operations while iterating. In my situation it was adding the iterated $node as an child to an new node:$newNode = $dom->createElement('newNode') ;foreach ($nodeList as $node) { echo $node->nodeValue ; $newNode->appendChild($node) ;}This only gives you the first element ...I'm interpreting it as an confusing but correct behavior because of the changes within the $dom-object while appending the node at an additional place ... So, if you want to do something like 2) use for, length and item() :)In Response to 'kassah at gmail'You don't need to convert a DOMNodeList to an array in order iterate through it using 'foreach'. You can use foreach directly with the DOMNodeList.$nodeList = $someDomDocument->getElementsbytagname('user');foreach ($nodeList as $node) { echo $node->nodeValue;}That's actually incorrect. You can use function results as objects. It makes building an API for your database very clean and neat. For example:Our code:$articles = Node::screate('tags', 123456)->assets('like:title:test')->articles;We use the above code to get articles that are linked to assets that are linked to a specific tag in our database.Addition to my first note:An traditional for-loop does not allow you to change the DOM-tree while looping - the effects are the nearly the same as with foreach. So you have to collect the nodes in an array and do the tree-altering stuff within a second loop (looping the array this time ...)