Dizi SimpleXML'e dönüştürme


Yanıtlar:


209

kısa bir tane:

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

sonuç

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

anahtarlar ve değerler değiştirilir - bunu array_flip()array_walk'tan önce ile düzeltebilirsiniz . array_walk_recursivePHP 5 gerektirir. array_walkBunun yerine 'stack' => 'overflow'xml içine giremezsiniz.


53
$ Test_array, 'another_array' gibi 'more_another_array' içeriyorsa bu çalışmaz, çünkü 'another_array' anahtarı dönüştürülmez. Dolayısıyla, birden fazla '<overflow> yığını </overflow>' olur.
understack

11
array_flipDeğil çevirme diziler (gibi olabildiğince çalışmaz another_arrayana dizinin içinde).
Lode

14
"Another_array" xml öğesi nerede? Her şey düzleştirildi :(
FMaz008

2
Array_walk_recursive'dan önce array_flip eklediğimde harika çalıştı. Teşekkürler.
Mike Purcell

12
Çünkü Downvoting array_flipdizi özdeş değerler içeriyorsa çalışır.
Martijn

386

İşte herhangi bir derinlikteki diziyi xml belgesine dönüştürecek php 5.2 kodu:

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

        )
)

oluşturulan XML şöyle olacaktır:

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

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

?>

SimpleXMLElement::asXMLBu pasajda kullanılan belgeler


40
Bu, IMO, kabul edilen cevaptan çok daha iyi bir çözümdür. Bununla birlikte, bunun sayısal olarak anahtarlanmış dizilerle hatalı biçimlendirilmiş XML üretmesi sınırlaması vardır. <0> <2> geçerli düğüm adları değil.
KOGI

2
Ancak, sayısal olarak anahtarlanmış diziniz yalnızca sayısal olarak anahtarlanmamış başka bir dizi içeriyorsa içermez.
Bryan Petty

15
@KOGI Hanmant'ın cevabını değiştirdim. Şimdi çok seviyeli dizileri destekliyor. pastebin.com/pYuXQWee
Mifas

1
Bu örnek, htmlspecialchars kullanarak öğe metin verilerindeki özel karakterlerden açıkça kaçar, ancak SimpleXMLElement :: addChild, xml özel karakterlerini otomatik olarak karakter varlıklarına çevirir, böylece htmlspecialchars dışarıda bırakılabilir. İlginçtir, bu gibi görünüyor değil çift-kaçan verileri sonuçlanması.
mbaynton

3
@Alex, Düzenleme 5'inizde örnek başarısız olur. XML çıktısını yazarın istediği gibi yapmayan her <öğrenci> kaydının önüne <öğe $ x> ekler. Belki düzeltmeye çalıştığınız sorunun bir örneğini verin ve her iki durum için de başka bir çözüm bulabiliriz. Yazarların kodunun değiştirildiğini fark etmeden önce bir süre aldı.
Nicholas Blasgen

124

Burada verilen cevaplar diziyi sadece düğümlerle XML'e dönüştürür, öznitelikleri ayarlayamazsınız. Ben php bir dizi dönüştürmek ve ayrıca xml belirli düğümler için öznitelikleri ayarlamak için izin veren bir php işlevi yazdım. Buradaki dezavantaj, birkaç kuralla belirli bir şekilde bir dizi oluşturmanız gerektiğidir (yalnızca nitelikleri kullanmak istiyorsanız)

Aşağıdaki örnek, XML'de de özellikler ayarlamanıza olanak tanır.

Kaynak burada bulunabilir: 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
Kimsenin buna tepki göstermediğinden şaşırıyorum. Bu sınıf, simpleXMLElement'in üreteceği şeyin tersini yaptığı için gerçekten yararlıdır. Böylece SimpleXMLElement öğesini her iki şekilde de kullanma imkanı sunar.
FMaz008

4
Bunu akım yerine cevap olarak işaretlerdim. Şu anki yanıt özyinelemeli diziler oluşturmuyor
Oleksandr IY

2
Güzel bir sınıf. Çizgiyi 128 değişti if(!is_array($arr)) {için if(!is_array($arr) && $arr !== '') {boş dizeleri için yeni bir metin düğümü ekler olmayacak böylece ve bu nedenle yani stenografi boş etiketi biçimini tutar 'tag'=>''ise <tag/>yerine<tag></tag>
user1433150

Bu şimdiye kadarki en iyi cevap. Ayrıca bu, aynı tuşa sahip birden fazla öğenin doğru yapısına sahiptir: 1. düğüm adı anahtarıdır, ardından sayısal tuşlara sahip diziyi içerir. (Hanmant cevabının tam tersi)
Vasil Popov


57

Çok fazla kod kullanmak için tüm cevapları buldum. İşte bunu yapmanın kolay bir yolu:

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

Daha sonra diziyi özyineleme kullanan işleve göndermek basit bir konudur, böylece çok boyutlu bir diziyi işleyecektir:

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

$ Xml, dizinizi tam olarak nasıl yazdığınıza dayalı güzel bir XML nesnesi içeriyor.

print $xml->asXML();

9
Bu çözümü en çok seviyorum. Rağmen, gibi sayısal tuşlar üzerinde bir test eklemek iyi olurdu: if ( is_numeric( $key ) ) $key = "numeric_$key"; .
wout

@wout İyi yakaladın. Katma. İs_numeric teknik olarak beklenen olsa da, gerçekten seni atmak bazı sonuçlar verebilir çünkü is_numeric yerine int döküm kontrolü yaptım.
Francis Lewis

Bu işlevi kullanıyorum, ancak $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');geçerli UTF-8 kodlaması için değişti .
Daantje

Bu çözelti gibi en sıra basit yapar o :-) Bir söylemek: Sen değiştirmek isteyebilirsiniz $object->addChild($key, $value);için $object->addChild($key, htmlspecialchars($value));$ değer "&" o ihtiyaç XML kodlama gibi karakterler içerdiğinde başarısız engellemek için.
leo

38
<? Php
fonksiyon dizi_to_xml (dizi $ arr, SimpleXMLElement $ xml)
{
    foreach ($ arr olarak $ k => $ v) {
        is_array (v $)
            ? array_to_xml ($ v, $ xml-> addChild ($ k))
            : $ xml-> addChild ($ k, $ v);
    }
    dönüş $ xml;
}

$ test_array = dizi (
    'bla' => 'blub',
    'foo' => 'bar',
    'another_array' => dizi (
        'stack' => 'taşma',
    ),
);

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

1
diziniz sayısal dizinlere sahip bir iç dizi içeriyorsa bu başarısız olur. <0> ... </0> geçerli bir XML değil.
Adriano Varoli Piazza

@AdrianoVaroliPiazza sadece $k = (is_numeric($k)) ? 'item' : $k;içinde gibi bir şey ekleyinforeach()
AlienWebguy

Dizideki anahtarlardan birine "gövde" adı verilirse, çalışmaz - daha kesin olarak, anahtar yoksayılır ve yönlendirilir. Nedenini anlamaya çalışıyorum.
Bambax

@Bambax Düşünebilmemin tek nedeni, XML'nin daha sonraki bir noktada HTML olarak ayrıştırılmasıdır.
Brilliand

16

PHP 5.4'den

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

Seçilen cevaptan düz bir kopya gibi görünüyor, sadece bir fonksiyona koy.
phaberest

Bu gibi addChild bölümüne htmlspecialchars () eklemek istiyorum: $ xml-> addChild ($ key, htmlspecialchars ($ değer));
Tyreal

15

Başka bir gelişme:

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

Kullanımı:

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

Teşekkür ederim! İşleviniz herhangi bir n boyutlu dizinin tam içeriğini döndürür.
besciualex

12

İşte benim giriş, basit ve temiz ..

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

Neyse ... Onokazu'nun kodunu aldım (teşekkürler!) Ve XML'de tekrarlanan etiketlere sahip olma yeteneğini ekledim, aynı zamanda nitelikleri de destekliyor, umarım birisi yararlı buluyor!

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

Kodu daha net hale getirmek için değişikliklerinizi yorumlamak yardımcı olabilir; yine de, güzel bir ek
StormeHawke

Bu benim için WP All Export ile çalıştı. Biraz is_numeric kısmını değiştirmek zorunda: if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
başarıların

4

Ben PHP ve jQuery vb ileri geri geçmek için xml oluşturmak için bir süre geri yazdım bir çift fonksiyonları kullanın ... Ne de herhangi bir ek çerçeveler sadece daha sonra sadece SimpleXML (veya başka bir çerçeve ile kullanılabilecek bir dize oluşturur ) ...

Herkes için yararlıysa, lütfen kullanın :)

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

Hepsine sevgiler :)


4

Bir dizi içindeki tüm öğeleri alıp öznitelik olarak ve tüm dizileri alt öğeler olarak ele alacak bir kod istedim.

Yani böyle bir şey için

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

Böyle bir şey alırdım

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

Bunu başarmak için kod aşağıdadır, ancak çok dikkatli olun, özyinelemelidir ve aslında bir yığın akışına neden olabilir :)

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

Bazı öğelerin öznitelik olarak değil, veri bölümünün içine yerleştirilmesi için dizinin uzunluğu için denetimler eklemek isteyebilirsiniz.


4

Buradaki diğer her şeye dayanarak, sayısal endeksleri + nitelikleri önekleme ile işler @ve mevcut düğümlere xml enjekte edebilir:

kod

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

kullanım

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

Sonuç

<?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'i biçimlendirme

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

Sayısal etiketler yerine alt öğeler olarak yinelenen güncellenmiş bir sürüm: github.com/zaus/forms-3rdparty-xpost/blob/…
drzaus

3

İşte benim için hile yapan bir işlev:

Sadece şöyle bir şeyle ara

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

Üzerinde çalıştığım XMLParser'ı kullanabilirsiniz .

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

Şunlarla sonuçlanır:

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

3

Bu çözümü orijinal soruna benzer buldum

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

Yukarıdaki cevapların çoğu doğrudur. Ancak, array_walk_recursive uyumluluk sorunu ve aynı zamanda sayısal anahtarlar sorunu çözen bu cevap geldi. Ayrıca yaptığım tüm testleri geçti:

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

Ayrıca yararlı bulabileceğiniz bir test sınıfı ekledim:

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

diğer çözüm:

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

Bunun methodCall, methodName, skaler ve vektörler, vb. Gibi şeyler ile RPC-tarzı XML oluşturma beklenmedik bir etkisi vardır.
Volomike

3

Dizi ilişkilendirilebilir ve doğru şekilde anahtarlanmışsa, önce xml'ye dönüştürmek daha kolay olur. Gibi bir şey:

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

Diğer yol, önce temel xml'nizi oluşturmak,

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

ve sonra dizinizin her bölümü için, metin oluşturma döngüme benzer bir şey kullanın ve bunun yerine dizinin her düğümü için "addChild" simpleksml işlevlerini kullanın.

Bunu daha sonra deneyeceğim ve bu yayını her iki sürümle de güncelleyeceğim.


"<diz> </array>" dan bahsettiğim bu bit, dize sürümünün benzer bir şeye ihtiyacı olduğunu anlamamı sağladı. Temelde dizinin çok dışında bir düğüm olması gerekir. Her şeyde uyuyayım, ilk hatayı hemen yakalayan bir şeyim olacak.
Anthony

2

Yukarıdaki işlevde yapılan bir düzenleme, bir tuş sayısal olduğunda, "key_" ön ekini ekleyin

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

Doğrudan kodunuzda aşağıdaki işlevi kullanabilirsiniz,

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

}

Diziniz olarak ilk argümanlı işlevi çağırın ve ikinci argüman 1 olmalı, mükemmel girinti için bu artırılacak ve üçüncüsü de doğru olmalıdır.

örneğin, dönüştürülecek dizi değişkeni $ dizi1 ise, çağrı olur, çağrı işlevi <pre>etiketi ile kapsüllenmelidir .

  artoxml ($ array1,1, true);   

Dosyayı yürüttükten sonra lütfen sayfa kaynağına bakın, çünkü <ve> sembolleri html sayfasında görüntülenmez.


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

Bu DOMDocument xml oluşturmak için mükemmel bir seçenektir. @Andrey
altsyset 03

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

Bu işlev örneğin sayısal dizinler için <obj>...</obj> <obj> ... </obj> XML etiketlerinin bir listesini döndürür.

Giriş:

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

Çıktı:

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

Bu, tüm ortak ihtiyaçları karşılamalıdır. Belki 3. satırı şu şekilde değiştirebilirsiniz:

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

veya s ile biten çoğullarla çalışıyorsanız:

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

1

FluidXML ile , bir PHP Dizisinden başlayarak, SimpleXML için bir XML ... sadece iki satır kod oluşturabilirsiniz.

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

Örnek bir dizi olabilir

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

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


0

Ayrıntılı bir xml sorun değilse diziden bir xml oluşturmak için xmlrpc_encode kullanabilirsiniz. www.php.net/xmlrpc_encode

ilişkilendirilebilir ve / veya sayısal anahtarlar kullanmanız durumunda oluşturulan xml'nin farklılık göstermesine dikkat edin

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

Bu işlev desteklenmemektedir ve aslında PHP 5.2.16 veya PHP 5.3.5 sürümlerimde sağlanmamıştır. (“PHP Önemli hata döndürür: xmlrpc_encode ()” tanımsız işlevine çağrı)
danorton

php.ini içinde aşağıdaki satırı uncomment gerekir: extension = php_xmlrpc.dll
w35l3y

@ w35l3y Ben ini kontrol ettim. Hatta bu uzantıyı içermiyor ve ben v 5.3.6 kullanıyorum.
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

Cevabım, başkalarının cevaplarını bir araya getirerek. Bu, sayısal anahtarları telafi edememesi için düzeltilmelidir:

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

array_to_xml()Fonksiyon dizisi ilk sayısal tuşlar oluşur varsayar. Dizinizin bir ilk öğesi olsaydı, foreach()ve $elemifadelerini array_to_xml()işlevden çıkarır ve $xmlonun yerine geçersiniz .


0

Sayısal olarak dizine alınmış iç diziler varsa, yapıyı korumaz ve kötü xml üretir, çünkü en çok oy verilen ikinci cevabı yorumlardım.

Buna dayanarak kendi versiyonumu geliştirdim, çünkü veri yapısından bağımsız olarak json ve xml arasında basit bir dönüştürücüye ihtiyacım vardı. Sürümüm, sayısal anahtar bilgilerini ve orijinal dizinin yapısını korur. Sayısal anahtar içeren anahtar özniteliğiyle değerleri değer adlandırılmış öğelere sarılarak sayısal olarak dizinlenmiş değerler için öğeler oluşturur.

Örneğin

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

dönüşür

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

Array_to_xml -function sürümüm (umarım birine yardımcı olur :)

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

Tüm XML yapısı $ data Array içinde tanımlanır:

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

Magento'da çalışıyorsanız ve bu tür ilişkisel diziniz varsa

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

ilişkilendirilebilir diziyi xml biçimine dönüştürmek en iyisi bu kodu denetleyici dosyasında kullanın.

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

Umarım herkese yardımcı olur.


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);
    }
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.