Write a recursive function to traverse the XML document tree:
- <?php
- // create XML data string
- $xmlData =<<< END
- <?xml version="1.0"?>
- <movie>
- <title>The Matrix</title>
- <credits>
- <actor>
- <name>Keanu Reeves</name>
- <character>Neo</character>
- </actor>
- <actor>
- <name>Laurence Fishburne</name>
- <character>Morpheus</character>
- </actor>
- <actor>
- <name>Carrie-Anne Moss</name>
- <character>Trinity</character>
- </actor>
- <director>
- <name>Andy Wachowski</name>
- </director>
- <director>
- <name>Larry Wachowski</name>
- </director>
- </credits>
- <year>1999</year>
- <duration units="min">120</duration>
- </movie>
- END;
- // read XML data
- $xml = simplexml_load_string($xmlData)↩
- or die("ERROR: Cannot create SimpleXML object");
- // function to recursively iterate over XML tree
- // printing node names and values
- function xmlTraverse($node) {
- foreach ($node->children() as $name => $data) {
- if (trim($data) != "") {
- echo "$name: [$data, " . strlen($data) . "]/n";
- }
- xmlTraverse($data);
- }
- }
- // traverse XML tree
- // result: "title: [The Matrix, 10] name: [Keanu Reeves, 12] …"
- xmlTraverse($xml);
- ?>
Comments
Because an XML document is a hierarchical tree of nested elements, the most efficient way to process it is with a recursive function that calls itself to traverse the entire tree. This is the technique illustrated in the previous listing.
The recursive xmlTraverse() function begins with the root element and looks for children with SimpleXML's children() function. If children exist, the function loops over the child list, repeatedly calling itself to process each node until it reaches the end of the list. The process continues until no further nodes remain to be processed. At each stage, the current node name and value are printed.
Alternatively, consider using an Iterator from the Standard PHP Library (SPL). Iterators are ready-made, extensible constructs designed specifically to loop over item collections—directories, files, class methods, and XML trees. A predefined SimpleXMLIterator already exists and it's not difficult to extend this for recursive array processing. Here's how:
- <?php
- // create XML data string
- $xmlData =<<< END
- <?xml version="1.0"?>
- <movie>
- <title>The Matrix</title>
- <credits>
- <actor>
- <name>Keanu Reeves</name>
- <character>Neo</character>
- </actor>
- <actor>
- <name>Laurence Fishburne</name>
- <character>Morpheus</character>
- </actor>
- <actor>
- <name>Carrie-Anne Moss</name>
- <character>Trinity</character>
- </actor>
- <director>
- <name>Andy Wachowski</name>
- </director>
- <director>
- <name>Larry Wachowski</name>
- </director>
- </credits>
- <year>1999</year>
- <duration units="min">120</duration>
- </movie>
- END;
- // read XML data
- $xml = simplexml_load_string($xmlData, "SimpleXMLIterator")↩
- or die("ERROR: Cannot create SimpleXML object");
- // recursively iterate over XML tree
- foreach(new RecursiveIteratorIterator($xml, true) as $name => $data)
- {
- if (trim($data) != "") {
- echo "$name: [$data, " . strlen($data) . "]/n";
- }
- }
- ?>
The process of traversing a series of nested directories is significantly simpler with the SPL at hand. First, initialize a SimpleXMLIterator() object and pass it the XML tree to be processed. Next, initialize a RecursiveIteratorIterator() object (this is an Iterator designed solely for the purpose of iterating over other recursive Iterators) and pass it the newly-minted SimpleXMLIterator(). You can now process the results with a foreach() loop.
You can read more about the SimpleXMLIterator and the RecursiveIteratorIterator http://www.php.net/~helly/php/ext/spl/.