我想我参加聚会有点晚了,但是我写了一个小函数来完成这项任务。它还照顾属性,文本内容,即使具有相同节点名的多个节点是同级节点也是如此。
免责声明:
我不是PHP本地人,所以请忍受简单的错误。
function xml2js($xmlnode) {
$root = (func_num_args() > 1 ? false : true);
$jsnode = array();
if (!$root) {
if (count($xmlnode->attributes()) > 0){
$jsnode["$"] = array();
foreach($xmlnode->attributes() as $key => $value)
$jsnode["$"][$key] = (string)$value;
}
$textcontent = trim((string)$xmlnode);
if (count($textcontent) > 0)
$jsnode["_"] = $textcontent;
foreach ($xmlnode->children() as $childxmlnode) {
$childname = $childxmlnode->getName();
if (!array_key_exists($childname, $jsnode))
$jsnode[$childname] = array();
array_push($jsnode[$childname], xml2js($childxmlnode, true));
}
return $jsnode;
} else {
$nodename = $xmlnode->getName();
$jsnode[$nodename] = array();
array_push($jsnode[$nodename], xml2js($xmlnode, true));
return json_encode($jsnode);
}
}
用法示例:
$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);
输入示例(myfile.xml):
<family name="Johnson">
<child name="John" age="5">
<toy status="old">Trooper</toy>
<toy status="old">Ultrablock</toy>
<toy status="new">Bike</toy>
</child>
</family>
输出示例:
{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
精美印刷:
{
"family" : [{
"$" : {
"name" : "Johnson"
},
"child" : [{
"$" : {
"name" : "John",
"age" : "5"
},
"toy" : [{
"$" : {
"status" : "old"
},
"_" : "Trooper"
}, {
"$" : {
"status" : "old"
},
"_" : "Ultrablock"
}, {
"$" : {
"status" : "new"
},
"_" : "Bike"
}
]
}
]
}
]
}
要记住的怪癖:
几个具有相同标记名的标记可能是同级标记。除最后一个兄弟姐妹外,其他解决方案很可能会丢弃所有其他兄弟姐妹。为了避免这种情况,即使每个节点只有一个孩子,也要使用一个数组,该数组为标记名的每个实例保存一个对象。(请参见示例中的多个“”元素)
甚至在有效XML文档中应该只存在一个根元素的情况下,也要与实例的对象一起存储为数组,以具有一致的数据结构。
为了能够区分XML节点内容和XML属性,每个对象属性都存储在“ $”中,内容存储在“ _”子级中。
编辑:
我忘了显示示例输入数据的输出
{
"states" : [{
"state" : [{
"$" : {
"id" : "AL"
},
"name" : [{
"_" : "Alabama"
}
]
}, {
"$" : {
"id" : "AK"
},
"name" : [{
"_" : "Alaska"
}
]
}
]
}
]
}
var_dump
效果很好。)