Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SimpleXML Attributes to Array

Is there any more elegant way to escape SimpleXML attributes to an array?

$result = $xml->xpath( $xpath );
$element = $result[ 0 ];
$attributes = (array) $element->attributes();
$attributes = $attributes[ '@attributes' ];

I don't really want to have to loop through it just to extract the key/value pair. All I need is to get it into an array and then pass it on. I would have thought attributes() would have done it by default, or at least given the option. But I couldn't even find the above solution anywhere, I had to figure that out on my own. Am I over complicating this or something?

Edit:

I'm still using the above script until I know for sure whether accessing the @attributes array is safe or not.

like image 808
mseancole Avatar asked Jul 11 '12 19:07

mseancole


4 Answers

a more elegant way; it gives you the same results without using $attributes[ '@attributes' ] :

$attributes = current($element->attributes());
like image 160
silverskater Avatar answered Nov 04 '22 00:11

silverskater


Don't directly read the '@attributes' property, that's for internal use. Anyway, attributes() can already be used as an array without needing to "convert" to a real array.

For example:

<?php
$xml = '<xml><test><a a="b" r="x" q="v" /></test><b/></xml>';
$x = new SimpleXMLElement($xml);

$attr = $x->test[0]->a[0]->attributes();
echo $attr['a']; // "b"

If you want it to be a "true" array, you're gonna have to loop:

$attrArray = array();
$attr = $x->test[0]->a[0]->attributes();

foreach($attr as $key=>$val){
    $attrArray[(string)$key] = (string)$val;
}
like image 30
Rocket Hazmat Avatar answered Nov 03 '22 23:11

Rocket Hazmat


You could convert the whole xml document into an array:

$array = json_decode(json_encode((array) simplexml_load_string("<response>{$xml}</response>")), true);

For more information see: https://github.com/gaarf/XML-string-to-PHP-array

like image 42
Kus Avatar answered Nov 03 '22 22:11

Kus


For me below method worked

function xmlToArray(SimpleXMLElement $xml)
{
    $parser = function (SimpleXMLElement $xml, array $collection = []) use (&$parser) {
        $nodes = $xml->children();
        $attributes = $xml->attributes();

        if (0 !== count($attributes)) {
            foreach ($attributes as $attrName => $attrValue) {
                $collection['@attributes'][$attrName] = strval($attrValue);
            }
        }

        if (0 === $nodes->count()) {
            if($xml->attributes())
            {
                $collection['value'] = strval($xml);
            }
            else
            {
                $collection = strval($xml);
            }
            return $collection;
        }

        foreach ($nodes as $nodeName => $nodeValue) {
            if (count($nodeValue->xpath('../' . $nodeName)) < 2) {
                $collection[$nodeName] = $parser($nodeValue);
                continue;
            }

            $collection[$nodeName][] = $parser($nodeValue);
        }

        return $collection;
    };

    return [
        $xml->getName() => $parser($xml)
    ];
}

This also provides me all the attributes as well, which I didn't get from any other method.

like image 21
Manik Thakur Avatar answered Nov 04 '22 00:11

Manik Thakur