Cách chuyển đổi mảng thành SimpleXML


Câu trả lời:


209

một đoạn ngắn:

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

kết quả trong

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

các khóa và giá trị được hoán đổi - bạn có thể sửa lỗi đó array_flip()trước mảng_walk. array_walk_recursiveyêu cầu PHP 5. array_walkthay vào đó bạn có thể sử dụng , nhưng sau đó bạn sẽ không nhận được 'stack' => 'overflow'trong xml.


53
Điều này sẽ không hoạt động nếu $ test_array có 'more_another_array' như 'Another_array', vì khóa 'Another_array' không được chuyển đổi. Do đó, bạn sẽ có nhiều '<overflow> stack </ overflow>'.
understack

11
Các array_flipsẽ không làm việc vì nó không thể mảng lật (như another_arraybên trong các mảng chính).
Lode

14
Phần tử xml "Another_array" ở đâu? Mọi thứ đều được làm phẳng :(
FMaz008

2
Hoạt động rất tốt khi tôi thêm mảng_flip trước mảng_walk_recursive. cảm ơn.
Mike Purcell

12
Downvote vì array_flipchỉ hoạt động nếu mảng không chứa các giá trị giống hệt nhau.
Martijn

385

Đây là mã php 5.2 sẽ chuyển đổi mảng có độ sâu bất kỳ sang tài liệu 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 được tạo sẽ là:

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

Đoạn mã 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');

?>

Tài liệu về SimpleXMLElement::asXMLsử dụng trong đoạn trích này


40
IMO, đây là một giải pháp tốt hơn nhiều so với câu trả lời được chấp nhận. Tuy nhiên, điều này có giới hạn là với các mảng được khóa bằng số, nó tạo ra XML không đúng định dạng. <0> <1> <2> không phải là tên nút hợp lệ.
KOGI

2
Tuy nhiên, nó sẽ làm gì nếu mảng khóa số của bạn chỉ chứa một mảng khác không được khóa bằng số, thì nó sẽ không.
Bryan Petty

15
@KOGI Tôi đã sửa đổi câu trả lời Hanmant. Bây giờ hỗ trợ mảng đa cấp. pastebin.com/pYuXQWee
Mifas

1
Ví dụ này rõ ràng thoát các ký tự đặc biệt trong dữ liệu văn bản phần tử bằng cách sử dụng htmlspecialchars, nhưng SimpleXMLEuity :: addChild tự động dịch các ký tự đặc biệt xml sang các thực thể char của chúng để có thể bỏ qua htmlspecialchars. Thật thú vị, điều này dường như không dẫn đến dữ liệu thoát gấp đôi.
mbaynton

3
@Alex, Chỉnh sửa số 5 của bạn làm cho ví dụ thất bại. Nó chèn <item $ x> trước mỗi bản ghi <student> làm cho đầu ra XML không như ý muốn của tác giả. Có thể cung cấp một ví dụ về vấn đề bạn đang cố gắng khắc phục và chúng tôi có thể tìm giải pháp khác cho cả hai trường hợp. Mất một lúc trước khi tôi nhận ra mã tác giả đã được sửa đổi.
Nicholas Blasgen

124

Các câu trả lời được cung cấp ở đây chỉ chuyển đổi mảng thành XML bằng các nút, bạn không thể đặt thuộc tính. Tôi đã viết một hàm php cho phép bạn chuyển đổi một mảng thành php và cũng đặt các thuộc tính cho các nút cụ thể trong xml. Nhược điểm ở đây là bạn phải xây dựng một mảng theo một cách cụ thể với một vài quy ước (chỉ khi bạn muốn sử dụng các thuộc tính)

Ví dụ sau đây cũng sẽ cho phép bạn đặt các thuộc tính trong XML.

Nguồn có thể được tìm thấy ở đây: 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
Tôi cho rằng không ai phản ứng về điều này. Lớp này thực sự hữu ích vì nó làm ngược lại với những gì SimpleXMLEuity sẽ tạo ra. Vì vậy, nó cung cấp cho bạn khả năng sử dụng SimpleXMLEuity theo cả hai cách.
FMaz008

4
Tôi sẽ đánh dấu nó là câu trả lời thay vì hiện tại. Câu trả lời hiện tại không xây dựng mảng đệ quy
Oleksandr IY

2
Lớp học đẹp. Tôi đã thay đổi dòng 128 if(!is_array($arr)) {thành if(!is_array($arr) && $arr !== '') {để nó không nối thêm một nút văn bản mới cho các chuỗi trống và do đó giữ định dạng thẻ tốc ký trống tức 'tag'=>''<tag/>thay vì<tag></tag>
user1433150

Đây là câu trả lời tốt nhất cho đến nay. Ngoài ra, điều này có cấu trúc chính xác của nhiều mục có cùng khóa: Thứ nhất là khóa tên nút, sau đó nó chứa mảng với các khóa số. (ngược lại với câu trả lời của Hanmant)
Vasil Popov

1
Tìm thấy một github từ tác giả @Legionar github.com/digitickets/lalit/blob/master/src/Array2XML.php
Daryl Teo

57

Tôi tìm thấy tất cả các câu trả lời để sử dụng quá nhiều mã. Đây là một cách dễ dàng để làm điều đó:

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

Sau đó, việc gửi mảng vào hàm là một vấn đề đơn giản, vì vậy nó sẽ xử lý một mảng đa chiều:

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

Bây giờ $ xml chứa một đối tượng XML đẹp dựa trên mảng của bạn chính xác như cách bạn đã viết nó.

print $xml->asXML();

9
Tôi thích giải pháp này nhất. Mặc dù, thật tuyệt khi thêm một bài kiểm tra trên các phím số, như : if ( is_numeric( $key ) ) $key = "numeric_$key"; .
Wout

@wout Bắt tốt. Thêm. Tôi đã thực hiện kiểm tra int cast thay vì is_numeric vì is_numeric có thể cung cấp một số, mặc dù về mặt kỹ thuật, kết quả sẽ thực sự làm bạn thất vọng.
Francis Lewis

Tôi sử dụng chức năng này, nhưng đã thay đổi $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');để mã hóa UTF-8 hợp lệ.
Daantje

Tôi như giải pháp này cũng nhất, đơn giản làm nó :-) Một nhận xét: Bạn có thể muốn thay đổi $object->addChild($key, $value);để $object->addChild($key, htmlspecialchars($value));ngăn chặn nó từ thất bại khi $ value chứa các ký tự như "&" mà nhu cầu XML-mã hóa.
leo

38
<?
hàm Array_to_xml (mảng $ Array, SimpleXMLEuity $ xml)
{
    foreach ($ Array là $ k => $ v) {
        is_array ($ v)
            ? mảng_to_xml ($ v, $ xml-> addChild ($ k))
            : $ xml-> addChild ($ k, $ v);
    }
    trả lại $ xml;
}

$ test_array = mảng (
    'bla' => 'blub',
    'foo' => 'thanh',
    'Another_array' => mảng (
        'ngăn xếp' => 'tràn',
    ),
);

echo mảng_to_xml ($ test_array, SimpleXMLEuity mới ('<root />')) -> asXML ();

1
điều này không thành công nếu mảng của bạn chứa một mảng bên trong với các chỉ mục số. <0> ... </ 0> không phải là XML hợp lệ.
Quảng trường Adriano Varoli

@AdrianoVaroliP Square chỉ cần thêm một cái gì đó như $k = (is_numeric($k)) ? 'item' : $k; bên trongforeach()
AlienWebguy

Nếu một trong các khóa trong mảng được đặt tên là "body", thì nó không hoạt động - chính xác hơn, khóa bị bỏ qua và di chuyển ngang. Cố gắng tìm hiểu tại sao.
Bambax

@Bambax Lý do duy nhất tôi có thể nghĩ đến là nếu XML được phân tích cú pháp dưới dạng HTML tại một số điểm sau đó.
Brilliand

16

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

Có vẻ như một bản sao thẳng từ câu trả lời đã chọn, chỉ cần đưa vào một chức năng.
phaberest

Tôi sẽ thêm htmlspecialchars () vào phần addChild, như thế này: $ xml-> addChild ($ key, htmlspecialchars ($ value));
Tyreal

15

Một cải tiến khác:

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

Sử dụng:

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

Cảm ơn bạn! Hàm của bạn trả về nội dung chính xác của bất kỳ mảng n chiều nào.
ambciualex

12

Đây là mục nhập của tôi, đơn giản và sạch sẽ ..

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

Vì vậy, dù sao đi nữa ... tôi đã lấy mã của onokazu (cảm ơn!) Và thêm khả năng có các thẻ lặp lại trong XML, nó cũng hỗ trợ các thuộc tính, hy vọng ai đó thấy nó hữu ích!

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

Có thể hữu ích để nhận xét các thay đổi của bạn để làm cho mã rõ ràng hơn; Tuy nhiên, bổ sung tốt đẹp
StormeHawke

Điều này làm việc cho tôi với WP All Export. Tôi đã phải thay đổi phần is_numeric một chút: if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
achiever

4

Tôi sử dụng một vài hàm mà tôi đã viết trước đây để tạo xml để truyền qua lại từ PHP và jQuery, v.v ... Không sử dụng bất kỳ khung công tác bổ sung nào chỉ đơn thuần tạo ra một chuỗi có thể được sử dụng với SimpleXML (hoặc khung khác ) ...

Nếu nó hữu ích cho bất cứ ai, xin vui lòng sử dụng 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;
}   

Yêu tất cả :)


4

Tôi muốn một mã sẽ lấy tất cả các phần tử bên trong một mảng và coi chúng là các thuộc tính và tất cả các mảng là các phần tử phụ.

Vì vậy, đối với một cái gì đó như

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

Tôi sẽ nhận được một cái gì đó như thế này

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

Để đạt được điều này, mã bên dưới, nhưng hãy cẩn thận, nó được đệ quy và thực sự có thể gây ra một 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();
} 

Bạn có thể muốn thêm kiểm tra độ dài của mảng để một số phần tử được đặt bên trong phần dữ liệu chứ không phải là một thuộc tính.


4

Dựa trên mọi thứ khác ở đây, xử lý các chỉ số + thuộc tính thông qua tiền tố với @ và có thể tiêm xml vào các nút hiện có:

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

Sử dụng

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

Kết quả

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

Phần thưởng: Định dạng 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

Phiên bản cập nhật lặp lại dưới dạng các phần tử con thay vì thẻ số: github.com/zaus/forms-3rdparty-xpost/blob/
Kẻ

3

Đây là một chức năng đã lừa tôi:

Chỉ cần gọi nó với một cái gì đó như

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

Bạn có thể sử dụng XMLParser mà tôi đang làm việc.

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

Sẽ dẫn đến:

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

3

Tôi thấy giải pháp này tương tự như vấn đề ban đầu

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

Hầu hết các câu trả lời trên là chính xác. Tuy nhiên, tôi đã đưa ra câu trả lời này để giải quyết vấn đề tương thích mảng_walk_recursive và cả vấn đề về phím số. Nó cũng vượt qua tất cả các bài kiểm tra tôi đã thực hiện:

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

Tôi cũng đã thêm một lớp kiểm tra cho cái này mà bạn có thể thấy hữu ích:

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

giải pháp khác:

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

Điều này có tác dụng không mong muốn khi tạo XML theo kiểu RPC với các công cụ như methodCall, methodName, vô hướng và vectơ, v.v. Nó không thực sự chuyển đổi một mảng thành XML theo nghĩa đơn giản.
Volomike

3

NẾU mảng được kết hợp và khóa chính xác, có thể dễ dàng biến nó thành xml trước. Cái gì đó như:

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

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

Lộ trình khác sẽ là tạo xml cơ bản của bạn trước, như

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

và sau đó cho từng phần của mảng của bạn, sử dụng một cái gì đó tương tự như vòng lặp tạo văn bản của tôi và thay vào đó sử dụng các hàm đơn giản "addChild" cho mỗi nút của mảng.

Tôi sẽ thử nó sau và cập nhật bài viết này với cả hai phiên bản.


Đó là nơi tôi đã đề cập "<mảng> </ mảng>" khiến tôi nhận ra rằng phiên bản chuỗi cần một cái gì đó tương tự. Về cơ bản, mảng phải có một nút ở bên ngoài. Hãy để tôi ngủ trên tất cả mọi thứ, tôi sẽ có một cái gì đó bắt lỗi ngay từ đầu.
Anthony

2

Chỉ cần chỉnh sửa một chức năng ở trên, khi một khóa là số, hãy thêm tiền tố "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

Bạn có thể sử dụng chức năng sau đây trong mã của bạn trực tiếp,

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

}

Gọi hàm với đối số thứ nhất là mảng của bạn và đối số thứ hai phải là 1, điều này sẽ được tăng lên để thụt lề hoàn hảo và thứ ba phải là đúng.

ví dụ: nếu biến mảng được chuyển đổi là $ mảng1 thì việc gọi sẽ là, hàm gọi sẽ được gói gọn bằng <pre>thẻ.

  artoxml ($ mảng1,1, đúng);   

Vui lòng xem nguồn trang sau khi thực hiện tệp, vì các ký hiệu <và> sẽ không được hiển thị trong trang 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;
}

Đây là tùy chọn tuyệt vời để tạo DOMDocument xml. Cảm ơn @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;
}

Ví dụ, hàm này trả về một danh sách các thẻ <obj> ... </ obj> <obj> ... </ obj> cho các chỉ mục số.

Đầu vào:

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

Đầu ra:

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

Điều này sẽ đáp ứng tất cả các nhu cầu chung. Có lẽ bạn có thể thay đổi dòng thứ 3 thành:

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

hoặc nếu bạn đang làm việc với số nhiều kết thúc bằng s:

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

1

Với FluidXML bạn có thể tạo, bắt đầu từ một Mảng PHP , một XML cho SimpleXML với ... chỉ hai dòng mã.

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

Một mảng ví dụ có thể là

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

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


0

Bạn có thể sử dụng xmlrpc_encode để tạo xml từ mảng nếu xml dài dòng không phải là vấn đề. www.php.net/xmlrpc_encode

hãy cẩn thận các xml được tạo khác nhau trong trường hợp bạn sử dụng các phím kết hợp và / hoặc số

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

Hàm này không được hỗ trợ và trên thực tế, không được cung cấp trong các bản dựng PHP 5.2.16 hoặc PHP 5.3.5 của tôi. (trả về Lỗi PHP chết người: Gọi hàm không xác định xmlrpc_encode (),)
danorton

bạn phải bỏ dòng sau trong php.ini: extension = php_xmlrpc.dll
w35l3y

@ w35l3y Tôi đã kiểm tra ini của tôi. Nó thậm chí không chứa phần mở rộng đó và tôi đang sử dụng phiên bản 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

Câu trả lời của tôi, lắp ghép câu trả lời của người khác. Điều này sẽ sửa cho lỗi không bù cho các phím số:

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

Các array_to_xml()chức năng giả định rằng mảng được tạo thành từ các phím số đầu tiên. Nếu mảng của bạn có một phần tử ban đầu, bạn sẽ bỏ các câu lệnh foreach()$elemcâu lệnh từ array_to_xml()hàm và chỉ cần truyền $xmlvào.


0

Tôi đã nhận xét câu trả lời được bình chọn nhiều thứ hai, bởi vì nó không bảo toàn cấu trúc và tạo ra xml xấu nếu có các mảng bên trong được lập chỉ mục bằng số.

Tôi đã phát triển phiên bản của riêng mình dựa trên nó, bởi vì tôi cần bộ chuyển đổi đơn giản giữa json và xml bất kể cấu trúc dữ liệu. Phiên bản của tôi bảo tồn thông tin khóa số và cấu trúc của mảng ban đầu. Nó tạo ra các phần tử cho các giá trị được lập chỉ mục bằng số bằng cách gói các giá trị thành các phần tử có tên giá trị với thuộc tính khóa có chứa khóa số.

Ví dụ

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

chuyển đổi thành

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

Phiên bản của tôi về mảng_to_xml (hy vọng nó sẽ giúp được ai đó :)

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

Toàn bộ cấu trúc XML được định nghĩa trong $ 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

Nếu bạn làm việc trong magento và bạn có loại mảng kết hợp này

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

thì đây là cách tốt nhất để chuyển mảng kết hợp thành định dạng xml. Sử dụng mã này trong tệp điều khiể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;
}
}

Tôi hy vọng nó sẽ giúp tất cả.


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);
    }
  }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.