我有一个需要转换为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");
}
}
}
答案 0 :(得分:2)
您可以使用递归来解决您的问题。递归可以很好地处理嵌套数据。
您可以通过创建将值添加到父XML元素的单个函数来完成此操作。
该函数在发现嵌套数据时调用自身。然后,它将首先将子元素添加到父元素,并将调用自身,并将新元素添加为父元素。
如果要添加的数据只是一个字符串,它仍然会创建子项,但直接添加字符串值并离开。那是叶子节点,最多在外面。
然后,add函数只需要读取你解析的数据并找出要处理的四个案例中的哪一个:
对于这个答案,我认为用匿名函数尝试这个会很好。为了使它递归,它需要引用自己。然后它可以包含在另一个允许创建和导入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。