简体   繁体   中英

Accessing a specific XML-node with PHP using SimpleXML

lately i ran into a problem using simplexml. What i want to do is to get a value of a nested node that occurs multiple times. The xml looks somewhat like this:

<response>
  <album id="123">
  [...]
    <duration>
      <value format="seconds">2576</value>
      <value format="mm:ss">42:56</value>
      <value format="hh:mm:ss">00:42:56</value>
      <value format="xs:duration">PT42M56S</value>
    </duration>
  [...]
  </album>
</response>

Specifically i need the value of the the <value format="hh:mm:ss"> node.

So I have a reference to the object that looks somewhat like this:

$this->webservice->album->duration->value;

Now, if i var_dump this the result will be:

object(SimpleXMLElement)#117 (5) { 
  ["@attributes"]=> array(1) { 
    ["format"]=> string(7) "seconds" 
  } 
  [0]=> string(4) "2576" 
  [1]=> string(5) "42:56" 
  [2]=> string(8) "00:42:56" 
  [3]=> string(8) "PT42M56S" 
}

I do not understand this output, since it takes the format-attribute of the first node (seconds) and continues with the node-values in the array, while ignoring the format-attribute of the following nodes completely.

Furthermore, if i do the following:

$this->webservice->album->duration->value[2];

it results in:

object(SimpleXMLElement)#108 (1) { 
  ["@attributes"]=> array(1) { 
    ["format"]=> string(8) "hh:mm:ss" 
  } 
}

where i haven't got a value to address at all.

I tried to use xpath instead too in the following way:

$this->webservice->album->duration->xpath('value[@format="hh:mm:ss"]');

which results in:

array(1) { 
  [0]=> object(SimpleXMLElement)#116 (1) { 
    ["@attributes"]=> array(1) { 
      ["format"]=> string(8) "hh:mm:ss" 
    } 
  } 
}

So my question is: What am I doing wrong? xD

Thanks in advance for any helpful advice :)

Your mistake is in trusting var_dump too completely, rather than trying to use the elements based on the examples in the manual .

On your first attempt, you accessed $duration_node->value ; this can be used in a few different ways:

  • if you iterate over it with foreach($duration_node->value as $value_node) , you get each of the <value> elements in turn
  • you can access specific elements by index, eg $duration_node->value[2] for the 3rd element
  • if you treat it as a single element, SimpleXML assumes you want the first element, ie echo $duration_node->value is the same as echo $duration_node->value[0]

Your second example worked fine - it found the <value> element with an attribute format="hh:mm:ss" . The xpath() method always returns an array, so you need to check that it's not empty then look at the first element.

Once you have the right element, accessing its text content is as simple as casting it to a string ( (string)$foo ), or passing it to something that always needs a string (eg echo ).

So this would work:

$xpath_results = $this->webservice->album->duration->xpath('value[@format="hh:mm:ss"]');
if ( count($xpath_results) != 0 ) {
    $value = (string)$xpath_results[0];
}

As would this:

foreach ( $this->webservice->album->duration->value as $value_node ) {
    if ( $value_node['format'] == 'hh:mm:ss' ) {
        $value = (string)$value_node;
        break;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM