Ich versuche, XML in PHP in JSON zu konvertieren. Wenn ich eine einfache Konvertierung mit einfachem XML und json_encode durchführe, werden keine der Attribute in der XML-Anzeige angezeigt.
Bitte fügen Sie einen Ausschnitt des XML-Codes und die endgültige Array-Struktur hinzu, die Sie nach dem Parsen haben. (EIN var_dump funktioniert gut.)
– nikc.org
12. Januar 2012 um 5:39 Uhr
Eingabe, Ausgabe und var_dump hinzugefügt
– Bryan Hadlock
12. Januar 2012 um 6:15 Uhr
Einige Anwendungen benötigen “Perfekte XML-zu-JSON-Zuordnung”das ist jsonMLsiehe Lösung hier.
Diese Lösung ist nicht fehlerfrei. XML-Attribute werden vollständig verworfen. Damit <person my-attribute='name'>John</person> wird interpretiert als <person>John</person>.
– Jake Wilson
26. Januar 2015 um 19:57 Uhr
$xml = simplexml_load_string($xml_string,’SimpleXMLElement’,LIBXML_NOCDATA); um cdata-Elemente zu glätten.
– txyoji
14. Juli 2015 um 17:29 Uhr
@JakeWilson vielleicht sind es die 2 Jahre, die vergangen sind, und verschiedene Versionskorrekturen, aber unter PHP 5.6.30 erzeugt diese Methode ALLE Daten. Attribute werden im Array unter gespeichert @attributes Schlüssel, so dass es absolut fehlerfrei und schön funktioniert. 3 kurze Codezeilen lösen mein Problem wunderbar.
– Alex
7. Februar 2017 um 16:12 Uhr
Dies funktioniert nicht, wenn Sie mehrere Namespaces haben, Sie können nur einen auswählen, der an $json_string übergeben wird:'(
– Jirislav
26. November 2017 um 5:49 Uhr
Denken Sie daran, dass bei dieser Lösung, wenn mehrere Knoten mit demselben Namen vorhanden sind, ein Knoten dazu führt, dass ein Schlüssel nur auf ein Element zeigt, aber mehrere Knoten dazu führen, dass ein Schlüssel auf ein Element zeigt Reihe von Elementen: <list><item><a>123</a><a>456</a></item><item><a>123</a></item></list> -> {"item":[{"a":["123","456"]},{"a":"123"}]}. Eine Lösung bei php.net nach ratfaktor löst dieses Problem, indem Elemente immer in einem Array gespeichert werden.
– Klesun
7. Januar 2019 um 21:44 Uhr
Entschuldigen Sie die Beantwortung eines alten Beitrags, aber dieser Artikel skizziert einen Ansatz, der relativ kurz, prägnant und einfach zu pflegen ist. Ich habe es selbst getestet und funktioniert ziemlich gut.
Dies funktioniert nicht, wenn Sie mehrere Instanzen desselben Tags in Ihrem XML haben, json_encode wird am Ende nur die letzte Instanz des Tags serialisieren.
– edrei
7. November 2013 um 20:50 Uhr
An alle, die sich diese alte Antwort ansehen: Bitte bedenken Sie die Zeit, in der dies geschrieben wurde, und ziehen Sie vielleicht modernere Ansätze in Betracht.
– Coreus
26. Mai 2021 um 21:42 Uhr
Ich habe es herausgefunden. json_encode behandelt Objekte anders als Strings. Ich habe das Objekt in eine Zeichenfolge umgewandelt und es funktioniert jetzt.
Ich schätze, ich bin etwas spät dran, aber ich habe eine kleine Funktion geschrieben, um diese Aufgabe zu erfüllen. Es kümmert sich auch um Attribute, Textinhalte und selbst wenn mehrere Knoten mit demselben Knotennamen Geschwister sind.
Haftungsausschluss:
Ich bin kein PHP-Native, also ertragen Sie bitte einfache Fehler.
Macken zu beachten:
Mehrere Tags mit demselben Tagnamen können Geschwister sein. Andere Lösungen werden höchstwahrscheinlich alle bis auf das letzte Geschwisterelement fallen lassen. Um dies zu vermeiden, ist jeder einzelne Knoten, selbst wenn er nur ein untergeordnetes Element hat, ein Array, das ein Objekt für jede Instanz des Tagnamens enthält. (Siehe mehrere “”-Elemente im Beispiel)
Sogar das Wurzelelement, von dem in einem gültigen XML-Dokument nur eines existieren sollte, wird als Array mit einem Objekt der Instanz gespeichert, nur um eine konsistente Datenstruktur zu haben.
Um zwischen XML-Knoteninhalt und XML-Attributen unterscheiden zu können, werden die Attribute jedes Objekts im “$” und der Inhalt im untergeordneten “_” gespeichert.
Bearbeiten: Ich habe vergessen, die Ausgabe für Ihre Beispieleingabedaten anzuzeigen
Eine häufige Falle ist, das zu vergessen json_encode() berücksichtigt keine Elemente mit einem Textwert und Attribut(e). Es wird eine davon auswählen, was Datenverlust bedeutet. Die folgende Funktion löst dieses Problem. Entscheidet man sich für die json_encode/decode Weise wird die folgende Funktion empfohlen.
Kompiliert nicht und erzeugt nicht die beschriebene Ausgabe, wenn Syntaxfehler korrigiert werden.
– Richard Kiefer
21. Januar 2015 um 10:36 Uhr
Was ist $dom? Woher kommt das?
– Jake Wilson
26. Januar 2015 um 20:20 Uhr
$dom = neues DOMDocument(); ist, woher es kommt
– Scott
25. November 2015 um 21:28 Uhr
Letzte Codezeile: $json = json_decode( json_encode( $sxml ) ) ); sollte sein: $json = json_decode( json_encode( $sxml ) );
– Lawrence Cooke
29. Februar 2016 um 2:46 Uhr
Klesun
Diese Lösung verarbeitet Namensräume, Attribute und erzeugt konsistente Ergebnisse mit sich wiederholenden Elementen (immer im Array, auch wenn es nur ein Vorkommen gibt). Inspiriert von sxiToArray() von ratfactor.
/**
* <root><a>5</a><b>6</b><b>8</b></root> -> {"root":[{"a":["5"],"b":["6","8"]}]}
* <root a="5"><b>6</b><b>8</b></root> -> {"root":[{"a":"5","b":["6","8"]}]}
* <root xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><a>123</a><wsp:b>456</wsp:b></root>
* -> {"root":[{"xmlns:wsp":"http://schemas.xmlsoap.org/ws/2004/09/policy","a":["123"],"wsp:b":["456"]}]}
*/
function domNodesToArray(array $tags, \DOMXPath $xpath)
{
$tagNameToArr = [];
foreach ($tags as $tag) {
$tagData = [];
$attrs = $tag->attributes ? iterator_to_array($tag->attributes) : [];
$subTags = $tag->childNodes ? iterator_to_array($tag->childNodes) : [];
foreach ($xpath->query('namespace::*', $tag) as $nsNode) {
// the only way to get xmlns:*, see https://stackoverflow.com/a/2470433/2750743
if ($tag->hasAttribute($nsNode->nodeName)) {
$attrs[] = $nsNode;
}
}
foreach ($attrs as $attr) {
$tagData[$attr->nodeName] = $attr->nodeValue;
}
if (count($subTags) === 1 && $subTags[0] instanceof \DOMText) {
$text = $subTags[0]->nodeValue;
} elseif (count($subTags) === 0) {
$text="";
} else {
// ignore whitespace (and any other text if any) between nodes
$isNotDomText = function($node){return !($node instanceof \DOMText);};
$realNodes = array_filter($subTags, $isNotDomText);
$subTagNameToArr = domNodesToArray($realNodes, $xpath);
$tagData = array_merge($tagData, $subTagNameToArr);
$text = null;
}
if (!is_null($text)) {
if ($attrs) {
if ($text) {
$tagData['_'] = $text;
}
} else {
$tagData = $text;
}
}
$keyName = $tag->nodeName;
$tagNameToArr[$keyName][] = $tagData;
}
return $tagNameToArr;
}
function xmlToArr(string $xml)
{
$doc = new \DOMDocument();
$doc->loadXML($xml);
$xpath = new \DOMXPath($doc);
$tags = $doc->childNodes ? iterator_to_array($doc->childNodes) : [];
return domNodesToArray($tags, $xpath);
}
Bitte fügen Sie einen Ausschnitt des XML-Codes und die endgültige Array-Struktur hinzu, die Sie nach dem Parsen haben. (EIN
var_dump
funktioniert gut.)– nikc.org
12. Januar 2012 um 5:39 Uhr
Eingabe, Ausgabe und var_dump hinzugefügt
– Bryan Hadlock
12. Januar 2012 um 6:15 Uhr
Einige Anwendungen benötigen “Perfekte XML-zu-JSON-Zuordnung”das ist jsonMLsiehe Lösung hier.
– Peter Krauß
6. Oktober 2016 um 14:19 Uhr