Reputation: 13
I'm following this tutorial:
Looping through XML part is problematic. PHP for some reason treats DOM object as an array. Furthermore, var_dump returns nothing about object attributes except length, but program output looks like it came out of nowhere. Can foreach loop through object somehow ? And if it does, where are these attributes contained (node name and node value) because var_dump is not showing them ?
$xml=new DOMDocument ();
$xml->load('note.xml');
$array_of_nodes=$xml->documentElement->childNodes;
var_dump($array_of_nodes);
foreach($array_of_nodes as $item) {
echo $item->nodeName." ".$item->nodeValue."<br>";
}
Var dump function returns this:
object(DOMNodeList)#3 (1) { ["length"]=> int(9) } #text
But the executed code look like this:
text =
to = Tove
text =
from = Jani
text =
heading = Reminder
text =
body = Don't forget me this weekend!
text =
Upvotes: 1
Views: 430
Reputation: 83
childNodes
is a property of DOMNodeList
type. The reason why var_dump doesn't show anything about it is simply because var_dump shows only those class properties that have been declared by their developers by calling such C-functions as
ZEND_API int zend_declare_property(...)
ZEND_API int zend_declare_property_null(...)
ZEND_API int zend_declare_property_bool(...)
ZEND_API int zend_declare_property_long(...)
ZEND_API int zend_declare_property_double(...)
ZEND_API int zend_declare_property_string(...)
ZEND_API int zend_declare_property_stringl(...)
Source: answer by akond: Why doesn't var_dump work with DomDocument objects, while print($dom->saveHTML()) does?
That is, developers of DOM extension chose not to expose the structure of DOMNodeList
class.
The reason why you can iterate through DOMNodeList
is because it implements Traversable
interface which signals that the class can be iterated through by using foreach
.
Upvotes: 1
Reputation: 19502
DOMNodeList
implements several interfaces: Traversable
, ArrayAccess
and Countable
. This allows using generic syntax to access the node objects in the list. Without them you would need to use specific methods and properties like this:
for ($i = 0; $c = $nodeList->length; $i < $c; $i++) {
$node = $nodeList->item($i);
//...
}
Traversable
allows you to use foreach
.
foreach ($nodeList as $node) {
//...
}
ArrayAccess
allows you use array syntax to access nodes by index, it replaces the ->item(...)
calls with [...]
.
if (isset($nodeList[0])) {
$node = $nodeList[0];
//...
}
Countable
allows you use count($nodeList)
instead of $nodeList->length
.
Traversable
has the most visual impact. It greatly reduces the complexity of the call. But that is only the first benefit. You can validate against the interfaces using typehints or instanceof
. This decouples you code, making it more robust and reusable.
However looping trough DOM is a lot easier if you use Xpath expressions. If you used CSS selectors before, you can think of Xpath expressions as a more powerful sibling.
$document = new DOMDocument();
$document->load('note.xml');
$xpath = DOMXpath($document);
foreach($xpath->evaluate('/note') as $item) {
echo 'To: ', $xpath->evaluate('string(to)', $item), "\n";
echo 'From: ', $xpath->evaluate('string(from)', $item), "\n";
echo 'Title: ', $xpath->evaluate('string(heading)', $item), "\n";
echo 'Text: ', $xpath->evaluate('string(body)', $item), "\n";
}
Upvotes: 1