Supongo que llego un poco tarde a la fiesta, pero he escrito una pequeña función para realizar esta tarea. También se ocupa de los atributos, el contenido del texto e incluso si varios nodos con el mismo nombre de nodo son hermanos.
Descargo de responsabilidad:
no soy un nativo de PHP, así que por favor tenga en cuenta los errores simples.
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);
}
}
Ejemplo de uso:
$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);
Entrada de ejemplo (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>
Salida de ejemplo:
{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
Bastante impreso:
{
"family" : [{
"$" : {
"name" : "Johnson"
},
"child" : [{
"$" : {
"name" : "John",
"age" : "5"
},
"toy" : [{
"$" : {
"status" : "old"
},
"_" : "Trooper"
}, {
"$" : {
"status" : "old"
},
"_" : "Ultrablock"
}, {
"$" : {
"status" : "new"
},
"_" : "Bike"
}
]
}
]
}
]
}
Quirks a tener en cuenta:
varias etiquetas con el mismo nombre de etiqueta pueden ser hermanos. Es probable que otras soluciones eliminen todas menos la última hermana. Para evitar esto, todos y cada uno de los nodos, incluso si solo tiene un hijo, es una matriz que contiene un objeto para cada instancia del nombre de etiqueta. (Ver múltiples "" elementos en el ejemplo)
Incluso el elemento raíz, del cual solo debe existir uno en un documento XML válido, se almacena como una matriz con un objeto de la instancia, solo para tener una estructura de datos coherente.
Para poder distinguir entre el contenido del nodo XML y los atributos XML, los atributos de cada objeto se almacenan en "$" y el contenido en el elemento secundario "_".
Editar:
olvidé mostrar la salida para sus datos de entrada de ejemplo
{
"states" : [{
"state" : [{
"$" : {
"id" : "AL"
},
"name" : [{
"_" : "Alabama"
}
]
}, {
"$" : {
"id" : "AK"
},
"name" : [{
"_" : "Alaska"
}
]
}
]
}
]
}
var_dump
funciona bien.)