Bagaimana cara mengubah array menjadi SimpleXML


Jawaban:


209

yang singkat:

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

hasil dalam

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

kunci dan nilai ditukar - Anda bisa memperbaikinya dengan array_flip()sebelum array_walk. array_walk_recursivemembutuhkan PHP 5. Anda bisa menggunakannya array_walk, tetapi Anda tidak akan mendapatkan 'stack' => 'overflow'xml saat itu.


53
Ini tidak akan berfungsi jika $ test_array memiliki 'more_another_array' seperti 'another_array', karena kunci 'another_array' tidak dikonversi. Karenanya Anda akan memiliki beberapa '<overflow> tumpukan </overflow>'.
understack

11
Tidak array_flipakan berfungsi karena tidak dapat membalik array (seperti di another_arraydalam array utama).
Lode

14
Di mana elemen xml "another_array"? Semuanya rata :(
FMaz008

2
Bekerja dengan baik ketika saya menambahkan array_flip sebelum array_walk_recursive. Terima kasih.
Mike Purcell

12
Menurunkan karena array_fliphanya berfungsi jika array tidak mengandung nilai yang identik.
Martijn

385

Berikut ini adalah kode php 5.2 yang akan mengonversi berbagai kedalaman ke dokumen xml:

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

        )
)

XML yang dihasilkan akan seperti:

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

Cuplikan PHP

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

?>

Dokumentasi tentang SimpleXMLElement::asXMLdigunakan dalam cuplikan ini


40
Ini, IMO, adalah solusi yang jauh lebih baik daripada jawaban yang diterima. Namun, ini memiliki batasan bahwa dengan array yang dikunci secara numerik, ini menghasilkan XML yang salah bentuk. <0> <1> <2> bukan nama simpul yang valid.
KOGI

2
Namun, jika array yang dikunci secara numerik hanya berisi array lain yang tidak dikunci secara numerik, array tidak akan dikunci.
Bryan Petty

15
@ KOGI Saya telah mengubah jawaban Hanmant. Sekarang mendukung array bertingkat. pastebin.com/pYuXQWee
Mifas

1
Contoh ini secara eksplisit lolos dari karakter khusus dalam data teks elemen menggunakan htmlspecialchars, tetapi SimpleXMLElement :: addChild menerjemahkan karakter khusus xml ke entitas char mereka secara otomatis sehingga htmlspecialchars dapat ditinggalkan. Menariknya, ini tampaknya tidak menghasilkan data dua kali lipat.
mbaynton

3
@Alex, Edit # 5 Anda membuat contoh gagal. Itu menyisipkan <item $ x> sebelum setiap catatan <student> membuat output XML bukan apa yang dimaksudkan penulis. Mungkin memberikan contoh masalah yang Anda coba untuk memperbaiki dan kami dapat menemukan solusi lain untuk kedua kasus. Butuh waktu beberapa saat sebelum saya menyadari bahwa kode penulis telah dimodifikasi.
Nicholas Blasgen

124

Jawaban yang diberikan di sini hanya mengubah array menjadi XML dengan node, Anda tidak dapat mengatur atribut. Saya telah menulis fungsi php yang memungkinkan Anda untuk mengkonversi array ke php dan juga mengatur atribut untuk node tertentu di xml. Kelemahannya di sini adalah Anda harus membuat array dengan cara tertentu dengan sedikit konvensi (hanya jika Anda ingin menggunakan atribut)

Contoh berikut akan memungkinkan Anda untuk mengatur atribut dalam XML juga.

Sumbernya dapat ditemukan di sini: 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
Saya terkejut bahwa tidak ada yang bereaksi pada yang ini. Kelas ini sangat berguna karena ia melakukan kebalikan dari apa yang akan dihasilkan oleh simpleXMLElement. Jadi itu memberi Anda kemungkinan menggunakan SimpleXMLElement dua arah.
FMaz008

4
Saya akan menandainya sebagai jawaban alih-alih saat ini. Jawaban saat ini tidak membangun array rekursif
Oleksandr IY

2
Kelas yang bagus. Saya mengubah baris 128 if(!is_array($arr)) {ke if(!is_array($arr) && $arr !== '') {sehingga tidak akan menambahkan sebuah simpul teks baru untuk string kosong dan karena itu membuat singkatan kosong Format tag yaitu 'tag'=>''adalah <tag/>bukan<tag></tag>
user1433150

Ini adalah jawaban terbaik sejauh ini. Juga ini memiliki struktur yang benar dari beberapa item dengan kunci yang sama: 1 adalah kunci nama simpul, kemudian berisi array dengan kunci numerik. (kebalikan dari jawaban Hanmant)
Vasil Popov

1
Ditemukan github dari penulis @Legionar github.com/digitickets/lalit/blob/master/src/Array2XML.php
Daryl Teo

57

Saya menemukan semua jawaban untuk menggunakan terlalu banyak kode. Ini cara mudah untuk melakukannya:

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

Maka itu masalah sederhana mengirimkan array ke fungsi, yang menggunakan rekursi, sehingga akan menangani array multi-dimensi:

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

Sekarang $ xml berisi objek XML yang indah berdasarkan pada array Anda persis bagaimana Anda menulisnya.

print $xml->asXML();

9
Saya paling suka solusi ini. Meskipun, itu akan menyenangkan untuk menambahkan tes pada tombol angka, seperti: if ( is_numeric( $key ) ) $key = "numeric_$key"; .
Wout

@ baik Tangkapan yang bagus. Ditambahkan. Saya melakukan pengecekan int bukan is_numeric karena is_numeric dapat memberikan beberapa, meskipun secara teknis diharapkan, hasil yang benar-benar akan membuat Anda marah.
Francis Lewis

Saya menggunakan fungsi ini, tetapi diubah $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');untuk pengkodean UTF-8 yang valid.
Daantje

Aku seperti solusi ini paling juga, sederhana melakukannya :-) Satu komentar: Anda mungkin ingin mengubah $object->addChild($key, $value);untuk $object->addChild($key, htmlspecialchars($value));untuk mencegah gagal ketika $ nilai berisi karakter seperti "&" yang perlu XML-encoding.
leo

38
<? php
function array_to_xml (array $ arr, SimpleXMLElement $ xml)
{
    foreach ($ arr as $ k => $ v) {
        is_array ($ v)
            ? array_to_xml ($ v, $ xml-> addChild ($ k))
            : $ xml-> addChild ($ k, $ v);
    }
    kembalikan $ xml;
}

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

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

1
ini gagal jika array Anda berisi array dalam dengan indeks numerik. <0> ... </0> bukan XML yang valid.
Adriano Varoli Piazza

@AdrianoVaroliPiazza tambahkan sesuatu seperti $k = (is_numeric($k)) ? 'item' : $k;di dalamforeach()
AlienWebguy

Jika salah satu kunci dalam array bernama "body", itu tidak berfungsi - lebih tepatnya, kunci tersebut diabaikan dan dilintasi. Mencoba mencari tahu alasannya.
Bambax

@Bambax Satu-satunya alasan yang dapat saya pikirkan adalah jika XML sedang diuraikan sebagai HTML di beberapa titik kemudian.
Brilliand

16

Dari 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();
}

Sepertinya salinan langsung dari jawaban yang dipilih, cukup dimasukkan ke dalam fungsi.
phaberest

Saya akan menambahkan htmlspecialchars () ke bagian addChild, seperti ini: $ xml-> addChild ($ key, htmlspecialchars ($ value));
Tyreal

15

Peningkatan lainnya:

/**
* 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();
}

Pemakaian:

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

Terima kasih! Fungsi Anda mengembalikan konten yang tepat dari setiap array n-dimensi.
besciualex

12

Inilah entri saya, sederhana dan bersih ..

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

Jadi, bagaimanapun juga ... Saya mengambil kode onokazu (terima kasih!) Dan menambahkan kemampuan untuk mengulangi tag dalam XML, itu juga mendukung atribut, semoga seseorang merasa berguna!

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

Sangat membantu untuk mengomentari perubahan Anda untuk membuat kode lebih jelas; masih, tambahan yang bagus
StormeHawke

Ini bekerja untuk saya dengan WP All Export. Aku harus mengubah bagian is_numeric sedikit: if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
achiever

4

Saya menggunakan beberapa fungsi yang saya tulis beberapa waktu lalu untuk menghasilkan xml untuk bolak-balik dari PHP dan jQuery dll ... Baik menggunakan kerangka kerja tambahan hanya murni menghasilkan string yang kemudian dapat digunakan dengan SimpleXML (atau kerangka kerja lain ) ...

Jika bermanfaat bagi siapa pun, silakan gunakan :)

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

Cinta untuk semua :)


4

Saya ingin kode yang akan mengambil semua elemen di dalam array dan memperlakukannya sebagai atribut, dan semua array sebagai sub elemen.

Jadi untuk sesuatu seperti

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

Saya akan mendapatkan sesuatu seperti ini

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

Untuk mencapai ini, kode di bawah ini, tetapi sangat hati-hati, ini bersifat rekursif dan sebenarnya dapat menyebabkan stackoverflow :)

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

Anda mungkin ingin menambahkan cek untuk panjang array sehingga beberapa elemen bisa diatur di dalam bagian data dan bukan sebagai atribut.


4

Berdasarkan semua hal lain di sini, menangani atribut + atribut numerik melalui awalan dengan @, dan dapat menyuntikkan xml ke node yang ada:

Kode

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

Pemakaian

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

Hasil

<?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: Memformat 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

Versi terbaru yang berulang sebagai elemen anak daripada tag numerik: github.com/zaus/forms-3rdparty-xpost/blob/…
drzaus

3

Inilah fungsi yang melakukan trik untuk saya:

Sebut saja dengan sesuatu seperti

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

Anda bisa menggunakan XMLParser yang telah saya kerjakan.

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

Akan menghasilkan:

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

3

Saya menemukan solusi ini mirip dengan masalah aslinya

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

Sebagian besar jawaban di atas benar. Namun, saya datang dengan jawaban ini yang memecahkan masalah kompatibilitas array_walk_recursive dan juga masalah kunci numerik. Itu juga lulus semua tes yang saya buat:

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

Saya juga telah menambahkan kelas tes untuk ini yang mungkin berguna bagi Anda:

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

solusi lain:

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

Ini memiliki efek yang tak terduga dalam membuat XML RPC-style dengan hal-hal seperti methodCall, methodName, skalar dan vektor, dll. Ini tidak benar-benar mengubah array menjadi XML dalam arti langsung.
Volomike

3

JIKA array asosiatif dan dikunci dengan benar, mungkin akan lebih mudah untuk mengubahnya menjadi xml terlebih dahulu. Sesuatu seperti:

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

Rute lainnya adalah membuat xml dasar Anda terlebih dahulu, seperti

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

dan kemudian untuk setiap bagian array Anda, gunakan sesuatu yang mirip dengan loop pembuatan teks saya dan alih-alih gunakan fungsi simplexml "addChild" untuk setiap node array.

Saya akan mencobanya nanti dan memperbarui posting ini dengan kedua versi.


Sedikit di mana saya sebutkan "<array> </array>" membuat saya menyadari bahwa versi string membutuhkan sesuatu yang serupa. Pada dasarnya array harus memiliki satu simpul di bagian paling luar. Biarkan saya tidur pada semuanya, saya akan memiliki sesuatu yang menangkap kesalahan awal segera.
Anthony

2

Hanya edit pada fungsi di atas, ketika kunci numerik, tambahkan awalan "key_"

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

Anda dapat menggunakan fungsi berikut dalam kode Anda secara langsung,

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

}

Panggil fungsi dengan argumen pertama sebagai array Anda dan argumen kedua harus 1, ini akan ditingkatkan untuk indentasi sempurna, dan ketiga harus benar.

misalnya, jika variabel array yang akan dikonversi adalah $ array1 maka, panggilan akan, fungsi panggilan harus dienkapsulasi dengan <pre>tag.

  artoxml ($ array1,1, true);   

Silakan lihat sumber halaman setelah mengeksekusi file, karena simbol <dan> tidak akan ditampilkan dalam halaman html.


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

Ini adalah opsi yang sangat baik untuk membuat DOMDocument xml. Terima kasih @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;
}

Fungsi ini mengembalikan misalnya daftar <obj> ...</obj> <obj> ... </obj> tag XML untuk indeks numerik.

Memasukkan:

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

Keluaran:

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

Ini harus memenuhi semua kebutuhan bersama. Mungkin Anda dapat mengubah baris ke-3 menjadi:

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

atau jika Anda bekerja dengan bentuk jamak yang diakhiri dengan s:

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

1

Dengan FluidXML Anda dapat membuat, mulai dari PHP Array , XML untuk SimpleXML dengan ... hanya dua baris kode.

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

Contoh array bisa berupa

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

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


0

Anda dapat menggunakan xmlrpc_encode untuk membuat xml dari array jika xml verbose tidak menjadi masalah. www.php.net/xmlrpc_encode

hati-hati xml yang dibuat berbeda jika Anda menggunakan kunci asosiatif dan / atau numerik

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

Fungsi ini tidak didukung dan, pada kenyataannya, tidak disediakan di build saya PHP 5.2.16 atau PHP 5.3.5. (mengembalikan "Kesalahan PHP Fatal: Panggil ke fungsi yang tidak ditentukan xmlrpc_encode ()")
danorton

Anda harus menghapus tanda komentar pada baris berikut di php.ini: extension = php_xmlrpc.dll
w35l3y

@ w35l3y Saya memeriksa ini. Bahkan tidak mengandung ekstensi itu dan saya menggunakan v 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

Jawaban saya, mengumpulkan jawaban orang lain. Ini harus memperbaiki kesalahan untuk mengkompensasi kunci numerik:

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

The array_to_xml()Fungsi menganggap bahwa array terdiri dari tombol angka pertama. Jika array Anda memiliki elemen awal, Anda akan menjatuhkan foreach()dan $elempernyataan dari array_to_xml()fungsi dan hanya meneruskannya $xml.


0

Saya akan mengomentari jawaban kedua yang paling banyak dipilih, karena itu tidak mempertahankan struktur dan menghasilkan xml buruk jika ada array batin yang diindeks secara numerik.

Saya mengembangkan versi saya sendiri berdasarkan itu, karena saya membutuhkan konverter sederhana antara json dan xml terlepas dari struktur data. Versi saya mempertahankan informasi kunci numerik dan struktur array asli. Itu menciptakan elemen untuk nilai yang diindeks secara numerik dengan membungkus nilai ke elemen yang diberi nama nilai dengan atribut-kunci yang berisi kunci numerik.

Sebagai contoh

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

dikonversi ke

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

Versi array_to_xml -fungsi saya (semoga membantu orang lain :)

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

Seluruh struktur XML didefinisikan dalam $ data Array:

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

Jika Anda bekerja di Magento dan Anda memiliki jenis array asosiatif

$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'
    ),
);

maka ini yang terbaik untuk mengubah array asosiatif ke format xml. Gunakan kode ini dalam file controller.

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

Saya harap ini membantu semua orang.


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);
    }
  }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.