XML Datei richtig einrücken

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
kl.feigling89
User
Beiträge: 42
Registriert: Montag 24. Februar 2014, 14:47

Hallo Leute, ich habe folgenden Code:

Code: Alles auswählen

from xml.dom.minidom import Document
import xml.dom.minidom as minidom
import codecs



#create minidom-document
doc = Document()

# create base element
base = doc.createElement('Dictionary')
doc.appendChild(base)

# create an entry element
entry = doc.createElement('Entry')

# ... and append it to the base element
base.appendChild(entry)

# create another element 
german = doc.createElement('German')

# create content
german_content = doc.createTextNode('Hund')

# append content to element
german.appendChild(german_content)

# append the german entry to our entry element
entry.appendChild(german)

# now the same with an english entry
english = doc.createElement('English')
english_content = doc.createTextNode('dog')
english.appendChild(english_content)
entry.appendChild(english)


with codecs.open("C:/Users/Emel/Desktop/out.xml", "w", "utf-8") as out:
    doc.writexml(out)
und möchte die XML datei aber mit einer schönen Formatierung erstellen. Gibt es da eine möglichkeit?

Es soll nicht so aussehen :

Code: Alles auswählen

<?xml version="1.0" ?><Dictionary><Entry><German>Hund</German><English>dog</English></Entry></Dictionary>
sondern so:

Code: Alles auswählen

<?xml version="1.0" ?>
<Dictionary>
      <Entry>
            <German>Hund</German>
            <English>dog</English>
      </Entry>
</Dictionary>
oder kann man das vielleicht nicht einstellen?
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Du solltest wirklich elementree benutzen

Code: Alles auswählen

from xml.etree import ElementTree as et

def indent(elem, level=0):
    i = "\n" + level*"  "
    if len(elem):
        if not elem.text or not elem.text.strip():
            elem.text = i + "  "
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
        for elem in elem:
            indent(elem, level+1)
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
    else:
        if level and (not elem.tail or not elem.tail.strip()):
            elem.tail = i

base = et.Element('Dictionary')
entry = et.SubElement(base, 'Entry')
et.SubElement(entry, 'German').text = 'Hund'
et.SubElement(entry, 'English').text = 'dog'
indent(base)
doc = et.ElementTree(base)
with open("C:/Users/Emel/Desktop/out.xml", "w") as out:
    doc.write(out)
BlackJack

Oder `lxml`, da gibt es das schon eingebaut, plus einigen anderen nützlichen Sachen. Wie man sich freiwillig mit einer DOM-API rumschlagen kann ist mir ein Rätsel.

Code: Alles auswählen

from lxml import etree
from lxml.builder import E


def main():
    root = E.dictionary(
        E.entry(E.word('Hund', lang='de'), E.word('dog', lang='en'))
    )
    tree = etree.ElementTree(root)
    tree.write('test.xml', pretty_print=True, xml_declaration=True)


if __name__ == '__main__':
    main()
Ergebnis in ``test.xml``:

Code: Alles auswählen

<?xml version='1.0' encoding='ASCII'?>
<dictionary>
  <entry>
    <word lang="de">Hund</word>
    <word lang="en">dog</word>
  </entry>
</dictionary>
kl.feigling89
User
Beiträge: 42
Registriert: Montag 24. Februar 2014, 14:47

Danke schön für eure Hilfe, benutze jetzt lxml und es funktioniert super!

Wünsche euch noch Frohe Ostern.
kl.feigling89
User
Beiträge: 42
Registriert: Montag 24. Februar 2014, 14:47

Noch eine kleine Frage dazu: Wie kann ich denn das Entry noch mit einer for-Schleife durch nomerrieren?

Code: Alles auswählen

<?xml version='1.0' encoding='ASCII'?>
<dictionary>
  <entry1>
    <word lang="de">Hund</word>
    <word lang="en">dog</word>
  </entry1>
  <entry2>
    <word lang="de">Katze</word>
    <word lang="en">cat</word>
  </entry2>
</dictionary>
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@kl.feigling89: gar nicht! Es ist genauso eine schlechte Idee, wie Variablennamen durchzunummerieren. Die Reihenfolge der <entry>-Tags ist durch die Reihenfolge, wie sie in der xml-Datei stehen schon genügend geordnet. Was wäre der Sinn dahinter, nochmals eine zweite Ordnung, die der ersten vielleicht sogar widerspricht, einzuführen?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Gar nicht.

Natuerlich geht das, aber das ist kein sinnvolles XML-Format. Wenn du tatsaechlich irgendwo IDs vergeben willst, dann als _Attribut_ aber nicht als _Tag_.
Das funktioniert dann analog zum "lang" Attribut .. nur eben bei `E.entry`
kl.feigling89
User
Beiträge: 42
Registriert: Montag 24. Februar 2014, 14:47

Ohh, da habt ihr recht. Habe Xml noch nie benutzt und hab nicht darüber nachgedacht, dass die Reihenfolge konstant ist.
Jetzt hab ich noch eine kleine Frage und hoffe es ist die letzte. Wie speichere ich denn am besten Array oder Listen ab ?
Wandele ich es als String? oder gibts noch ne alternative?
BlackJack

@kl.feigling89: Was für ein Array? Und reden wir immer noch von XML? Die Python-Datentypen einfach mit `str()` umwandeln ist zum Speichern keine gute Idee, denn dann stellt sich ja die Frage wie man das wieder einliest, und die Antwort darauf ist entweder hässlich und unsicher oder halt auf Python beschränkt. Wenn Du das in XML speichern willst, dann kannst Du ja einfach ein Element für den Container erstellen und darin dann Elemente für jeden Wert, also ``['one', 'two', 'three']`` könnte man als

Code: Alles auswählen

  <items>
      <item>one</item>
      <item>two</item>
      <item>three</item>
  </items>
serialisieren.
Möglicherweise mit passenderen Tagnamen.
Antworten