[Python-de] XML mit LXML einlesen , wobei die Struktur nicht alltäglich ist.

Stefan Behnel python-de at behnel.de
Di Mär 24 13:14:16 UTC 2009


Thomas Gebhard schrieb:
> ich habe für euch eine knifflige Aufgabe. Diese habe  ich zwar gelöst
> habe, jedoch mit einem hässlichem workaround. Im speziellem muss ich
> mehrere XML Files auslesen, die in Summe ca. 140GB Blog Daten enthalten.

Jemineh. Ich hoffe doch, die einzelnen Dateien sind kleiner?


> Die Einträge im XML File beginnen alle mit:
>
> <item>
> </item>
> <item>
> ....
>
> dies bedeutet, dass die Files KEIN Root Element enthalten.

Wie mein Vorredner schon sagte: kein XML.


> Dies habe ich nun gelöst, indem ich zu Beginn <root> und am Ende des
> Files </root> hinzugefügt habe.

Wenn du die Feed-Parser API benutzt, musst du zumindest die Dateien dazu
nicht anfassen.

http://codespeak.net/lxml/parsing.html#the-feed-parser-interface

Eine andere Möglichkeit ist es, selbst ein file-ähnliches Objekt um das
eigentliche Dateiobjekt herum zu schreiben, das bei .read() zuerst das
öffnende Root-Tag, dann den Dateiinhalt (häppchenweise) und danach das
schließende Root-Tag zurückliefert.

Das funktioniert dann auch mit iterparse(), so dass du auch noch alle
Dateien auf einen Schlag hintereinander weg einlesen könntest, indem du
sie einfach in deinem file-like hintereinander einliest.

Also sowas (völlig ungetestetes):

    class bigfile(object):
        def __init__(self, files):
             self.files = iter(files)
             self.next_file = None
        def read(self, size=8192):
             if self.files is None:
                 return ''
             data = ''
             try:
                 if self.next_file is None:
                     data = "<root>"
                     self.next_file = self.files.next()
                 else:
                     while not data:
                         self.next_file = self.files.next()
                         data = self.next_file.read(size)
             except StopIteration:
                 data += "</root>"
                 self.files = None
             return data


> Das zweite Problem das ich hatte, war dass es Element gibt die wie folgt
> ausschauen:
> <source:title></source:title>
> <weblog:weblog_type></weblog:weblog_type>
>
> LXML interpretierte hier immer source als auch weblog als Namespaces,
> die im Header jedoch nicht definiert wurden.

Also noch weniger XML, na super.

Dann benutz doch als öffnendes Root-Tag

    '<root xmlns:source="" xmlns:weblog="">'

Damit setzt du die Präfixe auf den leeren Namespace, so dass die Elemente
dann ohne Namespace aus dem Parser zurück kommen.

Hilft dir das?

Stefan




Mehr Informationen über die Mailingliste python-de