The DOMNodeList class

(PHP 5, PHP 7, PHP 8)

Class synopsis

class DOMNodeList implements IteratorAggregate, Countable {
/* Properties */
public readonly int $length;
/* Methods */
public count(): int
}

Properties

length

The number of nodes in the list. The range of valid child node indices is 0 to length - 1 inclusive.

Changelog

Version Description
8.0.0 DOMNodeList implements IteratorAggregate now. Previously, Traversable was implemented instead.
7.2.0 The Countable interface is implemented and returns the value of the length property.

Table of Contents

add a note

User Contributed Notes 9 notes

up
26
ignitedfirestarter at gmail dot com
12 years ago
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
*/
class DOMNodeRecursiveIterator extends ArrayIterator implements RecursiveIterator {

public function
__construct (DOMNodeList $node_list) {

$nodes = array();
foreach(
$node_list as $node) {
$nodes[] = $node;
}

parent::__construct($nodes);

}

public function
getRecursiveIterator(){
return new
RecursiveIteratorIterator($this, RecursiveIteratorIterator::SELF_FIRST);
}

public function
hasChildren () {
return
$this->current()->hasChildNodes();
}


public function
getChildren () {
return new
self($this->current()->childNodes);
}

}
?>
up
13
geompse at gmail dot com
14 years ago
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...
up
11
brack at wjp dot de
16 years ago
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.
up
14
c dot 1 at smithies dot org
16 years ago
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;
}
}
up
11
drichter at muvicom dot de
16 years ago
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() :)
up
3
niko at yopmail dot com
3 years ago
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.
up
6
james dot j dot hackett at gmail dot com
16 years ago
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;
}
up
1
bobvandell at hotmail dot com
16 years ago
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.
up
-2
drichter at muvicom dot de
16 years ago
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 ...)
To Top