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


当前回答

我想要一个代码,将一个数组内的所有元素,并把它们作为属性,所有数组作为子元素。

对于像这样的东西

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

我会得到这样的结果

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

要实现这一点,代码如下,但要非常小心,它是递归的,实际上可能会导致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();
} 

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

其他回答

下面讨论名称空间。在本例中,构造包装器以包含名称空间定义,并将其传递给函数。使用冒号来标识命名空间。

测试数组

$inarray = [];
$inarray['p:apple'] = "red";
$inarray['p:pear'] = "green";
$inarray['p:peach'] = "orange";
$inarray['p1:grocers'] = ['p1:local' => "cheap", 'p1:imported' => "expensive"];


$xml = new SimpleXMLElement( '<p:wrapper xmlns:p="http://namespace.org/api" xmlns:p1="http://namespace.org/api2 /> ');

array_to_xml($xml,$inarray); 




function array_to_xml(SimpleXMLElement $object, array $data)
{   
    $nslist = $object->getDocNamespaces();

    foreach ($data as $key => $value)
    {   
        $nspace = null;
        $keyparts = explode(":",$key,2);
        if ( count($keyparts)==2) 
            $nspace = $nslist[$keyparts[0]];

        if (is_array($value))
        {   
            $key = is_numeric($key) ? "item$key" : $key;
            $new_object = $object->addChild($key,null,$nspace);
            array_to_xml($new_object, $value);
        }   
        else
        {   
            $key = is_numeric($key) ? "item$key" : $key;
            $object->addChild($key, $value,$nspace);
        }   
    }   
}   
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();
}

我的答案,拼凑别人的答案。这应该可以纠正无法补偿数字键的错误:

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()函数假定数组首先由数字键组成。如果数组有一个初始元素,则可以从array_to_xml()函数中删除foreach()和$elem语句,只传递$xml。

一个简短的例子:

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

结果

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

键和值会被交换——你可以在array_walk之前用array_flip()来修复这个问题。array_walk_recursive需要PHP 5。你可以用array_walk代替,但你不会得到'stack' => 'overflow'在XML中。

其他解决方案:

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