4

我有一个需要转换为 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");
        }
    }
}
4

2 回答 2

3

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

为此,您可以创建一个将值添加到父 XML 元素的函数。

然后该函数调用自身以防找到嵌套数据。然后它将首先将子元素添加到父元素,然后将添加的新元素作为父元素调用自身。

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

然后 add 函数只需要读取您解析的数据并找出要处理的四种情况中的哪一种:

  1. 只需添加一个带有字符串值的新元素(命名元素的字符串)
  2. 添加多个具有相同名称的新元素(命名元素的 0-n 索引数组)
  3. 添加一个新子代,然后在其中添加 N 个新子代(命名元素的键控数组)
  4. 将 N 个新子代添加到父代(编号(未命名)元素的键控数组)

对于这个答案,我认为使用匿名函数尝试一下会很好。为了让它递归,它需要引用自己。然后可以将它包装在另一个函数中,该函数将允许创建和导入一个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);

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

下一个案例是

[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 的转换。

于 2013-01-03T17:12:49.557 回答
0

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

于 2013-01-03T10:54:01.523 回答