[Python-de] XML processing womit?

Stefan Behnel behnel_ml at gkec.informatik.tu-darmstadt.de
Don Jan 5 09:12:40 CET 2006



Andreas Pakulat schrieb:
> On 03.01.06 20:57:59, Stefan Behnel wrote:
>>> Schau Dir mal lxml (codespeak.net/lxml) an.
>> ... und dort insbesondere die "Namespace" Klasse ("scoder2" branch im SVN).
>> Die erlaubt dir die Implementierung von XML-basierten Datenklassen, die
>> automatisch beim Zugriff erzeugt werden (ähnlich Data-Binding, nur beliebig
>> programmierbar). Ein Beispiel findest du in der Doku in
> 
> Ich hab die Doku noch nicht ganz gelesen aber mir ist nicht ganz klar
> wie das da mit dem Abspeichern laufen soll?

Du kannst aus den Element Objekten heraus beliebig auf die XML-Struktur zugreifen.


> Ausserdem sollen die
> Elemente keinen internen Status haben, was sich auch nicht wirklich nach
> einer Datenklasse anhoert...

Der Status wird nur im XML abgebildet. Für anderweitige (interne) Felder der
Objekte wird keine Haftung übernommen.


> Hmm, alles nur ueber ne Property mit
> get/set Methoden? Kannst du mir mal ein Beispiel fuer folgendes geben:
> 
> <movie>
>   <version>
>     <title>blah</title>
>   </version>
>   <version>
>     <title>blub</title>
>   </version>
> </movie>

Nur ein Beispiel (Py2.4), schnell hingetippt:

class MovieElement(ElementBase):
  def iterversions(self):
    # use ElementTree API to iterate over version children
    return (child for child in self if child.tag == 'version')
  def addVersion(self, title):
    "test if version exists, otherwise add"

class VersionElement(ElementBase):
  @property
  def title(self):
    return self[0].text

# Ich nehme mal an, das Ganze läuft über den Namespace 'test'
ns = Namespace('test')
ns['movie']   = MovieElement
ns['version'] = VersionElement

# Dann kannst du das hier machen:

movie = XML('<movie ...')
for version in movie.iterversions():
    print version.title


Ist aber natürlich nur ein Beispiel für eine mögliche API. Du kannst dir damit
ja beliebige XML-APIs implementieren, das ist der Sinn.


> Fuer meine Movie-Klasse muesste ich dann eine get-Methode haben die
> einen Iterator liefert der "on the fly" Versions-Objekte liefert oder?
> (die mit dem entsprechenden XML-Teilstueck erzeugt werden).

Müsstest du nicht. Wie gesagt, nur ein Beispiel. Bietet sich aber sicherlich an.


> Aber das die Objekte "irgendwann" wieder geloescht werden macht mir
> etwas Sorgen. Ich kann sie also nicht nutzen um damit einen ListView
> daraus aufzubauen.

Doch. Du musst nur dafür sorgen, dass eine Python-Referenz zu dem Objekt
existiert, damit Python nicht auf die Idee kommt, dir Garbage Collection
anzuwerfen. PyQt müsste das eigentlich intern machen, ansonsten kannst du dir
auch mit einem Dict behelfen.


> Hmm, obwohl ich da vllt. mit XPath Ausdruecken
> weiterkaeme, die dann eine Liste der Elemente erzeugt und ich kann in
> diese dann indizieren... Kann das klappen?

Weiß nicht, was du meinst, XPath funktioniert aber ansonsten problemlos.


> Wie performant ist die staendige Erzeugung/Loeschung der Objekte? Ein Qt
> ListView liest jedes Objekt bestimmt 6 mal ein bevor der View das erste
> Mal dargestellt wird!

Die Objekte werden nur gelöscht, wenn keine Python-Referenz mehr existiert.
Daher ist es egal, wie oft auf die C-Referenzen zugegriffen wird. Wenn der
Zugriff aber so oft erfolgt, dann solltest du vielleicht nicht nur direkt über
die XML-API arbeiten, sondern einmal ausgelesene Werte im Objekt selbst als
simples Datenfeld zwischenspeichern, um Zugriffe zu vermeiden. Siehe
entsprechende Einträge im Python Cookbook. Oben könnte das z.B. so aussehen:

@property
def title(self):
  self.title = self[0].text
  return self.title

Dann geht der Zugriff beim nächsten Mal schneller, da direkt auf den Wert
zugegriffen werden kann. Allerdings ist er dann nicht mehr veränderbar. Für
den Fall gibt es ausgefeiltere Methoden (siehe Cookbook)

Stefan