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


当前回答

我认为上面所有的解决方案都很好,但我看到目前为止,它并没有真正创建一个准确的格式良好的XML,因为数组键与$my_array[main_node][multiple_values][] = ARRAY ('id' => '1')然后转换为

    <main_node>
       <multiple_values>
         <0>
           <id>1 test</id>
         </0>
       </multiple_values>
       <multiple_values>
         <1>
          <id>2 test</id>
         </1>
       </multiple_values>
    </main_node>

这是XML解析器方面的一个问题……

I should be like this:

    <main_node>
     <multiple_values>
      <id>1 test</id>
     </multiple_values>
     <multiple_values>
      <id>2 test</id>
     </multiple_values>
    </main_node>

如果你用load_simple_xml来解析…你会得到完全相同的数组/对象结构。

我的函数还自动创建正确的根节点。

    // Code to convert php array to xml document 20211112
    function array2xml(array $data, $xml_class_obj = '', $group_by_parent_allowed = '', $options = array())
        {   
            
            if(!$xml_class_obj) :
                $is_root = 1;
                $xml_class_obj = new XMLWriter();
                $xml_class_obj->openMemory();
                $xml_class_obj->setIndent(TRUE);
                $xml_class_obj->setIndentString('   ');
                if($options['encoding'] != '')  $xml_class_obj->startDocument('1.0', $options['encoding']);
                else                                                        $xml_class_obj->startDocument('1.0');
            endif;
            
            foreach ($data as $key => $value) {

                if (is_array($value)) { // IS ARRAY

                    // check if allow below keys are int, if yes group them to same parent tree
                    $group_by_parent = $key;
                    foreach(array_keys($value) as $c_keys) :
                        if(!is_int($c_keys)) $group_by_parent = '';
                    endforeach;

                    if(empty($group_by_parent)) $xml_class_obj->startElement($key); 
                    if($group_by_parent_allowed != '') $xml_class_obj->startElement($group_by_parent_allowed);
                    
                    $this->array2xml($value, $xml_class_obj, $group_by_parent, $options);
                    
                    if(empty($group_by_parent)) $xml_class_obj->endElement();  

                } else { // IS VALUE
                    
                    if(is_string($value)) :
                        $xml_class_obj->startElement($key);
                        $xml_class_obj->writeCData($value);         
                        $xml_class_obj->endElement();           
                    else :
                        $xml_class_obj->writeElement($key, $value); 
                    endif;

                }

            } // foreach
            
            if($group_by_parent_allowed != '')  $xml_class_obj->endElement(); 
            
            if($is_root == 1) :
            
                $xml_class_obj->endDocument();
                return $xml_class_obj->outputMemory();
            else :              
                return $xml_class_obj;                  
            endif;
              
        }  
    
    // usage
    $ary_new_xml = array();
    $ary_new_xml['order']['customer']['customerid'] = '123456'; 
    $ary_new_xml['order']['customer']['customertype'] = 15; 
            
    $ary_new_xml['order']['orderprio'] = 2; 
            
    $ary_new_xml['order']['orderpos'][] = array('sku' => 9999910001111, 'quantity' => 3);           
    $ary_new_xml['order']['orderpos'][] = array('sku' => 9999910002222, 'quantity' => 1); 
            
echo array2xml($ary_new_xml,'','',array('enconding' => 'UTF-8'));

结果:

<?xml version="1.0" encoding="UTF-8"?>
<order>
   <customer>
      <customerid>82936639</customerid>
      <customertype>15</customertype>
   </customer>
   <orderprio>2</orderprio>
   <orderpos>
      <sku>9999910001111</sku>
      <quantity>3</quantity>
   </orderpos>
   <orderpos>
      <sku>9999910002222</sku>
      <quantity>1</quantity>
   </orderpos>
</order>


 

我希望这能帮助到一些人;)

其他回答

如果你使用magento,你有这种类型的关联数组

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

那么最好将关联数组转换为XML格式。在控制器文件中使用此代码。

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

我希望这对大家都有帮助。

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

对于像这样的东西

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

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

如果冗长的xml不成问题,可以使用xmlrpc_encode从数组创建xml。 www.php.net/xmlrpc_encode

注意,如果使用关联键和/或数字键,创建的XML会有所不同

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

使用FluidXML,您可以从一个PHP数组开始,生成一个用于SimpleXML的XML…只有两行代码。

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

一个示例数组可以是

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

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

一个简短的例子:

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