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


当前回答

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

其他回答

这是我的入口,简单而干净。

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

我认为上面所有的解决方案都很好,但我看到目前为止,它并没有真正创建一个准确的格式良好的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>


 

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

如果冗长的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);
?>

一个简短的例子:

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

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

测试数组

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