即使对于嵌套数据,php数组也能转换为xml

时间:2013-01-03 10:09:41

标签: php xml arrays

我有一个需要转换为xml格式的数组。

[name] => ABC
[email] => email@email.com
[phones] => Array
                (
                 [phone] => Array
                          (
                                [0] => Array
                                    (
                                        [mobile] => 91454599193
                                        [land] =>  9999999 
                                    )

                                [1] => Array
                                    (
                                        [mobile] => 54520199193
                                        [land] =>  9999999 
                                    )

                                [2] => Array
                                    (
                                        [mobile] => 90424249194
                                        [land] =>  5555555 
                                    )

                                [3] => Array
                                    (
                                        [mobile] => 44224199195
                                        [land] =>  8888888 
                                    )

                            )
)

我希望它采用以下格式

<name>ABC</name>
<email>email@email.com</email>
 <phones>
 <phone>
   <mobile>545450199193</mobile>
   <land>9999999</land>
</phone>
 <phone>
   <mobile>575199193</mobile>
   <land>9999999</land>
</phone>
</phones>

请帮帮我....

这是我的功能,我用这种方式编写。我面临的问题是具有数字的索引必须在XML节点中显示文本。例如: - 在手机阵列下方,有索引[0],[1]。我希望在我的XML页面中将[0],[1]替换为<phone>

  function array_to_xml($value, &$xml_student_info) {
  foreach($value as $key => $value) {
    if(is_array($value)) {
        if(!is_numeric($key)){
            $subnode = $xml_student_info->addChild("$key");
            array_to_xml($value, $subnode);
        }
        else{
            array_to_xml($value, $xml_student_info);
         }
       }
        else {
            $xml_student_info->addChild("$key","$value");
        }
    }
}

2 个答案:

答案 0 :(得分:2)

您可以使用递归来解决您的问题。递归可以很好地处理嵌套数据。

您可以通过创建将值添加到父XML元素的单个函数来完成此操作。

该函数在发现嵌套数据时调用自身。然后,它将首先将子元素添加到父元素,并将调用自身,并将新元素添加为父元素。

如果要添加的数据只是一个字符串,它仍然会创建子项,但直接添加字符串值并离开。那是叶子节点,最多在外面。

然后,add函数只需要读取你解析的数据并找出要处理的四个案例中的哪一个:

  1. 只需添加一个带字符串值的新元素(指定元素的字符串)
  2. 添加多个具有相同名称的新元素(指定元素的0-n索引数组)
  3. 添加一个新子项,然后在其中添加N个新子项(指定元素的键控数组)
  4. 将N个新子项添加到父项(编号(未命名)元素的键控数组)
  5. 对于这个答案,我认为用匿​​名函数尝试这个会很好。为了使它递归,它需要引用自己。然后它可以包含在另一个允许创建和导入SimpleXMLElement的函数内,这允许轻松创建XML。进一步包装甚至允许将XML作为字符串生成,但是我将其保留到外部以使用清楚:

    require('inc/simplexml_pretty_print.php');
    
    $xml      = new SimpleXMLElement('<root/>');
    $importer = $createArrayImporter($xml);
    echo simplexml_pretty_print($importer($array));
    

    在此示例中,$array是您问题中的数组。它包含这四种情况,这些情况在$add函数中处理,在上面的示例中调用$createArrayImporter()时将返回包装在另一个匿名函数中。

    在进入之前,让我们回顾一下输入数组:

    $array = [
        'name'   => 'ABC',
        'email'  => 'email@email.com',
        'phones' =>
        [
            'phone' =>
            [
                [
                    'mobile' => '9000199193',
                    'land'   => ' 9999999 ',
                ],
                [
                    'mobile' => '9000199193',
                    'land'   => ' 9999999 ',
                ],
                [
                    'mobile' => '9000199194',
                    'land'   => ' 5555555 ',
                ],
                [
                    'mobile' => '9000199195',
                    'land'   => ' 8888888 ',
                ],
            ],
        ],
    ];
    

    这会产生输出:

    <?xml version="1.0"?>
    <root>
      <name>ABC</name>
      <email>email@email.com</email>
      <phones>
        <phone>
          <mobile>9000199193</mobile>
          <land> 9999999 </land>
        </phone>
        <phone>
          <mobile>9000199193</mobile>
          <land> 9999999 </land>
        </phone>
        <phone>
          <mobile>9000199194</mobile>
          <land> 5555555 </land>
        </phone>
        <phone>
          <mobile>9000199195</mobile>
          <land> 8888888 </land>
        </phone>
      </phones>
    </root>
    

    如何递归函数:

    $add = function (SimpleXMLElement $subject, $key, $value) use (&$add)
    

    主题是要添加数据的XML元素,键是数组中的键,值也是可能嵌套或不嵌套的值。

    因此,考虑到最直接的情况,你的键控(所有数组索引都是字符串)数组应该添加到根元素。

            case $isKeyed:
                foreach ($value as $oneof_key => $oneof_value) {
                    $add($subject, $oneof_key, $oneof_value);
                }
    

    这会将值作为嵌套值传递。例如,下一级的第一个是[name] => ABC,所以是一个键控字符串:

            case $isString && $hasKey:
                return $subject->addChild($key, $value);
    

    这只是添加了带有名为key的字符串值的子元素。

    下一个案例是

    [phones] => Array
         (
             [phone] => Array
                 (
                     ...
    

    这是命名元素的键控数组:

            case $isKeyed && $hasKey:
                $subject = $subject->addChild($key);
                // fall-through intended
    

    它需要添加自己的密钥作为与$isString && $hasKey情况相当的子元素,但是需要进一步处理它的数组值。这也是带索引子节点(0-N作为索引)的键控数组的嵌套情况,因此可以添加多个具有相同名称的元素:

            case $isKeyed:
                foreach ($value as $oneof_key => $oneof_value) {
                    $add($subject, $oneof_key, $oneof_value);
                }
                return true;
    

    它会落到那个案例中,并且还为没有键但只是编号的键控数组创建了第四种情况。

    这也是为什么我写的是他的三个半案例,最后两个案例是彼此分享一些部分。

    将它包装在一个封闭内部使得这更容易访问,我将在这里仅举几个例子:

    $createArrayImporter = function (SimpleXMLElement $subject) {
    
        $add = function (SimpleXMLElement $subject, $key, $value) use (&$add) {
    
             ...
    
        };
    
        return function (Array $array) use ($subject, $add) {
    
            $add($subject, null, $array);
            return $subject;
        };
    };
    

    所以这可以解决问题。您可以在Gist of mine

    中阅读完整代码

    你找到了一个类似的例子,但是在下面的答案中面向对象,它也通过递归来解决它:

    数组的格式 - 即使它看起来很相似 - 实际上与你的不同。

    对于更多指针,有:

    它处理不同类型的数组到XML转换。

答案 1 :(得分:0)

问题是你不能在一个数组或对象中使用相同的键。在simplexml的情况下,有一个保存xml的对象。解决方案是自己构建xml。