Reputation: 569
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 :)
Upvotes: 0
Views: 209
Reputation: 97718
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:
foreach($duration_node->value as $value_node)
, you get each of the <value>
elements in turn$duration_node->value[2]
for the 3rd elementecho $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 (e.g. 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;
}
}
Upvotes: 2