Chyba trochę się spóźniłem na przyjęcie, ale napisałem małą funkcję, aby wykonać to zadanie. Dba również o atrybuty, zawartość tekstową, a nawet jeśli wiele węzłów o tej samej nazwie węzła jest rodzeństwem.
Zastrzeżenie:
nie jestem natywnym językiem PHP, więc proszę, znoszę proste błędy.
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);
}
}
Przykład użycia:
$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);
Przykładowe dane wejściowe (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>
Przykładowe dane wyjściowe:
{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
Całkiem wydrukowane:
{
"family" : [{
"$" : {
"name" : "Johnson"
},
"child" : [{
"$" : {
"name" : "John",
"age" : "5"
},
"toy" : [{
"$" : {
"status" : "old"
},
"_" : "Trooper"
}, {
"$" : {
"status" : "old"
},
"_" : "Ultrablock"
}, {
"$" : {
"status" : "new"
},
"_" : "Bike"
}
]
}
]
}
]
}
Dziwactwa, o których należy pamiętać:
kilka tagów z tą samą zmienną może być rodzeństwem. Inne rozwiązania najprawdopodobniej odrzucą wszystko oprócz ostatniego rodzeństwa. Aby tego uniknąć, każdy węzeł, nawet jeśli ma tylko jedno dziecko, jest tablicą przechowującą obiekt dla każdej instancji zmiennej. (Zobacz przykład wielu elementów „”)
Nawet element główny, z którego tylko jeden powinien istnieć w ważnym dokumencie XML, jest przechowywany jako tablica z obiektem instancji, aby mieć spójną strukturę danych.
Aby móc odróżnić zawartość węzła XML od atrybutów XML, każdy atrybut obiektu jest przechowywany w „$”, a zawartość w podrzędnym „_”.
Edycja:
zapomniałem pokazać dane wyjściowe dla przykładowych danych wejściowych
{
"states" : [{
"state" : [{
"$" : {
"id" : "AL"
},
"name" : [{
"_" : "Alabama"
}
]
}, {
"$" : {
"id" : "AK"
},
"name" : [{
"_" : "Alaska"
}
]
}
]
}
]
}
var_dump
działa dobrze.)