309 votes

Comment convertir un tableau en SimpleXML

Comment convertir un tableau en objet SimpleXML en PHP ?

6 votes

Un tableau de quoi ?

1 votes

4voto

Cakes Points 11

Vous pourriez utiliser le XMLParser sur lequel j'ai travaillé.

$xml = XMLParser::encode(array(
    'bla' => 'blub',
    'foo' => 'bar',
    'another_array' => array (
        'stack' => 'overflow',
    )
));
// @$xml instanceof SimpleXMLElement
echo $xml->asXML();

Aurait pour conséquence :

<?xml version="1.0"?>
<root>
    <bla>blub</bla>
    <foo>bar</foo>
    <another_array>
        <stack>overflow</stack>
    </another_array>
</root>

4voto

drzaus Points 3344

Sur la base de tout ce qui précède, les indices numériques et les attributs sont gérés en les préfixant avec @ et pourrait injecter du xml dans les nœuds existants :

Code

function simple_xmlify($arr, SimpleXMLElement $root = null, $el = 'x') {
    // based on, among others http://stackoverflow.com/a/1397164/1037948

    if(!isset($root) || null == $root) $root = new SimpleXMLElement('<' . $el . '/>');

    if(is_array($arr)) {
        foreach($arr as $k => $v) {
            // special: attributes
            if(is_string($k) && $k[0] == '@') $root->addAttribute(substr($k, 1),$v);
            // normal: append
            else simple_xmlify($v, $root->addChild(
                    // fix 'invalid xml name' by prefixing numeric keys
                    is_numeric($k) ? 'n' . $k : $k)
                );
        }
    } else {
        $root[0] = $arr;
    }

    return $root;
}//--   fn  simple_xmlify

Utilisation

// lazy declaration via "queryparam"
$args = 'hello=4&var[]=first&var[]=second&foo=1234&var[5]=fifth&var[sub][]=sub1&var[sub][]=sub2&var[sub][]=sub3&var[@name]=the-name&var[@attr2]=something-else&var[sub][@x]=4.356&var[sub][@y]=-9.2252';
$q = array();
parse_str($val, $q);

$xml = simple_xmlify($q); // dump $xml, or...
$result = get_formatted_xml($xml); // see below

Résultat

<?xml version="1.0"?>
<x>
  <hello>4</hello>
  <var name="the-name" attr2="something-else">
    <n0>first</n0>
    <n1>second</n1>
    <n5>fifth</n5>
    <sub x="4.356" y="-9.2252">
      <n0>sub1</n0>
      <n1>sub2</n1>
      <n2>sub3</n2>
    
  </var>
  <foo>1234</foo>
</x>

Bonus : Formatage du XML

function get_formatted_xml(SimpleXMLElement $xml, $domver = null, $preserveWhitespace = true, $formatOutput = true) {
    // http://stackoverflow.com/questions/1191167/format-output-of-simplexml-asxml

    // create new wrapper, so we can get formatting options
    $dom = new DOMDocument($domver);
    $dom->preserveWhiteSpace = $preserveWhitespace;
    $dom->formatOutput = $formatOutput;
    // now import the xml (converted to dom format)
    /*
    $ix = dom_import_simplexml($xml);
    $ix = $dom->importNode($ix, true);
    $dom->appendChild($ix);
    */
    $dom->loadXML($xml->asXML());

    // print
    return $dom->saveXML();
}//--   fn  get_formatted_xml

0 votes

Une version mise à jour qui répète les éléments enfants plutôt que les balises numériques : github.com/zaus/forms-3rdparty-xpost/blob/

3voto

Anthony Points 14424

Si le tableau est associatif et correctement codé, il serait probablement plus facile de le transformer d'abord en xml. Quelque chose comme :

function array2xml ($array_item) {
$xml = '';
foreach($array_item as $element => $value)
{
    if (is_array($value))
    {
        $xml .= "<$element>".array2xml($value)."</$element>";
    }
    elseif($value == '')
    {
        $xml .= "<$element />";
    }
    else
    {
        $xml .= "<$element>".htmlentities($value)."</$element>";
    }
}
return $xml;

}

$simple_xml = simplexml_load_string(array2xml($assoc_array));

L'autre solution consisterait à créer d'abord votre fichier xml de base, par exemple

$simple_xml = simplexml_load_string("<array></array>");

et ensuite, pour chaque partie de votre tableau, utilisez quelque chose de similaire à ma boucle de création de texte et utilisez plutôt les fonctions simplexml "addChild" pour chaque nœud du tableau.

Je vais essayer cela plus tard et mettre à jour ce post avec les deux versions.

0 votes

La partie où j'ai mentionné "<array></array>" m'a fait réaliser que la version string a besoin de quelque chose de similaire. En fait, le tableau doit avoir un nœud à l'extérieur. Laisse-moi réfléchir à tout ça, j'aurai quelque chose qui corrigera cette erreur initiale tout de suite.

3voto

mike Points 11

Voici une fonction qui a fait l'affaire pour moi :

Il suffit de l'appeler avec quelque chose comme

echo arrayToXml("response",$arrayIWantToConvert);
function arrayToXml($thisNodeName,$input){
        if(is_numeric($thisNodeName))
            throw new Exception("cannot parse into xml. remainder :".print_r($input,true));
        if(!(is_array($input) || is_object($input))){
            return "<$thisNodeName>$input</$thisNodeName>";
        }
        else{
            $newNode="<$thisNodeName>";
            foreach($input as $key=>$value){
                if(is_numeric($key))
                    $key=substr($thisNodeName,0,strlen($thisNodeName)-1);
                $newNode.=arrayToXml3($key,$value);
            }
            $newNode.="</$thisNodeName>";
            return $newNode;
        }
    }

3voto

caiofior Points 39

J'ai trouvé cette solution similaire au problème original

<?php

$test_array = array (
  'bla' => 'blub',
  'foo' => 'bar',
  'another_array' => array (
    'stack' => 'overflow',
  ),
);

class NoSimpleXMLElement extends SimpleXMLElement {
 public function addChild($name,$value) {
  parent::addChild($value,$name);
 }
}
$xml = new NoSimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X