【问题标题】:How to convert array to SimpleXML如何将数组转换为 SimpleXML
【发布时间】:2010-11-26 16:34:51
【问题描述】:

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

【问题讨论】:

标签: php xml arrays simplexml


【解决方案1】:

如果数组是关联的并且键控正确,那么首先将其转换为 xml 可能会更容易。比如:

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

另一条路线是首先创建您的基本 xml,例如

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

然后对于数组的每个部分,使用类似于我的文本创建循环的内容,而是对数组的每个节点使用 simplexml 函数“addChild”。

我稍后会尝试并用这两个版本更新这篇文章。

【讨论】:

  • 我提到“”的那一点让我意识到字符串版本需要类似的东西。基本上,阵列必须在最外面有一个节点。让我睡一觉吧,我会有一些东西可以立即捕捉到最初的错误。
【解决方案2】:

一个简短的:

<?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,但你不会在 xml 中得到 'stack' =&gt; 'overflow'

【讨论】:

  • 如果 $test_array 有 'more_another_array' 和 'another_array' 一样,这将不起作用,因为键 'another_array' 没有被转换。因此,您将有多个 'stack'。
  • array_flip 不起作用,因为它不能翻转数组(如主数组中的 another_array)。
  • “another_array”xml 元素在哪里?一切都变平了:(
  • 投反对票,因为 array_flip 仅在数组不包含相同值时才有效。
  • 投反对票。翻转键/值不起作用,因为值不是唯一的,并且会相互覆盖。还试图翻转多维数组会使 PHP 崩溃并发出“警告”。
【解决方案3】:

如果详细的 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 5.2.16 或 PHP 5.3.5 版本中也没有提供。 (返回“PHP 致命错误:调用未定义函数 xmlrpc_encode()”)
  • 您必须取消注释 php.ini 中的以下行:extension=php_xmlrpc.dll
  • @w35l3y 我检查了我的ini。它甚至不包含该扩展名,我使用的是 v 5.3.6。
【解决方案4】:
$v) { is_array($v) ? array_to_xml($v, $xml->addChild($k)) : $xml->addChild($k, $v); } 返回 $xml; } $test_array = 数组 ( 'bla' => 'blub', 'foo' => '酒吧', 'another_array' => 数组 ( '堆栈' => '溢出', ), ); echo array_to_xml($test_array, new SimpleXMLElement(''))->asXML();

【讨论】:

  • 如果您的数组包含带有数字索引的内部数组,则此操作将失败。 ...0> 不是有效的 XML。
  • @AdrianoVaroliPiazza 只需在foreach() 内添加类似$k = (is_numeric($k)) ? 'item' : $k; 的内容
  • 如果数组中的一个键被命名为“body”,它就不起作用——更准确地说,键被忽略并遍历。试图找出原因。
  • @Bambax 我能想到的唯一原因是 XML 是否在稍后被解析为 HTML。
【解决方案5】:

这是 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
                        )   
                )

        )
)

生成的 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>

PHP sn-p

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

?>

Documentation on SimpleXMLElement::asXML used in this snippet

【讨论】:

  • 我们使用了这个'echo $xml_student_info->asXML();'直接显示此 xml,但它适用于大型数组数据。当数组数据少于十个元素时,不显示 xml 格式,而只是简单格式。我们使用了这个函数头(“Content-type: text/xml”);以 xml 显示格式。
  • 此示例使用 htmlspecialchars 显式转义元素文本数据中的特殊字符,但 SimpleXMLElement::addChild 会自动将 xml 特殊字符转换为其 char 实体,因此可以省略 htmlspecialchars。有趣的是,这似乎不会导致双重转义数据。
  • Empty Array-values [(string)""] 将被更改为空的 SimpleXML-Node 而不是留空。
  • @Alex,您的编辑 #5 使示例失败。它在每个 记录之前插入 ,从而使 XML 输出不是作者想要的。也许提供您尝试解决的问题的示例,我们可以为这两种情况找到另一种解决方案。我花了一段时间才意识到作者的代码被修改了。
  • 应该发布两个答案,这个修改后的答案打破了我的要求,因为它添加了&lt;itemN&gt;&lt;/itemN&gt;。本次修订:stackoverflow.com/revisions/5965940/2 是我的赢家
【解决方案6】:

这是我的入口,简单干净..

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

【讨论】:

    【解决方案7】:

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

    以下示例也允许您在 XML 中设置属性。

    来源可以在这里找到: 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>
    */
    ?>
    

    【讨论】:

    • 我很惊讶没有人对此作出反应。这个类非常有用,因为它与 simpleXMLElement 生成的相反。因此,它为您提供了两种方式使用 SimpleXMLElement 的可能性。
    • 我会将其标记为答案而不是当前。当前答案未构建递归数组
    • 好课。我将第 128 行 if(!is_array($arr)) { 更改为 if(!is_array($arr) &amp;&amp; $arr !== '') { 以便它不会为空字符串附加新的文本节点,因此保持简写空标记格式,即 'tag'=&gt;''&lt;tag/&gt; 而不是 &lt;tag&gt;&lt;/tag&gt;
    • 这是迄今为止最好的答案。这也具有具有相同键的多个项目的正确结构:第一个是节点名称键,然后它包含带有数字键的数组。 (与汉曼特答案相反)
    • 从作者那里找到一个github @Legionar github.com/digitickets/lalit/blob/master/src/Array2XML.php
    【解决方案8】:

    我使用了我不久前编写的几个函数来生成 xml 以从 PHP 和 jQuery 等来回传递...... 既不使用任何其他框架,也只是纯粹生成一个字符串,然后可以与 SimpleXML(或其他框架)一起使用......

    如果对任何人有用,请使用它:)

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

    爱所有人:)

    【讨论】:

      【解决方案9】:

      只是对上面一个函数的编辑,当key是数字时,添加前缀“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");
                     }
                }
           }
      }
      

      【讨论】:

        【解决方案10】:
        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();
        }
        

        【讨论】:

          【解决方案11】:

          您可以直接在代码中使用以下函数,

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

          以第一个参数作为数组调用函数,第二个参数必须为1,这将增加完美缩进,第三个必须为真。

          例如,如果要转换的数组变量是$array1,那么, 调用就是,调用函数需要封装&lt;pre&gt;标签。

           artoxml($array1,1,true); 

          执行文件后请查看页面源代码,因为符号不会显示在html页面中。

          【讨论】:

            【解决方案12】:

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

            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

            【讨论】:

              【解决方案13】:

              我会评论第二个投票最多的答案,因为如果有数字索引的内部数组,它不会保留结构并生成错误的 xml。

              我基于它开发了自己的版本,因为无论数据结构如何,我都需要简单的 json 和 xml 之间的转换器。我的版本保留了原始数组的数字键信息和结构。它通过将值包装到具有包含数字键的键属性的值命名元素来为数字索引值创建元素。

              例如

              array('test' =&gt; array(0 =&gt; 'some value', 1 =&gt; 'other'))

              转换成

              &lt;test&gt;&lt;value key="0"&gt;some value&lt;/value&gt;&lt;value key="1"&gt;other&lt;/value&gt;&lt;/test&gt;

              我的 array_to_xml -function 版本(希望对某人有所帮助:)

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

              【讨论】:

                【解决方案14】:

                这是一个对我有用的函数:

                只需用类似的东西调用它

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

                【讨论】:

                  【解决方案15】:

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

                  所以对于像

                  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>
                  

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

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

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

                  【讨论】:

                    【解决方案16】:
                    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;
                    }
                    

                    【讨论】:

                    • 这是创建 DOMDocument xml 的绝佳选择。谢谢@Andrey
                    【解决方案17】:

                    整个 XML 结构定义在 $data 数组中:

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

                    【讨论】:

                      【解决方案18】:

                      如果你在 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;
                      }
                      }
                      

                      希望对大家有帮助。

                      【讨论】:

                        【解决方案19】:

                        所以无论如何...我拿了小野的代码(谢谢!)并添加了在 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();
                            ?>
                        

                        【讨论】:

                        • 可能有助于评论您的更改以使代码更清晰;仍然,很好的补充
                        • 这对我来说适用于 WP All Export。我不得不稍微更改 is_numeric 部分:if (is_numeric($k)) { $i = $k + 1; $child = $xml-&gt;addChild("_$i"); array_to_xml($v, $child); }
                        【解决方案20】:

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

                        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 != 0 && $key == (int) $key) {
                                        $key = "key_$key";
                                    }
                        
                                    $object->addChild($key, $value);
                                }   
                            }   
                        }   
                        

                        那么就是简单的将数组发送到函数中,它使用递归,所以它会处理一个多维数组:

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

                        现在 $xml 包含一个漂亮的 XML 对象,它基于您的数组,与您编写它的方式完全相同。

                        print $xml->asXML();
                        

                        【讨论】:

                        • 我最喜欢这个解决方案。不过,最好在数字键上添加一个测试,例如:if ( is_numeric( $key ) ) $key = "numeric_$key";
                        • @wout 很好。添加。我做了一个 int cast 检查,而不是 is_numeric,因为 is_numeric 可以给出一些(虽然在技术上是预期的)结果,这真的会让你失望。
                        • 我使用了这个函数,但是把$xml = new SimpleXMLElement('&lt;?xml version="1.0" encoding="UTF-8" ?&gt;&lt;rootTag/&gt;');改成了有效的UTF-8编码。
                        • 我也最喜欢这个解决方案,很简单 :-) 备注:您可能需要将 $object-&gt;addChild($key, $value); 更改为 $object-&gt;addChild($key, htmlspecialchars($value)); 以防止它在 $value 包含诸如 " 之类的字符时失败&" 需要 XML 编码。
                        • 它有效,但您必须添加三个等号:if ($key === (int) $key) { $key = "key_$key"; }
                        【解决方案21】:

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

                        【讨论】:

                          【解决方案22】:

                          您可以使用我一直在处理的XMLParser

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

                          会导致:

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

                          【讨论】:

                            【解决方案23】:

                            我发现这个解决方案类似于原来的问题

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

                            【讨论】:

                              【解决方案24】:

                              另一个改进:

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

                              用法:

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

                              【讨论】:

                              • 谢谢!您的函数返回任何 n 维数组的确切内容。
                              【解决方案25】:

                              以上大部分答案都是正确的。但是,我想出了这个答案,它解决了 array_walk_recursive 兼容性问题以及数字键问题。它也通过了我所做的所有测试:

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

                              我还为此添加了一个测试类,您可能会发现它很有用:

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

                              【讨论】:

                                【解决方案26】:

                                基于这里的所有其他内容,通过前缀@处理数字索引+属性,并且可以将xml注入现有节点:

                                代码

                                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
                                

                                用法

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

                                结果

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

                                奖励:格式化 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
                                

                                【讨论】:

                                【解决方案27】:

                                以下处理命名空间。在这种情况下,您构造包装器以包含命名空间定义,并将其传递给函数。使用冒号来标识命名空间。

                                测试数组

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

                                【讨论】:

                                  【解决方案28】:

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

                                  【讨论】:

                                  • 这似乎是所选答案的直接副本,只需放入函数中即可。
                                  • 我会将 htmlspecialchars() 添加到 addChild 部分,如下所示: $xml->addChild($key, htmlspecialchars($value));
                                  【解决方案29】:

                                  其他解决方案:

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

                                  【讨论】:

                                  • 这对使用 methodCall、methodName、标量和向量等创建 RPC 样式的 XML 产生了意想不到的效果。它并没有真正将数组转换为直接意义上的 XML。
                                  • xmlrpc_encode_request 函数在 php 7.3 上未定义
                                  【解决方案30】:
                                  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;
                                  }
                                  

                                  此函数返回例如 ...... XML 标记的数字索引列表。

                                  输入:

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

                                  输出:

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

                                  这应该可以满足所有常见的需求。也许您可以将第 3 行更改为:

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

                                  或者如果你正在使用以 s 结尾的复数:

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

                                  【讨论】:

                                    猜你喜欢
                                    • 2011-09-04
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2019-04-28
                                    • 2013-10-11
                                    • 1970-01-01
                                    相关资源
                                    最近更新 更多