So konvertieren Sie ein Array in SimpleXML


Antworten:


209

eine kurze:

<?php

$test_array = array (
  'bla' => 'blub',
  'foo' => 'bar',
  'another_array' => array (
    'stack' => 'overflow',
  ),
);
$xml = new SimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();

führt zu

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

Schlüssel und Werte werden vertauscht - Sie können dies array_flip()vor dem array_walk beheben. array_walk_recursiveerfordert PHP 5. Sie könnten array_walkstattdessen verwenden, aber Sie werden dann nicht 'stack' => 'overflow'in die XML bekommen.


53
Dies funktioniert nicht, wenn $ test_array 'more_another_array' wie 'another_array' hat, da der Schlüssel 'another_array' nicht konvertiert wird. Daher haben Sie mehrere '<Überlauf> Stapel </ Überlauf>'.
Understack

11
Das array_flipfunktioniert nicht, da es keine Arrays umdrehen kann (wie das another_arrayInnere des Haupt-Arrays).
Lode

14
Wo ist das XML-Element "another_array"? Alles ist abgeflacht :(
FMaz008

2
Hat super funktioniert, als ich array_flip vor array_walk_recursive hinzugefügt habe. Vielen Dank.
Mike Purcell

12
Downvoting, weil array_flipnur funktioniert, wenn das Array keine identischen Werte enthält.
Martijn

385

Hier ist PHP 5.2 Code, der Arrays beliebiger Tiefe in XML-Dokumente konvertiert:

Array
(
    ['total_stud']=> 500
    [0] => Array
        (
            [student] => Array
                (
                    [id] => 1
                    [name] => abc
                    [address] => Array
                        (
                            [city]=>Pune
                            [zip]=>411006
                        )                       
                )
        )
    [1] => Array
        (
            [student] => Array
                (
                    [id] => 2
                    [name] => xyz
                    [address] => Array
                        (
                            [city]=>Mumbai
                            [zip]=>400906
                        )   
                )

        )
)

generiertes XML wäre wie folgt:

<?xml version="1.0"?>
<student_info>
    <total_stud>500</total_stud>
    <student>
        <id>1</id>
        <name>abc</name>
        <address>
            <city>Pune</city>
            <zip>411006</zip>
        </address>
    </student>
    <student>
        <id>1</id>
        <name>abc</name>
        <address>
            <city>Mumbai</city>
            <zip>400906</zip>
        </address>
    </student>
</student_info>

PHP-Snippet

<?php
// function defination to convert array to xml
function array_to_xml( $data, &$xml_data ) {
    foreach( $data as $key => $value ) {
        if( is_array($value) ) {
            if( is_numeric($key) ){
                $key = 'item'.$key; //dealing with <0/>..<n/> issues
            }
            $subnode = $xml_data->addChild($key);
            array_to_xml($value, $subnode);
        } else {
            $xml_data->addChild("$key",htmlspecialchars("$value"));
        }
     }
}

// initializing or creating array
$data = array('total_stud' => 500);

// creating object of SimpleXMLElement
$xml_data = new SimpleXMLElement('<?xml version="1.0"?><data></data>');

// function call to convert array to xml
array_to_xml($data,$xml_data);

//saving generated xml file; 
$result = $xml_data->asXML('/file/path/name.xml');

?>

Dokumentation zur SimpleXMLElement::asXMLVerwendung in diesem Snippet


40
Dies, IMO, ist eine viel bessere Lösung als die akzeptierte Antwort. Dies hat jedoch die Einschränkung, dass bei numerisch verschlüsselten Arrays fehlerhaftes XML generiert wird. <0> <1> <2> sind keine gültigen Knotennamen.
KOGI

2
Wenn Ihr Array mit numerischen Schlüsseln jedoch nur ein anderes Array enthält, das nicht mit numerischen Schlüsseln versehen ist, wird dies nicht der Fall sein.
Bryan Petty

15
@ KOGI Ich habe Hanmant Antwort geändert. Jetzt unterstützt es mehrstufige Arrays. pastebin.com/pYuXQWee
Mifas

1
In diesem Beispiel werden Sonderzeichen in Elementtextdaten mithilfe von htmlspecialchars explizit umgangen, aber SimpleXMLElement :: addChild übersetzt XML-Sonderzeichen automatisch in ihre Zeichenentitäten, sodass htmlspecialchars weggelassen werden können. Interessanterweise scheint dies nicht zu doppelt entkommenen Daten zu führen.
mbaynton

3
@Alex, Ihre Bearbeitung Nr. 5 lässt das Beispiel fehlschlagen. Vor jedem <student> -Datensatz wird <item $ x> eingefügt, sodass die XML-Ausgabe nicht den vom Autor beabsichtigten entspricht. Geben Sie möglicherweise ein Beispiel für das Problem, das Sie beheben möchten, und wir können für beide Fälle eine andere Lösung finden. Es dauerte eine Weile, bis mir klar wurde, dass der Code des Autors geändert wurde.
Nicholas Blasgen

124

Die hier bereitgestellten Antworten konvertieren Array nur mit Knoten in XML. Sie können keine Attribute festlegen. Ich habe eine PHP-Funktion geschrieben, mit der Sie ein Array in PHP konvertieren und Attribute für bestimmte Knoten in der XML festlegen können. Der Nachteil hier ist, dass Sie ein Array auf eine bestimmte Weise mit wenigen Konventionen erstellen müssen (nur wenn Sie Attribute verwenden möchten).

Im folgenden Beispiel können Sie Attribute auch in XML festlegen.

Die Quelle finden Sie hier: https://github.com/digitickets/lalit/blob/master/src/Array2XML.php

<?php    
$books = array(
    '@attributes' => array(
        'type' => 'fiction'
    ),
    'book' => array(
        array(
            '@attributes' => array(
                'author' => 'George Orwell'
            ),
            'title' => '1984'
        ),
        array(
            '@attributes' => array(
                'author' => 'Isaac Asimov'
            ),
            'title' => 'Foundation',
            'price' => '$15.61'
        ),
        array(
            '@attributes' => array(
                'author' => 'Robert A Heinlein'
            ),
            'title' => 'Stranger in a Strange Land',
            'price' => array(
                '@attributes' => array(
                    'discount' => '10%'
                ),
                '@value' => '$18.00'
            )
        )
    )
);
/* creates 
<books type="fiction">
  <book author="George Orwell">
    <title>1984</title>
  </book>
  <book author="Isaac Asimov">
    <title>Foundation</title>
    <price>$15.61</price>
  </book>
  <book author="Robert A Heinlein">
    <title>Stranger in a Strange Land</title>
    <price discount="10%">$18.00</price>
  </book>
</books>
*/
?>

9
Ich habe vermutet, dass niemand darauf reagiert hat. Diese Klasse ist wirklich nützlich, da sie das Gegenteil von dem tut, was simpleXMLElement generiert. So haben Sie die Möglichkeit, SimpleXMLElement in beide Richtungen zu verwenden.
FMaz008

4
Ich würde es als Antwort anstelle von aktuell markieren. Aktuelle Antwort nicht rekursive Arrays
erstellen

2
Schöne Klasse. Ich wechselte die Leitung 128 if(!is_array($arr)) {zu , if(!is_array($arr) && $arr !== '') {so dass es nicht einen neuen Textknoten für leere Strings anhängen und deshalb hält die Kurz leer - Tag - Format , dh 'tag'=>''ist <tag/>statt<tag></tag>
user1433150

Dies ist die bisher beste Antwort. Auch dies hat die korrekte Struktur mehrerer Elemente mit demselben Schlüssel: 1. ist der Knotenname Schlüssel, dann enthält es das Array mit numerischen Schlüsseln. (das Gegenteil der Hanmant-Antwort)
Vasil Popov


57

Ich habe alle Antworten gefunden, um zu viel Code zu verwenden. Hier ist eine einfache Möglichkeit, dies zu tun:

function to_xml(SimpleXMLElement $object, array $data)
{   
    foreach ($data as $key => $value) {
        if (is_array($value)) {
            $new_object = $object->addChild($key);
            to_xml($new_object, $value);
        } else {
            // if the key is an integer, it needs text with it to actually work.
            if ($key == (int) $key) {
                $key = "key_$key";
            }

            $object->addChild($key, $value);
        }   
    }   
}   

Dann ist es eine einfache Sache, das Array in die Funktion zu senden, die Rekursion verwendet, damit es ein mehrdimensionales Array verarbeitet:

$xml = new SimpleXMLElement('<rootTag/>');
to_xml($xml, $my_array);

Jetzt enthält $ xml ein schönes XML-Objekt, das auf Ihrem Array basiert und genau so ist, wie Sie es geschrieben haben.

print $xml->asXML();

9
Ich liebe diese Lösung am meisten. Es wäre jedoch schön, einen Test für Zifferntasten hinzuzufügen, wie : if ( is_numeric( $key ) ) $key = "numeric_$key"; .
Ohne

@wout Guter Fang. Hinzugefügt. Ich habe anstelle von is_numeric eine Int-Cast-Prüfung durchgeführt, da is_numeric einige, wenn auch technisch erwartete, Ergebnisse liefern kann, die Sie wirklich abschrecken würden.
Francis Lewis

Ich benutze diese Funktion, habe sie aber $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');für eine gültige UTF-8-Codierung geändert .
Daantje

Ich mag diese Lösung auch am liebsten, einfach ist es :-) Eine Bemerkung: Vielleicht möchten Sie sie ändern, $object->addChild($key, $value);um $object->addChild($key, htmlspecialchars($value));zu verhindern, dass sie fehlschlägt, wenn $ value Zeichen wie "&" enthält, die XML-Codierung benötigen.
Leo

38
<? php
Funktion array_to_xml (Array $ arr, SimpleXMLElement $ xml)
{
    foreach ($ arr als $ k => $ v) {
        is_array ($ v)
            ? array_to_xml ($ v, $ xml-> addChild ($ k))
            : $ xml-> addChild ($ k, $ v);
    }}
    return $ xml;
}}

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

echo array_to_xml ($ test_array, neues SimpleXMLElement ('<root />')) -> asXML ();

1
Dies schlägt fehl, wenn Ihr Array ein inneres Array mit numerischen Indizes enthält. <0> ... </ 0> ist kein gültiges XML.
Adriano Varoli Piazza

@AdrianoVaroliPiazza fügen Sie einfach etwas wie $k = (is_numeric($k)) ? 'item' : $k;inforeach()
AlienWebguy

Wenn einer der Schlüssel im Array "body" heißt, funktioniert er nicht - genauer gesagt, der Schlüssel wird ignoriert und durchlaufen. Ich versuche herauszufinden warum.
Bambax

@Bambax Der einzige Grund, an den ich denken kann, ist, dass das XML zu einem späteren Zeitpunkt als HTML analysiert wird.
Brilliand

16

Ab PHP 5.4

function array2xml($data, $root = null){
    $xml = new SimpleXMLElement($root ? '<' . $root . '/>' : '<root/>');
    array_walk_recursive($data, function($value, $key)use($xml){
        $xml->addChild($key, $value);
    });
    return $xml->asXML();
}

Es scheint wie eine direkte Kopie der ausgewählten Antwort, die einfach in eine Funktion eingefügt wird.
Phaberest

Ich würde htmlspecialchars () zum addChild-Teil hinzufügen, wie folgt: $ xml-> addChild ($ key, htmlspecialchars ($ value));
Tyreal

15

Eine weitere Verbesserung:

/**
* Converts an array to XML
*
* @param array $array
* @param SimpleXMLElement $xml
* @param string $child_name
*
* @return SimpleXMLElement $xml
*/
public function arrayToXML($array, SimpleXMLElement $xml, $child_name)
{
    foreach ($array as $k => $v) {
        if(is_array($v)) {
            (is_int($k)) ? $this->arrayToXML($v, $xml->addChild($child_name), $v) : $this->arrayToXML($v, $xml->addChild(strtolower($k)), $child_name);
        } else {
            (is_int($k)) ? $xml->addChild($child_name, $v) : $xml->addChild(strtolower($k), $v);
        }
    }

    return $xml->asXML();
}

Verwendungszweck:

$this->arrayToXML($array, new SimpleXMLElement('<root/>'), 'child_name_to_replace_numeric_integers');

Danke dir! Ihre Funktion gibt den genauen Inhalt eines n-dimensionalen Arrays zurück.
Besciualex

12

Hier ist mein Eintrag, einfach und sauber ..

function array2xml($array, $xml = false){
    if($xml === false){
        $xml = new SimpleXMLElement('<root/>');
    }
    foreach($array as $key => $value){
        if(is_array($value)){
            array2xml($value, $xml->addChild($key));
        }else{
            $xml->addChild($key, $value);
        }
    }
    return $xml->asXML();
}


header('Content-type: text/xml');
print array2xml($array);

8

Also trotzdem ... Ich habe den Code von onokazu genommen (danke!) Und die Möglichkeit hinzugefügt, wiederholte Tags in XML zu haben. Er unterstützt auch Attribute. Ich hoffe, jemand findet ihn nützlich!

 <?php

function array_to_xml(array $arr, SimpleXMLElement $xml) {
        foreach ($arr as $k => $v) {

            $attrArr = array();
            $kArray = explode(' ',$k);
            $tag = array_shift($kArray);

            if (count($kArray) > 0) {
                foreach($kArray as $attrValue) {
                    $attrArr[] = explode('=',$attrValue);                   
                }
            }

            if (is_array($v)) {
                if (is_numeric($k)) {
                    array_to_xml($v, $xml);
                } else {
                    $child = $xml->addChild($tag);
                    if (isset($attrArr)) {
                        foreach($attrArr as $attrArrV) {
                            $child->addAttribute($attrArrV[0],$attrArrV[1]);
                        }
                    }                   
                    array_to_xml($v, $child);
                }
            } else {
                $child = $xml->addChild($tag, $v);
                if (isset($attrArr)) {
                    foreach($attrArr as $attrArrV) {
                        $child->addAttribute($attrArrV[0],$attrArrV[1]);
                    }
                }
            }               
        }

        return $xml;
    }

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

        $xml = array_to_xml($test_array, new SimpleXMLElement('<root/>'))->asXML();

        echo "$xml\n";
        $dom = new DOMDocument;
        $dom->preserveWhiteSpace = FALSE;
        $dom->loadXML($xml);
        $dom->formatOutput = TRUE;
        echo $dom->saveXml();
    ?>

Könnte hilfreich sein, Ihre Änderungen zu kommentieren, um den Code klarer zu machen.
Trotzdem

Dies funktionierte bei mir mit WP All Export. Ich musste den is_numeric Teil leicht ändern: if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
Achiever

4

Ich verwende einige Funktionen, die ich vor einiger Zeit geschrieben habe, um die XML-Datei zu generieren, die von PHP und jQuery usw. hin und her übertragen werden soll. Weder zusätzliche Frameworks verwenden lediglich eine Zeichenfolge, die dann mit SimpleXML (oder einem anderen Framework) verwendet werden kann ) ...

Wenn es für jemanden nützlich ist, benutze es bitte :)

function generateXML($tag_in,$value_in="",$attribute_in=""){
    $return = "";
    $attributes_out = "";
    if (is_array($attribute_in)){
        if (count($attribute_in) != 0){
            foreach($attribute_in as $k=>$v):
                $attributes_out .= " ".$k."=\"".$v."\"";
            endforeach;
        }
    }
    return "<".$tag_in."".$attributes_out.((trim($value_in) == "") ? "/>" : ">".$value_in."</".$tag_in.">" );
}

function arrayToXML($array_in){
    $return = "";
    $attributes = array();
    foreach($array_in as $k=>$v):
        if ($k[0] == "@"){
            // attribute...
            $attributes[str_replace("@","",$k)] = $v;
        } else {
            if (is_array($v)){
                $return .= generateXML($k,arrayToXML($v),$attributes);
                $attributes = array();
            } else if (is_bool($v)) {
                $return .= generateXML($k,(($v==true)? "true" : "false"),$attributes);
                $attributes = array();
            } else {
                $return .= generateXML($k,$v,$attributes);
                $attributes = array();
            }
        }
    endforeach;
    return $return;
}   

Grüße an alle :)


4

Ich wollte einen Code, der alle Elemente in einem Array als Attribute und alle Arrays als Unterelemente behandelt.

Also für so etwas

array (
'row1' => array ('head_element' =>array("prop1"=>"some value","prop2"=>array("empty"))),
"row2"=> array ("stack"=>"overflow","overflow"=>"overflow")
);

Ich würde so etwas bekommen

<?xml version="1.0" encoding="utf-8"?>
<someRoot>
  <row1>
    <head_element prop1="some value">
      <prop2 0="empty"/>
    </head_element>
  </row1>
  <row2 stack="overflow" overflow="stack"/>
 </someRoot>

Um dies zu erreichen, ist der Code unten, aber seien Sie sehr vorsichtig, er ist rekursiv und kann tatsächlich einen Stapelüberlauf verursachen :)

function addElements(&$xml,$array)
{
$params=array();
foreach($array as $k=>$v)
{
    if(is_array($v))
        addElements($xml->addChild($k), $v);
    else $xml->addAttribute($k,$v);
}

}
function xml_encode($array)
{
if(!is_array($array))
    trigger_error("Type missmatch xml_encode",E_USER_ERROR);
$xml=new SimpleXMLElement('<?xml version=\'1.0\' encoding=\'utf-8\'?><'.key($array).'/>');
addElements($xml,$array[key($array)]);
return $xml->asXML();
} 

Möglicherweise möchten Sie die Länge des Arrays überprüfen, damit ein Element im Datenteil und nicht als Attribut festgelegt wird.


4

Basierend auf allem anderen hier werden numerische Indizes + Attribute über das Präfix mit behandelt @und können XML in vorhandene Knoten einfügen:

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

Verwendung

// 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

Ergebnis

<?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>
    </sub>
  </var>
  <foo>1234</foo>
</x>

Bonus: XML formatieren

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

Eine aktualisierte Version, die sich als
untergeordnete

3

Hier ist eine Funktion, die den Trick für mich getan hat:

Nennen Sie es einfach mit so etwas wie

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

3

Sie können den XMLParser verwenden , an dem ich gearbeitet habe.

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

Würde ergeben zu:

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

3

Ich fand diese Lösung ähnlich wie das ursprüngliche Problem

<?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();

3

Die meisten der obigen Antworten sind richtig. Ich habe jedoch diese Antwort gefunden, die das Kompatibilitätsproblem array_walk_recursive und auch das Problem der numerischen Schlüssel löst. Es hat auch alle Tests bestanden, die ich gemacht habe:

function arrayToXML(Array $array, SimpleXMLElement &$xml) {

    foreach($array as $key => $value) {

        // None array
        if (!is_array($value)) {
            (is_numeric($key)) ? $xml->addChild("item$key", $value) : $xml->addChild($key, $value);
            continue;
        }   

        // Array
        $xmlChild = (is_numeric($key)) ? $xml->addChild("item$key") : $xml->addChild($key);
        arrayToXML($value, $xmlChild);
    }
}   

Ich habe auch eine Testklasse hinzugefügt, die Sie vielleicht nützlich finden:

class ArrayToXmlTest extends PHPUnit_Framework_TestCase {

    public function setUp(){ }
    public function tearDown(){ }

    public function testFuncExists() {
        $this->assertTrue(function_exists('arrayToXML'));
    }

    public function testFuncReturnsXml() {
        $array = array(
            'name' => 'ardi',
            'last_name' => 'eshghi',
            'age' => 31,
            'tel' => '0785323435'
        );

        $xmlEl =  new SimpleXMLElement('<root/>');
        arrayToXml($array, $xmlEl);

        $this->assertTrue($xmlEl instanceOf SimpleXMLElement);
    }

    public function testAssocArrayToXml() {

        $array = array(
            'name' => 'ardi',
            'last_name' => 'eshghi',
            'age' => 31,
            'tel' => '0785323435'
        );

        $expectedXmlEl = new SimpleXMLElement('<root/>'); 
        $expectedXmlEl->addChild('name', $array['name']);
        $expectedXmlEl->addChild('last_name', $array['last_name']);
        $expectedXmlEl->addChild('age', $array['age']);
        $expectedXmlEl->addChild('tel', $array['tel']);

        $actualXmlEl =  new SimpleXMLElement('<root/>');
        arrayToXml($array, $actualXmlEl);

        $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());
    }

    public function testNoneAssocArrayToXml() {

        $array = array(
            'ardi',
            'eshghi',
            31,
            '0785323435'
        );

        // Expected xml value
        $expectedXmlEl = new SimpleXMLElement('<root/>'); 
        foreach($array as $key => $value)
            $expectedXmlEl->addChild("item$key", $value);

        // What the function produces       
        $actualXmlEl =  new SimpleXMLElement('<root/>');
        arrayToXml($array, $actualXmlEl);

        $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());
    }

    public function testNestedMixArrayToXml() {

        $testArray = array(
            "goal",
            "nice",
            "funny" => array(
                'name' => 'ardi',
                'tel'   =>'07415517499',
                "vary",
                "fields" => array(
                    'small',
                    'email' => 'ardi.eshghi@gmail.com'
                ),

                'good old days'

            ),

            "notes" => "come on lads lets enjoy this",
            "cast" => array(
                'Tom Cruise',
                'Thomas Muller' => array('age' => 24)
            )
        );

        // Expected xml value
        $expectedXmlEl = new SimpleXMLElement('<root/>'); 
        $expectedXmlEl->addChild('item0', $testArray[0]);
        $expectedXmlEl->addChild('item1', $testArray[1]);
        $childEl = $expectedXmlEl->addChild('funny');
        $childEl->addChild("name", $testArray['funny']['name']);
        $childEl->addChild("tel", $testArray['funny']['tel']);
        $childEl->addChild("item0", "vary");
        $childChildEl = $childEl->addChild("fields");
        $childChildEl->addChild('item0', 'small');
        $childChildEl->addChild('email', $testArray['funny']['fields']['email']);
        $childEl->addChild("item1", 'good old days');
        $expectedXmlEl->addChild('notes', $testArray['notes']);
        $childEl2 = $expectedXmlEl->addChild('cast');
        $childEl2->addChild('item0', 'Tom Cruise');
        $childChildEl2 = $childEl2->addChild('Thomas Muller');
        $childChildEl2->addChild('age', $testArray['cast']['Thomas Muller']['age']);

        // What the function produces       
        $actualXmlEl = new SimpleXMLElement('<root/>');
        arrayToXml($testArray, $actualXmlEl);

        $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());
    }
}      

3

andere Lösung:

$marray=array(....);
$options = array(
                "encoding" => "UTF-8",
                "output_type" => "xml", 
                "version" => "simple",
                "escaping" => array("non-ascii, on-print, markup")
                );
$xmlres = xmlrpc_encode_request('root', $marray, $options);
print($xmlres);

Dies hat einen unerwarteten Effekt beim Erstellen von XML im RPC-Stil mit Methoden wie methodCall, methodName, Skalaren und Vektoren usw. Es konvertiert ein Array nicht wirklich in XML im einfachen Sinne.
Volomike

3

Wenn das Array assoziativ und korrekt verschlüsselt ist, ist es wahrscheinlich einfacher, es zuerst in XML umzuwandeln. Etwas wie:

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

Der andere Weg wäre, zuerst Ihre grundlegende XML zu erstellen, wie z

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

Verwenden Sie dann für jeden Teil Ihres Arrays etwas Ähnliches wie meine Texterstellungsschleife und verwenden Sie stattdessen die Simplexml-Funktionen "addChild" für jeden Knoten des Arrays.

Ich werde das später ausprobieren und diesen Beitrag mit beiden Versionen aktualisieren.


Das Bit, in dem ich "<array> </ array>" erwähnte, machte mir klar, dass die String-Version etwas Ähnliches benötigt. Grundsätzlich muss das Array einen Knoten ganz außen haben. Lassen Sie mich über die ganze Sache schlafen, ich werde etwas haben, das diesen anfänglichen Fehler sofort auffängt.
Anthony

2

Nur eine Bearbeitung einer Funktion oben, wenn eine Taste numerisch ist, fügen Sie ein Präfix "key_" hinzu.

// initializing or creating array
$student_info = array(your array data);

// creating object of SimpleXMLElement
$xml_student_info = new SimpleXMLElement("<?xml version=\"1.0\"?><student_info></student_info>");

// function call to convert array to xml
array_to_xml($student,$xml_student_info);

//saving generated xml file
$xml_student_info->asXML('file path and name');


function array_to_xml($student_info, &$xml_student_info) {
     foreach($student_info as $key => $value) {
          if(is_array($value)) {
            if(!is_numeric($key)){
                $subnode = $xml_student_info->addChild("$key");
                array_to_xml($value, $subnode);
            }
            else{
                $subnode = $xml_student_info->addChild("key_$key");
                array_to_xml($value, $subnode);
            }
          }
          else {
               if(!is_numeric($key)){
                    $xml_student_info->addChild("$key","$value");
               }else{
                    $xml_student_info->addChild("key_$key","$value");
               }
          }
     }
}

1

Sie können die folgende Funktion in Ihrem Code direkt verwenden:

    function artoxml($arr, $i=1,$flag=false){
    $sp = "";
    for($j=0;$j<=$i;$j++){
        $sp.=" ";
     }
    foreach($arr as $key=>$val){
        echo "$sp&lt;".$key."&gt;";
        if($i==1) echo "\n";
        if(is_array($val)){
            if(!$flag){echo"\n";}
            artoxml($val,$i+5);
            echo "$sp&lt;/".$key."&gt;\n";
        }else{
              echo "$val"."&lt;/".$key."&gt;\n";
         }
    }

}

Rufen Sie die Funktion mit dem ersten Argument als Array auf, und das zweite Argument muss 1 sein. Dies wird für eine perfekte Einrückung erhöht, und das dritte muss wahr sein.

Wenn die zu konvertierende Array-Variable beispielsweise $ array1 ist, sollte die aufrufende Funktion beim Aufrufen mit einem <pre>Tag gekapselt werden .

  artoxml ($ array1,1, true);   

Bitte sehen Sie sich die Seitenquelle nach dem Ausführen der Datei an, da die Symbole <und> auf einer HTML-Seite nicht angezeigt werden.


1
function toXML($data, $obj = false, $dom) {
    $is_first_level = false;
    if($obj === false) {
        $dom = new DomDocument('1.0');
        $obj = $dom;
        $is_first_level = true;
    }

    if(is_array($data)) {
        foreach($data as $key => $item) {
            $this->toXML($item, $obj->appendChild($dom->createElement($key)), $dom);
        }
    }else {
        $obj->appendChild($dom->createTextNode($data));
    }

    if($is_first_level) {
        $obj->formatOutput = true;
        return $obj->saveXML();
    }
    return $obj;
}

Dies ist eine hervorragende Option zum Erstellen von DOMDocument-XML. Danke @Andrey
Altsyset

1
function array2xml(array $data, SimpleXMLElement $object = null, $oldNodeName = 'item')
{
    if (is_null($object)) $object = new SimpleXMLElement('<root/>');
    $isNumbered = true;
    $idx = 0;
    foreach ($data as $key => $x)
        if (is_string($key) || ($idx++ != $key + 0))
            $isNumbered = false;
    foreach ($data as $key => $value)
    {   
        $attribute = preg_match('/^[0-9]/', $key . '') ? $key : null;
        $key = (is_string($key) && !preg_match('/^[0-9]/', $key . '')) ? $key : preg_replace('/s$/', '', $oldNodeName);
        if (is_array($value))
        {
            $new_object = $object->addChild($key);
            if (!$isNumbered && !is_null($attribute)) $new_object->addAttribute('id', $attribute);
            array2xml($value, $new_object, $key);
        }
        else
        {
            if (is_bool($value)) $value = $value ? 'true' : 'false';
            $node = $object->addChild($key, htmlspecialchars($value));
            if (!$isNumbered && !is_null($attribute) && !isset($node->attributes()->id))
                $node->addAttribute('id', $attribute);
        }
    }
    return $object;
}

Diese Funktion gibt beispielsweise eine Liste von <obj> ... </obj> <obj> ... </ obj> XML-Tags für numerische Indizes zurück.

Eingang:

    array(
    'people' => array(
        'dog',
        'cat',
        'life' => array(
            'gum',
            'shoe',
        ),
        'fish',
    ),
    array('yeah'),
)

Ausgabe:

<root>
    <people>
        <people>dog</people>
        <people>cat</people>
        <life>
            <life>gum</life>
            <life>shoe</life>
        </life>
        <people>fish</people>
        <people>
            <people>yeah</people>
        </people>
    </people>
</root>

Dies sollte alle gängigen Bedürfnisse befriedigen. Vielleicht können Sie die 3. Zeile ändern in:

$key = is_string($key) ? $key : $oldNodeName . '_' . $key;

oder wenn Sie mit Pluralformen arbeiten, die mit s enden:

$key = is_string($key) ? $key : preg_replace('/s$/', '', $oldNodeName);

1

Mit FluidXML können Sie ausgehend von einem PHP-Array ein XML für SimpleXML mit ... nur zwei Codezeilen generieren.

$fluidxml  = fluidxml($array);
$simplexml = simplexml_import_dom($fluidxml->dom());

Ein Beispielarray könnte sein

$array = [ 'doc' => [
              'fruit' => 'orange',
              'cake'  => [
                   '@id' => '123', 
                   '@'   => 'tiramisu' ],
              [ 'pasta' => 'matriciana' ],
              [ 'pasta' => 'boscaiola'  ]
] ];

https://github.com/servo-php/fluidxml


0

Sie können xmlrpc_encode verwenden, um eine XML aus einem Array zu erstellen, wenn eine ausführliche XML kein Problem darstellt. www.php.net/xmlrpc_encode

Seien Sie vorsichtig, die erstellte XML unterscheidet sich, wenn Sie assoziative und / oder numerische Schlüssel verwenden

<?php
// /params/param/value/struct/member
// there is a tag "member" for each element
// "member" contains a tag "name". its value is the associative key
$xml1 = xmlrpc_encode(array('a'=>'b','c'=>'d'));
$simplexml1 = simplexml_load_string($xml1);
print_r($xml1);
print_r($simplexml1);

// /params/param/value/array/data
// there is a tag "data" for each element
// "data" doesn't contain the tag "name"
$xml2 = xmlrpc_encode(array('a','b'));
$simplexml2 = simplexml_load_string($xml2);
print_r($xml2);
print_r($simplexml2);
?>

Diese Funktion wird nicht unterstützt und ist in meinen Builds von PHP 5.2.16 oder PHP 5.3.5 nicht enthalten. (gibt "PHP Fatal error: Aufruf der undefinierten Funktion xmlrpc_encode ()" zurück)
Danorton

Sie müssen die folgende Zeile in php.ini auskommentieren: extension = php_xmlrpc.dll
w35l3y

@ w35l3y Ich habe meine INI überprüft. Es enthält nicht einmal diese Erweiterung und ich verwende Version 5.3.6.
Mike S.

0
function array2xml($array, $xml = false){

    if($xml === false){

        $xml = new SimpleXMLElement('<?xml version=\'1.0\' encoding=\'utf-8\'?><'.key($array).'/>');
        $array = $array[key($array)];

    }
    foreach($array as $key => $value){
        if(is_array($value)){
            $this->array2xml($value, $xml->addChild($key));
        }else{
            $xml->addChild($key, $value);
        }
    }
    return $xml->asXML();
}

0

Meine Antwort, die Antworten anderer zusammenzuschustern. Dies sollte das Versagen korrigieren, numerische Tasten zu kompensieren:

function array_to_xml($array, $root, $element) {
    $xml = new SimpleXMLElement("<{$root}/>");
    foreach ($array as $value) {
        $elem = $xml->addChild($element);
        xml_recurse_child($elem, $value);
    }
    return $xml;
}

function xml_recurse_child(&$node, $child) {
    foreach ($child as $key=>$value) {
        if(is_array($value)) {
            foreach ($value as $k => $v) {
                if(is_numeric($k)){
                    xml_recurse_child($node, array($key => $v));
                }
                else {
                    $subnode = $node->addChild($key);
                    xml_recurse_child($subnode, $value);
                }
            }
        }
        else {
            $node->addChild($key, $value);
        }
    }   
}

Die array_to_xml()Funktion setzt voraus, dass das Array zuerst aus Zifferntasten besteht. Wenn Ihr Array ein Anfangselement hätte, würden Sie die Anweisungen foreach()und $elemaus der array_to_xml()Funktion löschen und $xmlstattdessen einfach übergeben .


0

Ich hätte die am zweithäufigsten gewählte Antwort kommentiert, da sie die Struktur nicht beibehält und schlechte XML generiert, wenn es numerisch indizierte innere Arrays gibt.

Darauf aufbauend habe ich meine eigene Version entwickelt, da ich unabhängig von der Datenstruktur einen einfachen Konverter zwischen json und xml benötigte. Meine Version behält die numerischen Schlüsselinformationen und die Struktur des ursprünglichen Arrays bei. Es erstellt Elemente für die numerisch indizierten Werte, indem Werte in wertbenannte Elemente mit einem Schlüsselattribut eingeschlossen werden, das einen numerischen Schlüssel enthält.

Beispielsweise

array('test' => array(0 => 'some value', 1 => 'other'))

konvertiert zu

<test><value key="0">some value</value><value key="1">other</value></test>

Meine Version von array_to_xml -function (hoffe es hilft jemandem :)

function array_to_xml($arr, &$xml) {
    foreach($arr as $key => $value) {
        if(is_array($value)) {
            if(!is_numeric($key)){
                $subnode = $xml->addChild("$key");
            } else {
                $subnode = $xml->addChild("value");
                $subnode->addAttribute('key', $key);                    
            }
            array_to_xml($value, $subnode);
        }
        else {
            if (is_numeric($key)) {
                $xml->addChild("value", $value)->addAttribute('key', $key);
            } else {
                $xml->addChild("$key",$value);
            }
        }
    }
}   

0

Die gesamte XML-Struktur ist in $ data Array definiert:

function array2Xml($data, $xml = null)
{
    if (is_null($xml)) {
        $xml = simplexml_load_string('<' . key($data) . '/>');
        $data = current($data);
        $return = true;
    }
    if (is_array($data)) {
        foreach ($data as $name => $value) {
            array2Xml($value, is_numeric($name) ? $xml : $xml->addChild($name));
        }
    } else {
        $xml->{0} = $data;
    }
    if (!empty($return)) {
        return $xml->asXML();
    }
}

0

Wenn Sie in Magento arbeiten und diese Art von assoziativem Array haben

$test_array = array (
    '0' => array (
            'category_id' => '582',
            'name' => 'Surat',
            'parent_id' => '565',
            'child_id' => '567',
            'active' => '1',
            'level' => '6',
            'position' => '17'
    ),

    '1' => array (
            'category_id' => '567', 
            'name' => 'test',
            'parent_id' => '0',
            'child_id' => '576',
            'active' => '0',
            'level' => '0',
            'position' => '18'
    ),
);

Dann ist es am besten, das assoziative Array in das XML-Format zu konvertieren. Verwenden Sie diesen Code in der Controller-Datei.

$this->loadLayout(false);
//header ("content-type: text/xml");
$this->getResponse()->setHeader('Content-Type','text/xml');
$this->renderLayout();

$clArr2xml = new arr2xml($test_array, 'utf-8', 'listdata');
$output = $clArr2xml->get_xml();
print $output; 

class arr2xml
{
var $array = array();
var $xml = '';
var $root_name = '';
var $charset = '';

public function __construct($array, $charset = 'utf-8', $root_name = 'root')
{
    header ("content-type: text/xml");
    $this->array = $array;
    $this->root_name = $root_name;
    $this->charset = $charset;

    if (is_array($array) && count($array) > 0) {
        $this->struct_xml($array);

    } else {
        $this->xml .= "no data";
    }
}

public function struct_xml($array)
{
    foreach ($array as $k => $v) {
        if (is_array($v)) {
            $tag = ereg_replace('^[0-9]{1,}', 'item', $k); // replace numeric key in array to 'data'
            $this->xml .= "<$tag>";
            $this->struct_xml($v);
            $this->xml .= "</$tag>";
        } else {
            $tag = ereg_replace('^[0-9]{1,}', 'item', $k); // replace numeric key in array to 'data'
            $this->xml .= "<$tag><![CDATA[$v]]></$tag>";
        }
    }
}

public function get_xml()
{

    $header = "<?xml version=\"1.0\" encoding=\"" . $this->charset . "\"?><" . $this->root_name . ">";
    $footer = "</" . $this->root_name . ">";

    return $header . $this->xml . $footer;
}
}

Ich hoffe es hilft allen.


0

// Structered array for XML convertion.
$data_array = array(
  array(
    '#xml_tag' => 'a',
    '#xml_value' => '',
    '#tag_attributes' => array(
      array(
        'name' => 'a_attr_name',
        'value' => 'a_attr_value',
      ),
    ),
    '#subnode' => array(
      array(
        '#xml_tag' => 'aa',
        '#xml_value' => 'aa_value',
        '#tag_attributes' => array(
          array(
            'name' => 'aa_attr_name',
            'value' => 'aa_attr_value',
          ),
        ),
        '#subnode' => FALSE,
      ),
    ),
  ),
  array(
    '#xml_tag' => 'b',
    '#xml_value' => 'b_value',
    '#tag_attributes' => FALSE,
    '#subnode' => FALSE,
  ),
  array(
    '#xml_tag' => 'c',
    '#xml_value' => 'c_value',
    '#tag_attributes' => array(
      array(
        'name' => 'c_attr_name',
        'value' => 'c_attr_value',
      ),
      array(
        'name' => 'c_attr_name_1',
        'value' => 'c_attr_value_1',
      ),
    ),
    '#subnode' => array(
      array(
        '#xml_tag' => 'ca',  
        '#xml_value' => 'ca_value',
        '#tag_attributes' => FALSE,
        '#subnode' => array(
          array(
            '#xml_tag' => 'caa',
            '#xml_value' => 'caa_value',
            '#tag_attributes' => array(
              array(
                'name' => 'caa_attr_name',
                'value' => 'caa_attr_value',
              ),
            ),
            '#subnode' => FALSE,
          ),
        ),
      ),
    ),
  ),
);


// creating object of SimpleXMLElement
$xml_object = new SimpleXMLElement('<?xml version=\"1.0\"?><student_info></student_info>');


// function call to convert array to xml
array_to_xml($data_array, $xml_object);

// saving generated xml file
$xml_object->asXML('/tmp/test.xml');

/**
 * Converts an structured PHP array to XML.
 *
 * @param Array $data_array
 *   The array data for converting into XML.
 * @param Object $xml_object
 *   The SimpleXMLElement Object
 *
 * @see https://gist.github.com/drupalista-br/9230016
 * 
 */
function array_to_xml($data_array, &$xml_object) {
  foreach($data_array as $node) {
    $subnode = $xml_object->addChild($node['#xml_tag'], $node['#xml_value']);

    if ($node['#tag_attributes']) {
      foreach ($node['#tag_attributes'] as $tag_attributes) {
        $subnode->addAttribute($tag_attributes['name'], $tag_attributes['value']); 
      }
    }

    if ($node['#subnode']) {
      array_to_xml($node['#subnode'], $subnode);
    }
  }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.