JSON in XML umwandeln mit Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
kjd
User
Beiträge: 12
Registriert: Freitag 12. Juli 2019, 09:48

Hallo!

Ich muss für eine Aufgabe eine JSON Datei in eine XML Datei umwandeln. Leider finde ich kaum Tutorials von JSON zu XML, eher in die andere Richtung. Ich hab es trotzdem einfach versucht, aber ich bekomm leider einfach keine XML Datei raus.

Hier ist ein Beispiel JSON Code:

Code: Alles auswählen

[
"Name": "Noel",
"Augenfarbe": ["Grün"],
"Geburtsort": None
"Größe (cm)": 180
"Gewicht": 90
]
So soll die XML Datei später aussehen:

Code: Alles auswählen

<?xml version='1.0' encoding='UTF-8'?>
<Personen>
	<Name> Noel </Name>
	<Farben>
		<Augenfarbe> Grün </Augenfarbe>
	</Farben
	<Geburtsort> </Geburtsort>
	<Maße> 180 , 90 </Maße>
</Personen>
Diesen Code habe ich geschrieben:

Code: Alles auswählen

import json

with open("people.json", mode="r", encoding="utf8") as file:
    people = json.load(file)

Code: Alles auswählen

import xml.etree.cElementTree as ET
root = ET.Element('Personen')

ET.SubElement(root, "Name").text = str(people['Name'])

farben = ET.SubElement(root, "Farben")
for i in people['Farben']:
	ET.SubElement(farben, "Augenfarbe").text = str(i['Augenfarbe'])
	
ET.SubElement(root, "Geburtsort").text = str(people['Geburtsort'])
ET.SubElement(root, "Maße").text = str((people['Größe (cm)'], people["Gewicht]))
 
tree = ET.ElementTree(root)
tree.write('beispiel.xml') 
Ich bekomm die ganze Zeit Errors, momentan diesen: "TypeError: list indices must be integers or slices, not str". Dabei meine ich es genauso gemacht zu haben, wie in den Tutorials.

Danke im Voraus!
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Dein JSON ist kein JSON. Die Klammern sind falsch. Wie sieht denn der komplette Traceback aus. Das ist hilfreich, denn so müssen wir raten, an welcher Stelle denn der Fehler auftritt. Da Du ungültiges JSON hast und ich raten muß, bekomme ich entweder den von Dir beschriebenen Fehler, oder aber einen KeyError.

Name und Augenfarbe sind schon Strings, die muß man also nicht nochmal in einen String umwandeln.
i ist ein besonders schlechter Name für eine Farbe. Gewöhn Dir gleich an, sprechende Variablennamen zu benutzen.
Eingerückt wird immer mit 4 Leerzeichen pro Ebene, keine Tabs.
Geburtsort soll laut Vorgabe leer sein, und nicht den Text "None" enthalten. Die Stringrepräsentation eines Tupels ist nicht dafür da, dass man sie in XML-Dateien schreibt, benutze Stringformatierung um eine passende Ausgabe zu bekommen.
<Personen> ist ein seltsames Tag für EINE Person.
Benutzeravatar
__blackjack__
User
Beiträge: 13113
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kjd: Weder das JSON noch das XML sind gültiges JSON bzw. XML. Neben den Klammern beim JSON gibt es dort auch kein `None` und es fehlen Kommas. Das sollte wohl eher so aussehen:

Code: Alles auswählen

{
  "Name": "Noel",
  "Augenfarbe": ["Grün"],
  "Geburtsort": null,
  "Größe (cm)": 180,
  "Gewicht": 90
}
Ich würde die JSON-Datei als Binärdatei öffnen, dann erkennt `json.load()` selbst welche UTF-Kodierung vorliegt.

Das `lxml`-Package hat das überaus praktische `builder`-Modul:

Code: Alles auswählen

#!/usr/bin/env python3
import json

import lxml.etree as ET
from lxml.builder import E


def main():
    with open("test.json", "rb") as json_file:
        data = json.load(json_file)

    document = E.Personen(
        E.Name(data["Name"]),
        E.Farben(*(E.Augenfarbe(colour) for colour in data["Augenfarbe"])),
        E.Geburtsort(
            "" if data["Geburtsort"] is None else data["Geburtsort"],
        ),
        E.Maße(
            ", ".join(str(data[key]) for key in ["Größe (cm)", "Gewicht"]),
        ),
    )

    print(ET.tounicode(document, pretty_print=True))


if __name__ == "__main__":
    main()

Ausgabe:

Code: Alles auswählen

<Personen>
  <Name>Noel</Name>
  <Farben>
    <Augenfarbe>Grün</Augenfarbe>
  </Farben>
  <Geburtsort></Geburtsort>
  <Maße>180, 90</Maße>
</Personen>
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten