我想我有点晚来参加这个派对,但我写了一个小函数来完成这个任务。它还处理属性、文本内容,甚至处理具有相同节点名称的多个兄弟节点。
免责声明:
我不是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"
}
]
}
]
}
]
}