PHP konvertiert XML in JSON

Lesezeit: 9 Minuten

PHP konvertiert XML in JSON
Bryan Hadlock

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.

$xml = simplexml_load_file("states.xml");
echo json_encode($xml);

Also versuche ich, es manuell so zu analysieren.

foreach($xml->children() as $state)
{
    $states[]= array('state' => $state->name); 
}       
echo json_encode($states);

und die Ausgabe für Zustand ist {"state":{"0":"Alabama"}} eher, als {"state":"Alabama"}

Was mache ich falsch?

XML:

<?xml version="1.0" ?>
<states>
    <state id="AL">     
    <name>Alabama</name>
    </state>
    <state id="AK">
        <name>Alaska</name>
    </state>
</states>

Ausgabe:

[{"state":{"0":"Alabama"}},{"state":{"0":"Alaska"}

Var-Dump:

object(SimpleXMLElement)#1 (1) {
["state"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#3 (2) {
  ["@attributes"]=>
  array(1) {
    ["id"]=>
    string(2) "AL"
  }
  ["name"]=>
  string(7) "Alabama"
}
[1]=>
object(SimpleXMLElement)#2 (2) {
  ["@attributes"]=>
  array(1) {
    ["id"]=>
    string(2) "AK"
  }
  ["name"]=>
  string(6) "Alaska"
}
}
}

  • 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


PHP konvertiert XML in JSON
Anton Max

Json & Array aus XML in 3 Zeilen:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

  • 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.

http://lostechies.com/seanbiefeld/2011/10/21/simple-xml-to-json-with-php/

<?php   
class XmlToJson {
    public function Parse ($url) {
        $fileContents= file_get_contents($url);
        $fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
        $fileContents = trim(str_replace('"', "'", $fileContents));
        $simpleXml = simplexml_load_string($fileContents);
        $json = json_encode($simpleXml);

        return $json;
    }
}
?>

  • 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.

foreach($xml->children() as $state)
{
    $states[]= array('state' => (string)$state->name); 
}       
echo json_encode($states);

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.

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);
    }
}   

Anwendungsbeispiel:

$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);

Beispieleingabe (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>

Beispielausgabe:

{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}

Schön gedruckt:

{
    "family" : [{
            "$" : {
                "name" : "Johnson"
            },
            "child" : [{
                    "$" : {
                        "name" : "John",
                        "age" : "5"
                    },
                    "toy" : [{
                            "$" : {
                                "status" : "old"
                            },
                            "_" : "Trooper"
                        }, {
                            "$" : {
                                "status" : "old"
                            },
                            "_" : "Ultrablock"
                        }, {
                            "$" : {
                                "status" : "new"
                            },
                            "_" : "Bike"
                        }
                    ]
                }
            ]
        }
    ]
}

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

{
    "states" : [{
            "state" : [{
                    "$" : {
                        "id" : "AL"
                    },
                    "name" : [{
                            "_" : "Alabama"
                        }
                    ]
                }, {
                    "$" : {
                        "id" : "AK"
                    },
                    "name" : [{
                            "_" : "Alaska"
                        }
                    ]
                }
            ]
        }
    ]
}

1646889248 975 PHP konvertiert XML in JSON
Kodierer der Erlösung

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.

function json_prepare_xml($domNode) {
  foreach($domNode->childNodes as $node) {
    if($node->hasChildNodes()) {
      json_prepare_xml($node);
    } else {
      if($domNode->hasAttributes() && strlen($domNode->nodeValue)){
         $domNode->setAttribute("nodeValue", $node->textContent);
         $node->nodeValue = "";
      }
    }
  }
}

$dom = new DOMDocument();
$dom->loadXML( file_get_contents($xmlfile) );
json_prepare_xml($dom);
$sxml = simplexml_load_string( $dom->saveXML() );
$json = json_decode( json_encode( $sxml ) );

dadurch, <foo bar="3">Lorem</foo> wird nicht so enden {"foo":"Lorem"} in Ihrem JSON.

  • 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


Versuchen Sie, dies zu verwenden

$xml = ... // Xml file data

// first approach
$Json = json_encode(simplexml_load_string($xml));

---------------- OR -----------------------

// second approach
$Json = json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA));

echo $Json;

Oder

Sie können diese Bibliothek verwenden: https://github.com/rentpost/xml2array

  • 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


1646889248 222 PHP konvertiert XML in JSON
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);
}

Beispiel:

php > print(json_encode(xmlToArr('<root a="5"><b>6</b></root>')));
{"root":[{"a":"5","b":["6"]}]}

  • Dies funktioniert tatsächlich für Fälle mit mehreren Namespaces, besser als andere Lösungen, warum eine Ablehnung …

    – Aaron

    10. Juli 2020 um 4:00 Uhr

  • Nachdem ich zig Lösungen ausprobiert habe, ist diese die einzige, die für mich funktioniert hat, vielen Dank!

    – G. Chris DCosta

    9. März 2021 um 13:38 Uhr

986330cookie-checkPHP konvertiert XML in JSON

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy