32

I have an XML file loaded into a DOM document, I wish to iterate through all 'foo' tags, getting values from every tag below it. I know I can get values via

$element = $dom->getElementsByTagName('foo')->item(0);
foreach($element->childNodes as $node){
    $data[$node->nodeName] = $node->nodeValue;
}

However, what I'm trying to do, is from an XML like,

<stuff>
  <foo>
    <bar></bar>
      <value/>
    <pub></pub>
  </foo>
  <foo>
    <bar></bar>
    <pub></pub>
  </foo>
  <foo>
    <bar></bar>
    <pub></pub>
  </foo>
  </stuff>

iterate over every foo tag, and get specific bar or pub, and get values from there. Now, how do I iterate over foo so that I can still access specific child nodes by name?

hakre
  • 193,403
  • 52
  • 435
  • 836
Esa
  • 1,121
  • 2
  • 15
  • 23

4 Answers4

45

Not tested, but what about:

$elements = $dom->getElementsByTagName('foo');
$data = array();
foreach($elements as $node){
    foreach($node->childNodes as $child) {
        $data[] = array($child->nodeName => $child->nodeValue);
    }
}
roryf
  • 29,592
  • 16
  • 81
  • 103
4

It's generally much better to use XPath to query a document than it is to write code that depends on knowledge of the document's structure. There are two reasons. First, there's a lot less code to test and debug. Second, if the document's structure changes it's a lot easier to change an XPath query than it is to change a bunch of code.

Of course, you have to learn XPath, but (most of) XPath isn't rocket science.

PHP's DOM uses the xpath_eval method to perform XPath queries. It's documented here, and the user notes include some pretty good examples.

Robert Rossney
  • 94,622
  • 24
  • 146
  • 218
2

Here's another (lazy) way to do it.

$data[][$node->nodeName] = $node->nodeValue;
Chris
  • 5,882
  • 2
  • 32
  • 57
-2

With FluidXML you can query and iterate XML very easly.

$data = [];

$store_child = function($i, $fooChild) use (&$data) {
    $data[] = [ $fooChild->nodeName => $fooChild->nodeValue ];
};

fluidxml($dom)->query('//foo/*')->each($store_child);

https://github.com/servo-php/fluidxml

Daniele Orlando
  • 2,692
  • 3
  • 23
  • 26