3

I have the following XML saved in $string

<?xml version="1.0" encoding="ISO-8859-1"?>
<users>
  <user id="1">
    <name>Michael Tray</name>
    <account>473.43</account>
  </user>
  <user id="2">
    <name>Sandra Marry</name>
    <account>154.24</account>
  </user>
</users>

I use the following simple XPath expression to get all names

$xml = simplexml_load_string($string);
$result = $xml->xpath("/users/user/name");
echo "<pre>";
print_r($result);
echo "</pre>";

What I get

Array (
    [0] => SimpleXMLElement Object
        (
            [0] => Michael Tray
        )

    [1] => SimpleXMLElement Object
        (
            [0] => Sandra Marry
        )
)

What I want

Array (
    [0] => SimpleXMLElement Object
        (
            [name] => Michael Tray
        )

    [1] => SimpleXMLElement Object
        (
            [name] => Sandra Marry
        )
)

So the SimpleXMLElement key should be a string (tag name) and not a number. How can I do that?

Christian Vorhemus
  • 2,396
  • 1
  • 17
  • 29
  • Why did you think the key should be a string (tag name)? (just curious, could also add some useful context to your question) – hakre Mar 25 '15 at 17:14

1 Answers1

2

As usual with SimpleXML, print_r is lying to you. The objects don't really have a "key" of 0 at all.

Each object actually represent a single XML element, and you can access the tag name using getName(), and the string content with a (string) cast, as follows:

foreach ( $result as $node ) {
    echo 'Name: ', $node->getName(), '; ';
    echo 'Content: ', (string)$node, '<br />';
}

(The (string) is actually redundant with echo, because it forces things to string anyway, but is important to remember anywhere else to avoid passing around the whole object by mistake.)

IMSoP
  • 89,526
  • 13
  • 117
  • 169
  • Thanks, that's helpful! – Christian Vorhemus Mar 25 '15 at 15:49
  • Actually it does have a "key" of 0. More correctly every **SimpleXMLElement** which represents an *existing* node in the document does have. Just saying, that `print_r` is lying is totally true :) – hakre Mar 25 '15 at 17:15
  • @hakre True, you can access `$node[0]`; and because that just returns itself, you can also access `$node[0][0]` and `$node[0][0][0]`, and `$node[0][0][0][0]`... – IMSoP Mar 25 '15 at 17:24
  • 1
    Yes, that's what I often call the SimpleXMLElement self-reference. Useful for example to [delete the node itself. E.g. with an xpath result](http://stackoverflow.com/q/2442314/367456). – hakre Mar 25 '15 at 17:33