如何将数组转换为SimpleXML

277 php xml arrays simplexml

如何在PHP中将数组转换为SimpleXML对象?

Han*_*ant 378

这是php 5.2代码,它将任何深度的数组转换为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
                        )   
                )

        )
)
Run Code Online (Sandbox Code Playgroud)

生成的XML将如下:

<?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>
Run Code Online (Sandbox Code Playgroud)

PHP片段

<?php
// function definition to convert array to xml
function array_to_xml( $data, &$xml_data ) {
    foreach( $data as $key => $value ) {
        if( is_numeric($key) ){
            $key = 'item'.$key; //dealing with <0/>..<n/> issues
        }
        if( is_array($value) ) {
            $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');

?>
Run Code Online (Sandbox Code Playgroud)

SimpleXMLElement::asXML此代码段中使用的文档

  • 这是IMO,比接受的答案要好得多.但是,这有一个限制,即使用数字键控数组,它会生成格式错误的XML.<0> <1> <2>不是有效的节点名称. (40认同)
  • @KOGI我修改了Hanmant的答案.现在它支持多级数组.http://pastebin.com/pYuXQWee (15认同)
  • 应该发布两个答案,这个修改后的答案打破了我的要求,因为它添加了“&lt;itemN&gt;&lt;/itemN&gt;”。本次修订:http://stackoverflow.com/revisions/5965940/2 是我的赢家 (4认同)
  • 此示例使用 htmlspecialchars 显式转义元素文本数据中的特殊字符,但 SimpleXMLElement::addChild 会自动将 xml 特殊字符转换为其 char 实体,因此可以省略 htmlspecialchars。有趣的是,这似乎_不会_导致数据双重转义。 (3认同)
  • @Alex,您的Edit#5使示例失败.它在每个<student>记录之前插入<item $ x>,使XML输出不是作者想要的.也许提供一个您正在尝试修复的问题的示例,我们可以为这两种情况找到另一种解决方案.在我意识到作者代码被修改之前,我花了一些时间. (3认同)
  • 但是,如果您的数字键控数组只包含另一个非数字键控的数组,则它不会. (2认同)

ax.*_*ax. 202

一个简短的:

<?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();
Run Code Online (Sandbox Code Playgroud)

结果是

<?xml version="1.0"?>
<root>
  <blub>bla</blub>
  <bar>foo</bar>
  <overflow>stack</overflow>
</root>
Run Code Online (Sandbox Code Playgroud)

键和值是交换的 - 您可以array_flip()在array_walk之前修复它.array_walk_recursive需要PHP 5.你可以使用array_walk,但你不会进入'stack' => 'overflow'xml.

  • 如果$ test_array具有'more_another_array'之类的'another_array',则无效,因为未转换键'another_array'.因此,您将有多个'<overflow> stack </ overflow>'. (53认同)
  • 哪个是"another_array"xml元素?一切都变平了:( (14认同)
  • `array_flip`不起作用,因为它不能翻转数组(如主数组中的`another_array`). (11认同)
  • Downvoting是因为`array_flip`仅在数组不包含相同值时才有效. (11认同)
  • 当我在array_walk_recursive之前添加array_flip时工作得很好.谢谢. (2认同)
  • Downvoted.翻转键/值不起作用,因为值不是唯一的,并且会相互覆盖.同时尝试翻转多维数组会使PHP出现"警告". (2认同)
  • 由于格式向后,这是一个糟糕的解决方案。完全没有意义。 (2认同)
  • 投反对票 - 因为,表面上看起来很优雅,array_flip 的需要使得这非常无用。 (2认同)
  • 投反对票,未添加多维数组,“another_array”在哪里? (2认同)
  • 投反对票是因为一个不起作用的解决方案到底是如何被签名为顶部的?谁需要转换非多维的 xml!? (2认同)

小智 119

这里提供的答案只将数组转换为带节点的XML,您无法设置属性.我编写了一个php函数,允许您将数组转换为php,并为xml中的特定节点设置属性.这里的缺点是你必须以一种特殊的方式构造一个数组,几乎没有约定(只有你想使用属性)

以下示例将允许您在XML中设置属性.

详细示例和用法可在此处找到:http: //www.lalit.org/lab/convert-php-array-to-xml-with-attributes/

<?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>
*/
?>
Run Code Online (Sandbox Code Playgroud)

  • 我觉得没有人对此作出任何反应.这个类非常有用,因为它与simpleXMLElement将生成的相反.因此,它为您提供了两种方式使用SimpleXMLElement的可能性. (8认同)
  • 我会把它标记为答案而不是当前.目前的答案不是构建递归数组 (4认同)
  • 好课。我将第128行if(!is_array($ arr)){`更改为`if(!is_array($ arr)&amp;&amp; $ arr!==''){`,以便不会为空添加新的文本节点字符串,因此保留简写的空标签格式,即`'tag'=&gt;''`是`&lt;tag /&gt;`而不是`&lt;tag&gt; &lt;/ tag&gt;` (2认同)

Fra*_*wis 53

我找到了使用太多代码的所有答案.这是一个简单的方法:

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);
        }   
    }   
}   
Run Code Online (Sandbox Code Playgroud)

然后将数组发送到使用递归的函数是一件简单的事情,因此它将处理一个多维数组:

$xml = new SimpleXMLElement('<rootTag/>');
to_xml($xml, $my_array);
Run Code Online (Sandbox Code Playgroud)

现在$ xml包含一个漂亮的XML对象,它基于你的数组,就像你编写它一样.

print $xml->asXML();
Run Code Online (Sandbox Code Playgroud)

  • 我最爱这个解决方案.虽然,在数字键上添加测试会很好,例如:`if(is_numeric($ key))$ key ="numeric_ $ key"; `. (7认同)
  • 我喜欢这个答案,它更明确。:) (2认同)

小智 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);
    }
    return $xml;
}

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

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

  • 如果您的数组包含带有数字索引的内部数组,则此操作会失败。&lt;0&gt;...&lt;/0&gt; 不是有效的 XML。 (2认同)
  • 此外,在同一级别使用相同的名称标签不起作用 (2认同)

小智 16

从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();
}
Run Code Online (Sandbox Code Playgroud)


Syl*_*Syl 15

另一项改进:

/**
* 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();
}
Run Code Online (Sandbox Code Playgroud)

用法:

$this->arrayToXML($array, new SimpleXMLElement('<root/>'), 'child_name_to_replace_numeric_integers');
Run Code Online (Sandbox Code Playgroud)


小智 12

这是我的入门,简单而干净..

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);
Run Code Online (Sandbox Code Playgroud)


小智 8

所以无论如何...我拿了onokazu的代码(谢谢!)并添加了在XML中重复标记的能力,它还支持属性,希望有人发现它有用!

 <?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();
    ?>
Run Code Online (Sandbox Code Playgroud)


小智 5

我想要一个代码,它将获取数组中的所有元素并将它们视为属性,并将所有数组视为子元素。

所以对于像

array (
'row1' => array ('head_element' =>array("prop1"=>"some value","prop2"=>array("empty"))),
"row2"=> array ("stack"=>"overflow","overflow"=>"overflow")
);
Run Code Online (Sandbox Code Playgroud)

我会得到这样的东西

<?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>
Run Code Online (Sandbox Code Playgroud)

为了实现这一点,代码如下,但要非常小心,它是递归的,实际上可能会导致计算器溢出:)

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();
} 
Run Code Online (Sandbox Code Playgroud)

您可能希望添加对数组长度的检查,以便将某些元素设置在数据部分内而不是作为属性。