ubuntuusers.de

Python: Laden/Speichern bläst XML-Dokumente auf

Status: Ungelöst | Ubuntu-Version: Ubuntu
Antworten |

Fredo Team-Icon

Avatar von Fredo

Anmeldungsdatum:
27. Juni 2005

Beiträge: 5244

Wohnort: Bochum

Hallo!

Gerade arbeite ich an einer kleinen Python-Anwendung, die ein XML-Format zum Speichern verwendet. Dazu verwende ich minidom. Damit die erzeugte XML-Datei einigermaßen lesbar ist, verwende ich prettyprinting, die XML-Elemente werden also hübsch eingerückt.

Leider wird beim speichern, laden und erneuten speichern das Dokument immer mehr aufgebläht. Das Verhalten lässt sich auch einfach nachvollziehen:

>>> from xml.dom import minidom
>>> xmlstring = "<a><b><c></c></b></a>"
>>> xmldoc = minidom.parseString(xmlstring)
>>> print xmldoc.toprettyxml()
<?xml version="1.0" ?>
<a>
        <b>
                <c/>
        </b>
</a>

>>> xmlstring = xmldoc.toprettyxml()
>>> xmldoc = minidom.parseString(xmlstring)
>>> print xmldoc.toprettyxml()
<?xml version="1.0" ?>
<a>


        <b>


                <c/>


        </b>


</a>

Das Problem ist wohl, dass durch das prettyprinting die Elemente jeweils noch einen Textknoten (der nur aus whitespace besteht) bekommen. Und der wird dann bei der Ausgabe wieder durch Zeilenumbruch und Einrückung hervorgehoben, und so weiter.

Meiner Meinung nach wäre das optimale Verhalten, nur Elementknoten einzurücken, Textknoten aber nicht. Also

<a>
    <b>Text</b>
</a>


statt

<a>
    <b>
        Text
    </b>
</a>

Lässt sich das irgendwie realisieren? Oder lässt sich das Problem mit der aufgeblasenen XML-Ausgabe sonst irgendwie umgehen?

Herzlichen Dank schon mal und liebe Grüße
Fredo

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4702

Wohnort: Berlin

Hm, diese toprettyxml()-Methode sieht insgesamt ziemlich "gefährlich" aus wenn sie einfach davon ausgeht, das "whitespace" in Textknoten kein Bedeutung hat. Mir würde da nur einfallen eine uglify()-Funktion zu schreiben die in allen Textknoten Leerzeichen strip()t.

Fredo Team-Icon

(Themenstarter)
Avatar von Fredo

Anmeldungsdatum:
27. Juni 2005

Beiträge: 5244

Wohnort: Bochum

Marc 'BlackJack' Rintsch hat geschrieben:

Mir würde da nur einfallen eine uglify()-Funktion zu schreiben die in allen Textknoten Leerzeichen strip()t.

Ja, darauf läuft es wohl hinaus. Oder doch auf das prettyprinting verzichten, obwohl mir das nicht richtig behagt. Naja, danke trotzdem für die Antwort.

Liebe Grüße
Fredo

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

schon jemand ne schönere Lösung gefunden als

114                        print "Speichere"
115                        f = file(pfad, 'w')
116                        xml = self._dat.toprettyxml(encoding="utf-8")
117                        #Kontrukt um leere Zeilen rauszufiltern
118                        xml = xml.splitlines()
119                        #xml wirs zur liste der zeilen
120                        xml2 = []
121                        for l in xml:
122                                l = l.strip() #filtere aus jedem element der Liste die Leerzeilen raus
123                                xml2 += l
124                        xml = ""
125                        for l in xml2:
126                                xml += l #und füge das bereinigte wieder zusammen
127                        xml2 = minidom.parseString(xml)
128                        xml = xml2.toprettyxml(encoding="utf-8")
129                        f.write(xml)
130                        f.close
131                        print "Speichern erfolgreich"

?

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4702

Wohnort: Berlin

Man kann es auf jeden Fall kürzen:

    xml = self._dat.toprettyxml(encoding="utf-8") 
    stripped_xml = ''.join(line.strip() for line in xml.splitlines())
    xml = minidom.parseString(stripped_xml).toprettyxml(encoding='utf-8')
    out_file = open(pfad, 'wb')
    out_file.write(xml)
    out_file.close()

Der Kommentar mit den Leerzeilen ist nicht ganz vollständig: Es wird sämtlicher "whitespace" am Anfang und Ende jeder Zeile entfernt. Und in dem Beispiel wurde die Datei nicht geschlossen: fehlende Klammern.

Statt in eine Zeichenkette zu wandeln, diese zu filtern und dann nochmal über das DOM wieder zu einer Zeichenkette zu kommen, könntest Du das Filtern auch auf dem ursprünglichen DOM erledigen. Da bestünde dann auch die Chance bestimmte Tags von der Säuberung auszunehmen, weil das ja nicht unbedingt in jedem Fall erwünscht ist. Da liegt letztendlich auch das Problem mit "pretty printing" von XML.

Antworten |