web-dev-qa-db-fra.com

Attributs SimpleXML à un tableau

Existe-t-il un moyen plus élégant d'échapper aux attributs SimpleXML d'un tableau?

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

Je ne veux pas vraiment avoir à le parcourir en boucle pour extraire le couple clé/valeur. Tout ce dont j'ai besoin, c'est de le placer dans un tableau, puis de le transmettre. J'aurais pensé que attributes() l'aurait fait par défaut, ou du moins s'il avait eu l'option. Mais je ne pouvais même pas trouver la solution ci-dessus nulle part, je devais le résoudre moi-même. Est-ce que je complique exagérément ceci ou quelque chose?

Modifier:

J'utilise toujours le script ci-dessus jusqu'à ce que je sache avec certitude si l'accès au tableau @attributes est sécurisé ou non.

21
mseancole

Ne lisez pas directement la propriété '@attributes', elle est à usage interne. Quoi qu'il en soit, attributes() peut déjà être utilisé comme un tableau sans avoir besoin de "convertir" en un tableau réel.

Par exemple:

<?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"

Si vous voulez que ce soit un "vrai" tableau, vous devrez boucler:

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

foreach($attr as $key=>$val){
    $attrArray[(string)$key] = (string)$val;
}
11
Rocket Hazmat

une manière plus élégante; il vous donne les mêmes résultats sans utiliser $ attributs ['@attributes'] :

$attributes = current($element->attributes());
45
silverskater

Vous pouvez convertir le document XML entier dans un tableau:

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

Pour plus d'informations, voir: https://github.com/gaarf/XML-string-to-PHP-array

2
Kus

Pour moi, la méthode ci-dessous a fonctionné

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)
    ];
}

Cela me fournit également tous les attributs, que je n’ai obtenus d’aucune autre méthode.

0
Manik Thakur

Je pense que vous devrez faire une boucle. Vous pouvez l'obtenir dans un tableau une fois que vous avez lu xml.

<?php
function objectsIntoArray($arrObjData, $arrSkipIndices = array())
{
$arrData = array();

// if input is object, convert into array
if (is_object($arrObjData)) {
    $arrObjData = get_object_vars($arrObjData);
}

if (is_array($arrObjData)) {
    foreach ($arrObjData as $index => $value) {
        if (is_object($value) || is_array($value)) {
            $value = objectsIntoArray($value, $arrSkipIndices); // recursive call
        }
        if (in_array($index, $arrSkipIndices)) {
            continue;
        }
        $arrData[$index] = $value;
    }
}
return $arrData;
}

$xmlStr = file_get_contents($xml_file);
$xmlObj = simplexml_load_string($xmlStr);
$arrXml = objectsIntoArray($xmlObj);

foreach($arrXml as $attr)
  foreach($attr as $key->$val){
 if($key == '@attributes') ....
}
0
PoX