Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einleitung
2 Überblick über Python
3 Die Arbeit mit Python
4 Der interaktive Modus
5 Grundlegendes zu Python-Programmen
6 Kontrollstrukturen
7 Das Laufzeitmodell
8 Basisdatentypen
9 Benutzerinteraktion und Dateizugriff
10 Funktionen
11 Modularisierung
12 Objektorientierung
13 Weitere Spracheigenschaften
14 Mathematik
15 Strings
16 Datum und Zeit
17 Schnittstelle zum Betriebssystem
18 Parallele Programmierung
19 Datenspeicherung
20 Netzwerkkommunikation
21 Debugging
22 Distribution von Python-Projekten
23 Optimierung
24 Grafische Benutzeroberflächen
25 Python als serverseitige Programmiersprache im WWW mit Django
26 Anbindung an andere Programmiersprachen
27 Insiderwissen
28 Zukunft von Python
A Anhang
Stichwort

Download:
- ZIP, ca. 4,8 MB
Buch bestellen
Ihre Meinung?

Spacer
 <<   zurück
Python von Peter Kaiser, Johannes Ernesti
Das umfassende Handbuch - Aktuell zu Python 2.5
Buch: Python

Python
gebunden, mit CD
819 S., 39,90 Euro
Galileo Computing
ISBN 978-3-8362-1110-9
Pfeil 19 Datenspeicherung
  Pfeil 19.1 Komprimierte Dateien lesen und schreiben – gzStandardbibliothekgzipip
  Pfeil 19.2 XML
    Pfeil 19.2.1 DOM – Document Object Model
    Pfeil 19.2.2 SAX – Simple API for XML
    Pfeil 19.2.3 ElementTree
  Pfeil 19.3 Datenbanken
    Pfeil 19.3.1 Pythons eingebaute Datenbank – sqlite3
    Pfeil 19.3.2 MySQLdb
  Pfeil 19.4 Serialisierung von Instanzen – pickle
  Pfeil 19.5 Das Tabellenformat CSV – csv
  Pfeil 19.6 Temporäre Dateien – tempfile


Galileo Computing - Zum Seitenanfang

19.2 XML  Zur nächsten ÜberschriftZur vorigen Überschrift

Das Modul xml der Standardbibliothek erlaubt es, XML-Dateien einzulesen. XML (kurz für »Extensible Markup Language«) ist eine standardisierte Beschreibungssprache, die es ermöglicht, komplexe, hierarchisch aufgebaute Datenstrukturen in einem lesbaren Textformat abzuspeichern. XML kann daher sehr gut zum Datenaustausch bzw. zur Datenspeicherung verwendet werden.

Besonders in der Welt des Internets finden sich viele auf XML basierende Beschreibungssprachen, wie beispielsweise XHTML, RSS, MathML oder SVG.

An dieser Stelle soll eine kurze Einführung in XML gegeben werden. Dazu dient folgende, einfache XML-Datei, die eine Möglichkeit aufzeigt, wie der Inhalt eines Python-Dictionarys dauerhaft abgespeichert werden könnte:

<?xml version="1.0" encoding="UTF-8"?> 
<dictionary> 
    <eintrag> 
        <schluessel>Hallo</schluessel> 
        <wert>0</wert> 
    </eintrag> 
    <eintrag> 
        <schluessel>Welt</schluessel> 
        <wert>1</wert> 
    </eintrag> 
</dictionary>

Die erste Zeile der Datei ist die sogenannte XML-Deklaration. Diese optionale Angabe kennzeichnet die verwendete Version von XML und vor allem, was viel wichtiger ist, das Encoding, in dem die Datei gespeichert wurde. Durch Angabe des Encodings, in diesem Fall UTF-8, können auch Umlaute und andere Sonderzeichen korrekt verarbeitet werden.

Abgesehen von der XML-Deklaration besteht ein XML-Dokument aus sogenannten Tags. Tags können wie Klammern geöffnet und geschlossen werden und stellen damit eine Art Gruppe dar, die weitere Tags enthalten kann. Jedes Tag hat einen Namen, den sogenannten Tag-Namen. Um ein Tag zu öffnen, wird dieser Tag-Name in spitze Klammern geschrieben. Ein schließendes Tag besteht aus dem Tag-Namen, der zusammen mit einem Slash ebenfalls in spitze Klammern geschrieben wird. Das folgende Beispiel zeigt ein öffnendes Tag, direkt gefolgt von dem entsprechenden schließenden Tag.

<wert></wert>

Innerhalb eines Tags können sowohl Text als auch weitere Tags stehen. Auf diese Weise kann eine hierarchische Struktur erstellt werden, die dazu in der Lage ist, auch komplexe Datensätze abzubilden.

Zudem können bei einem Tag sogenannte Attribute angegeben werden. Dazu soll das vorherige Beispiel dahingehend erweitert werden, dass der Datentyp der Schlüssel und Werte des abzubildenden Dictionarys als Attribut des jeweiligen schluessel- bzw. wert-Tags gespeichert werden kann.

<?xml version="1.0" encoding="UTF-8"?> 
<dictionary> 
    <eintrag> 
        <schluessel typ="str">Hallo</schluessel> 
        <wert typ="int">0</wert> 
    </eintrag> 
    <eintrag> 
        <schluessel typ="str">Welt</schluessel> 
        <wert typ="int">1</wert> 
    </eintrag> 
</dictionary>

Ein Attribut stellt im Prinzip ein Schlüssel/Wert-Paar dar. Im Beispiel wurde jedem schluessel- und wert-Tag ein Attribut typ verpasst, über das der Datentyp des Schlüssels bzw. des Werts angegeben werden kann. Beachten Sie, dass der Wert eines XML-Attributs stets in Anführungszeichen zu schreiben ist.

Zum Einlesen von XML-Dateien stellt Python, wie die meisten anderen Programmiersprachen oder XML-Bibliotheken auch, zwei sogenannte Parser zur Verfügung. Der Begriff des Parsers ist nicht auf XML beschränkt, sondern bezeichnet ganz allgemein ein Programm, das eine Syntaxanalyse bestimmter Daten eines speziellen Formats leistet. Die beiden im Modul xml enthaltenen Parser heißen dom und sax und implementieren zwei unterschiedliche Herangehensweisen an das XML-Dokument. Aus diesem Grund ist es sinnvoll, beide getrennt und ausführlich zu besprechen, was in den nächsten beiden Kapiteln geschehen soll. Das Thema des dritten Unterkapitels soll eine relativ neue Herangehensweise an XML-Daten namens ElementTree sein.


Hinweis
Eine Besonderheit bei XML-Tags stellen sogenannte körperlose Tags dar. Solche Tags spielen in den Beispielen, die in diesem Buch vorgestellt werden, keine Rolle, sind jedoch in einigen Fällen durchaus sinnvoll. Ein körperloses Tag sieht folgendermaßen aus:

<tag attr="wert" />
Ein körperloses Tag ist öffnendes und schließendes Tag zugleich und darf demzufolge nur über Attribute verfügen. Ein solches Tag kann keinen Text oder weitere Tags enthalten. Von einem XML-Parser wird ein körperloses Tag behandelt, als stünde <tag attr="wert"></tag> in der XML-Datei.



Galileo Computing - Zum Seitenanfang

19.2.1 DOM – Document Object Model  Zur nächsten ÜberschriftZur vorigen Überschrift

Das Document Object Model, kurz DOM, ist eine Schnittstelle, die vom World Wide Web Consortium (W3C) standardisiert wurde und es ermöglicht, auf einzelne Elemente einer XML-Datei zuzugreifen und diese zu modifizieren. Dazu wird die Datei vollständig eingelesen und zu einer baumartigen Struktur aufbereitet. Jedes Tag wird durch eine Klasse repräsentiert, den sogenannten Knoten (engl. node). Durch Methoden und Attribute dieser Klasse können die enthaltenen Informationen ausgelesen oder verändert werden.

Das DOM ist vor allem dann interessant, wenn ein wahlfreier Zugriff auf die XML-Daten möglich sein muss. Unter einem wahlfreien Zugriff versteht man den punktuellen Zugriff auf verschiedene, voneinander unabhängige Teile des Datensatzes. Das Gegenteil des wahlfreien Zugriffs wäre das sequenzielle Einlesen der XML-Datei.

Da die Datei stets vollständig eingelesen wird, ist die Verwendung von DOM sehr speicherintensiv. Im Gegensatz dazu liest das Konkurrenzmodell SAX immer nur kleine Teile der XML-Daten ein und stellt sie sofort zur Weiterverarbeitung zur Verfügung. Diese Herangehensweise benötigt weniger Arbeitsspeicher und erlaubt es, Teile der gespeicherten Daten bereits zu verwenden, beispielsweise anzuzeigen, während die Datei selbst noch nicht vollständig eingelesen ist. Ein wahlfreier Zugriff auf die XML-Daten und die Manipulation selbiger ist mit SAX allerdings nicht möglich.

Jetzt möchten wir darauf zu sprechen kommen, wie die XML-Daten bei Verwendung eines DOM-Parsers aufbereitet werden. Betrachten Sie dazu noch einmal unser vorheriges Beispiel einer XML-Datei:

<?xml version="1.0" encoding="UTF-8"?> 
<dictionary> 
    <eintrag> 
        <schluessel typ="str">Hallo</schluessel> 
        <wert typ="int">0</wert> 
    </eintrag> 
    <eintrag> 
        <schluessel typ="str">Welt</schluessel> 
        <wert typ="int">1</wert> 
    </eintrag> 
</dictionary>

Unter Verwendung eines DOM-Parsers werden die XML-Daten zu einem sogenannten Baum aufbereitet. Ein Baum besteht aus einzelnen Klassen, den sogenannten Knoten. Jede dieser Knotenklassen enthält verschiedene Referenzen auf benachbarte Knoten, nämlich:

  • sein Elternelement (engl. parent). Das ist der Knoten, der im Baum direkt über diesem Knoten steht.
  • seine Kindelemente (engl. children). Das sind alle Knoten, die im Baum direkt unter diesem Knoten stehen.
  • seine Geschwisterelemente (engl. siblings). Das sind alle Knoten, die im Baum direkt neben diesem Knoten stehen und dasselbe Elternelement haben.

Somit enthält jeder Knoten des Baumes Referenzen zu allen umliegenden, auch verwandten Knoten. Auf diese Weise lässt sich der Baum vollständig durchlaufen und verarbeiten.

Die aus dem obigen Beispiel erzeugte Baumstruktur sieht folgendermaßen aus:

Abbildung 19.1  Vom DOM-Parser erzeugter Baum

Dabei handelt es sich bei Document, Element und Text um die grundlegenden Knotenklassen, aus denen ein DOM-Baum aufgebaut ist. Die Document-Instanz ist einmalig und entspricht der Wurzel des Baumes (engl. root). Sie enthält eine Referenz auf alle Tags erster Ordnung, wie in diesem Fall beispielsweise das Tag dictionary. Diesem Knoten sind mehrere Instanzen der Klasse Element untergeordnet, die jeweils ein eintrag-Tag repräsentieren. Durch Attribute dieser Klasse können Informationen wie der Tag-Name, enthaltene XML-Attribute oder Ähnliches abgerufen werden.

Beachten Sie zum einen, dass in Abbildung 19.1 aus Gründen der Übersichtlichkeit keine Geschwisterbeziehungen eingezeichnet wurden, und zum anderen, dass die Attribute der Elemente schluessel und wert keine eigenständigen Instanzen einer Knotenklasse sind, sondern Teil des Elementknotens.

Neben den Klassen Document und Element existieren Instanzen einer weiteren Klasse namens Text. Diese Instanzen enthalten Text, der innerhalb eines Tags geschrieben wurde.

Abgesehen von den hier aufgelisteten Klassen gibt es noch weitere Knotenklassen, die allerdings nur in Spezialfällen im Baum vorkommen. So existiert beispielsweise die Klasse Comment für ein Kommentar-Tag in der XML-Datei. Wir möchten uns in diesem Kapitel auf das Wesentliche, das heißt auf die Klassen Document, Element und Text, beschränken.

Beispiel

An dieser Stelle soll die Verwendung von DOM an einem einfachen Beispiel gezeigt werden. Dazu rufen wir uns erneut unsere Beispieldatei ins Gedächtnis, deren Zweck es war, den Inhalt eines Python-Dictionarys abzubilden:

<?xml version="1.0" encoding="UTF-8"?> 
<dictionary> 
    <eintrag> 
        <schluessel typ="str">Hallo</schluessel> 
        <wert typ="int">0</wert> 
    </eintrag> 
</dictionary>

Die Datei besteht aus einem Tag erster Ordnung namens dictionary, in dem mehrere eintrag-Tags vorkommen dürfen. Jedes eintrag-Tag enthält zwei untergeordnete Tags namens schluessel und wert, die gemeinsam jeweils ein Schlüssel/Wert-Paar des Dictionarys repräsentieren. Der Datentyp des Schlüssels bzw. des Wertes wird über das Attribut typ festgelegt, das bei den Tags schluessel und wert vorkommen muss.

Das Beispielprogramm soll dazu in der Lage sein, eine solche XML-Datei einzulesen und das entsprechende Dictionary daraus zu rekonstruieren. Im Folgenden soll der Quelltext des Beispielprogramms besprochen werden.

import xml.dom.minidom as dom
def _knoten_auslesen(knoten): return eval("%s('%s')" % (knoten.getAttribute("typ"), knoten.firstChild.data.strip()))

In der ersten Zeile wird der DOM-Parser eingebunden und unter dem Namensraum dom verfügbar gemacht. Für dieses Beispiel wurde der Parser xml.dom.minidom eingebunden, der eine grundlegende und simple Implementation darstellt, die in den meisten Fällen genügen sollte. Abgesehen von dem Minidom-Parser existieren noch weitere spezielle DOM-Parser im Paket xml.dom.

Danach wird die Funktion _knoten_auslesen definiert. Der Funktionsname beginnt mit einem Unterstrich, da es sich um eine Hilfsfunktion handelt, die für sich allein keinen Wert darstellt. Die Aufgabe der Funktion _knoten_auslesen ist es, aus einer Element-Instanz das Attribut typ auszulesen und den im Element enthaltenen Text in den angegebenen Datentyp zu konvertieren. Dazu wird dynamisch ein String erzeugt, der beispielsweise für den Typ int und den Text "123" zu "int('123')" wird. Dieser String wird mittels eval interpretiert und zurückgegeben. Beachten Sie, dass aus Gründen der Übersichtlichkeit alle Konsistenzprüfungen weggelassen wurden. In einem normalen Programm sollte in der Funktion _knoten_auslesen beispielsweise geprüft werden, ob ein Attribut typ überhaupt existiert oder ob der dort angegebene Datentyp gültig ist.

Das Auslesen eines XML-Attributs geschieht über die Methode getAttribute einer Element-Instanz. Um den vom Tag umschlossenen Text auszulesen, wird über das Attribut firstChild das erste Kindelement der übergebenen Element-Instanz angesprochen. Dabei handelt es sich um die jeweilige Text-Instanz. Über das Attribut data dieser Text-Instanz kann der enthaltene Text ausgelesen werden.

Beachten Sie beim Arbeiten mit Text-Instanzen, dass der DOM-Standard vorsieht, dass Whitespace-Zeichen, auch wenn sie nur aus Formatierungsgründen in der XML-Datei stehen, später im Baum wiederzufinden sind. Aus diesem Grund müssen wir eventuell vorkommende Whitespace-Zeichen durch Aufruf der String-Methode strip entfernen.

def lade_dict(dateiname): 
    d = {} 
    baum = dom.parse(dateiname)
for eintrag in baum.firstChild.childNodes: if eintrag.nodeName == "eintrag": schluessel = wert = None
for knoten in eintrag.childNodes: if knoten.nodeName == "schluessel": schluessel = _knoten_auslesen(knoten) elif knoten.nodeName == "wert": wert = _knoten_auslesen(knoten)
d[schluessel] = wert return d

Danach wird die Hauptfunktion lade_dict definiert. Die Aufgabe dieser Funktion ist es, eine XML-Datei, deren Dateinamen sie übergeben bekommt, zu öffnen, die enthaltenen Informationen zu extrahieren, in das Dictionary d zu schreiben und das entstandene Dictionary zurückzugeben.

Zunächst wird durch Aufruf der Funktion parse des minidom-Parsers das XML-Dokument eingelesen und zu einer Baumstruktur aufbereitet. Die Referenz baum referenziert jetzt eine Instanz der Klasse Document, über die auf alle Elemente des Dokuments zugegriffen werden kann. Alternativ hätte auch die Methode parse String des minidom-Parsers aufgerufen werden können, wenn die XML-Daten in Form eines Strings vorliegen würden.

Dann soll über alle eintrag-Tags iteriert und das jeweilige Schlüssel/Wert-Paar ins Dictionary d eingefügt werden. Dazu nutzen wir die Attribute der Klasse Node, von der sowohl Document als auch Element abgeleitet sind. Von der Document-Instanz baum aus erreichen wir über das Attribut baum.firstChild das erste Kindelement, also die Element-Instanz, die das dictionary-Tag repräsentiert. Genau genommen interessieren wir uns jedoch auch nicht für das dictionary-Tag, sondern für alle diesem Tag direkt untergeordneten Elemente. Diese können wir über das Attribut childNodes erreichen, das eine Liste aller Kindelemente bereitstellt. Über diese Liste wird in einer for-Schleife iteriert.

Innerhalb der for-Schleife wird zunächst geprüft, ob es sich tatsächlich um den Knoten eines eintrag-Tags handelt. Dazu wird das Attribut nodeName verwendet, das jede Node-Instanz, also jeder Knoten besitzt. Beachten Sie wie bereits gesagt, dass der DOM-Standard vorschreibt, auch Whitespaces, die zur Formatierung der XML-Datei eingesetzt wurden, in Form von Text-Instanzen im DOM-Baum einzutragen. Diese Text-Instanzen werden hier ebenfalls herausgefiltert, ihr nodeName-Wert ist "#text". Zudem werden zwei Referenzen namens schluessel und wert angelegt, die später zum Aufbau des Dictionarys verwendet werden.

In der darauf folgenden for-Schleife wird über alle Kindelemente des eintrag-Tags iteriert. Je nachdem, ob es sich bei dem aktuellen Kindelement um ein schluessel- oder ein wert-Tag handelt, wird das Ergebnis des Funktionsaufrufs von _knoten_auslesen dem Namen schluessel bzw. wert zugewiesen. Nachdem die innere Schleife durchlaufen ist, werden Schlüssel und Wert ins Dictionary d eingetragen.

Beachten Sie unbedingt, dass wir in diesem Beispiel davon ausgehen, dass die XML-Datei exakt unseren Ansprüchen entspricht. In einem wirklichen Programm sollten Sie grundsätzlich davon ausgehen, dass auch fehlerhafte Angaben vorkommen, und diese entsprechend behandeln. Auch der sorglose Umgang mit dem Attribut typ (direktes Übergeben nach eval) sollte in einem fertigen Programm so nicht vorkommen.

Dieses Beispiel sollte einen kurzen Überblick über die Verwendung des DOM-Baumes bieten. Im Folgenden werden die Klassen Node, Document, Element und Text besprochen, aus denen ein DOM-Baum zusammengesetzt ist.

Die Klasse Node

Die Klasse Node ist die Basisklasse aller im DOM-Baum verwendeten Klassen. Das bedeutet, dass die in dieser Klasse enthaltene Funktionalität an allen Knoten des Baumes verfügbar ist. In der Klasse Node sind vor allem Attribute und Methoden enthalten, die es ermöglichen, Zugriff auf verwandte Knoten, das heißt Kinder, Geschwister oder den Elternknoten, zu erlangen.

Im Folgenden sollen die wichtigsten Attribute der Klasse Node beschrieben werden. Dabei soll n eine Instanz der Klasse Node sein.

n.nodeType

Kennzeichnet den Typ des Knotens. Das Attribut referenziert eine ganze Zahl, die mit folgenden symbolischen Konstanten verglichen werden kann:


Tabelle 19.2  Konstanten zur Beschreibung eines Knotentyps
Konstante Beschreibung

Node.ELEMENT_NODE

Bei dem Knoten handelt es sich um eine Element-Instanz.

Node.TEXT_NODE

Bei dem Knoten handelt es sich um eine Text-Instanz.

Node.DOCUMENT_NODE

Bei dem Knoten handelt es sich um eine Document-Instanz.


n.parentNode

Referenziert das Elternelement des Knotens n. Wenn es sich bei dem Knoten um die Document-Instanz handelt, referenziert dieses Attribut None.

n.previousSibling

Referenziert das Geschwisterelement, das in der Reihenfolge vor dem Knoten n steht, oder None, wenn dieser Knoten das erste Kind von parentNode ist.

n.nextSibling

Referenziert das Geschwisterelement, das in der Reihenfolge hinter dem Knoten n steht, oder None, wenn dieser Knoten das letzte Kind von parentNode ist.

n.firstChild

Referenziert das erste Kindelement des Knotens n oder None, wenn keine untergeordneten Knoten existieren.

n.lastChild

Referenziert das letzte Kindelement des Knotens n oder None, wenn keine untergeordneten Knoten existieren.

Abbildung 19.2 soll die hier vorgestellten Attribute anhand der Beziehung von drei Knoten eines Baumes verdeutlichen:

Abbildung 19.2  Verwandtschaftsbeziehungen dreier Knoten

n.childNodes

Referenziert eine Liste aller Kinder des Knotens n.

Dieser Auflistung der wichtigsten Attribute der Klasse Node folgen die wichtigsten Methoden dieser Klasse.

n.hasChildNodes()

Gibt True zurück, wenn der Knoten n über Kinder verfügt, andernfalls False.

n.appendChild(newChild)

Fügt die Node-Instanz newChild als Kindelement an das Ende der Liste aller Kinder von n ein. Beachten Sie, dass diese Methode den DOM-Baum verändert.

n.insertBefore(newChild, refChild)

Fügt die Node-Instanz newChild als Kindelement des aktuellen Knotens vor dem Kindelement refChild in die Liste aller Kinder von n ein. Beachten Sie, dass diese Methode den DOM-Baum verändert.

n.removeChild(oldChild)

Löscht das angegebene Kindelement oldChild. Beachten Sie, dass diese Methode den DOM-Baum verändert.

n.replaceChild(newChild, oldChild)

Ersetzt das Kindelement oldChild durch newChild. Beachten Sie, dass diese Methode den DOM-Baum verändert.

n.writexml(writer[, indent[, addindent[, newl]]])

Schreibt die Node-Instanz n mitsamt all ihren Kindelementen als XML in das geöffnete Dateiobjekt writer. Beachten Sie, dass diese Methode auch an die Klasse Document weitervererbt wird. Wenn sie für eine Document-Instanz aufgerufen wird, kann der vollständige DOM-Baum als XML-Datei gespeichert werden.

Die optionalen Parameter indent, addindent und newl (allesamt Strings) können verwendet werden, um die Ausgabe der XML-Daten zu formatieren. Dabei steht indent für die Zeichen, die zur Einrückung der gesamten Ausgabe verwendet werden, addindent für die Zeichen, die zur Einrückung tieferer Ebenen verwendet werden, und newl für das zu verwendende Newline-Zeichen.

Wenn die Methode auf einer Document-Instanz aufgerufen wird, kann ein zusätzlicher, optionaler Schlüsselwortparameter encoding angegeben werden. Das hier als String übergebene Encoding wird in die XML-Deklaration eingetragen und zum Speichern der Datei verwendet.

n.toxml([encoding])

Ähnlich wie writexml, gibt die XML-Daten jedoch als String zurück. Optional kann über den Parameter encoding ein Encoding angegeben werden, das in die XML-Deklaration geschrieben und im zurückgegebenen String verwendet wird.

n.toprettyxml([indent[, newl]])

Ähnlich wie toxml, gibt die XML-Daten jedoch in einem formatierten String zurück. Um die Formatierung der Daten zu verändern, können das Einrückungszeichen (indent, üblicherweise \t) und das zu verwendende Newline-Zeichen (newl, üblicherweise \n) angegeben werden.

Ein Encoding kann wie bei der Methode writexml angegeben werden.

Die Klasse Document

Ein von einem DOM-Parser erzeugter Baum enthält als Wurzelelement eine Instanz der Klasse Document. Dies ist die Instanz, die bei einem Aufruf der Funktion parse zurückgegeben wird und alle weiteren Elemente des Baumes direkt oder indirekt referenziert. Eine Document-Instanz verwaltet dabei immer ein vollständiges XML-Dokument.

Die Klasse Document erbt von der Basisklasse Node.

Nachfolgend sollen die wichtigsten Methoden und Attribute der Klasse Document erläutert werden. Dabei sei d eine Instanz der Klasse Document.

d.documentElement

Dieses Attribut referenziert die Element-Instanz des ersten Tags des XML-Dokuments d. Beachten Sie, dass ein wohlgeformtes XML-Dokument über genau ein Wurzel-Tag verfügt. Sollten mehrere sogenannte toplevel-Tags vorkommen, kann auf diese über ihre Geschwisterbeziehung zu documentElement zugegriffen werden.

d.createElement(tagName)

Erzeugt einen neuen Elementknoten mit dem Tag-Namen tagName. Die Funktion gibt eine Instanz der Klasse Element zurück. Beachten Sie, dass der Knoten zwar erzeugt, aber nicht automatisch in den Baum eingefügt wird. Dazu können beispielsweise die Methoden insertBefore oder appendChild der Klasse Node verwendet werden.

d.createTextNode(data)

Erzeugt einen neuen Textknoten mit dem Inhalt data. Die Funktion gibt eine Instanz der Klasse Text zurück. Für diese Methode gilt ebenfalls der Hinweis, dass der erzeugte Knoten nicht automatisch in den DOM-Baum eingefügt wird.

d.getElementsByTagName(tagName)

Gibt eine Liste zurück, in der alle Element-Instanzen enthalten sind, die Tags mit dem Tag-Namen tagName repräsentieren.

Die Klasse Element

Die Klasse Element repräsentiert ein Tag im DOM-Baum. Sie erbt von der Basisklasse Node.

Im Folgenden sollen die wichtigsten Attribute und Methoden der Klasse Element erläutert werden. Dabei sei e eine Instanz der Klasse Element.

e.tagName

Dieses Attribut referenziert den Tag-Namen des von e repräsentierten Tags.

e.getElementsByTagName(tagName)

Äquivalent zu Document.getElementsByTagName. Beachten Sie, dass diese Methode nur nach direkt oder indirekt untergeordneten Elementen mit dem Tag-Namen tagName sucht.

e.hasAttribute(name)

Gibt True zurück, wenn das Element e ein Attribut mit dem Schlüssel name besitzt, andernfalls False.

e.getAttribute(name)

Gibt den Wert des Attributs mit dem Schlüssel name zurück. Sollte kein Attribut name existieren, wird ein leerer String zurückgegeben.

e.removeAttribute(name)

Löscht das Attribut mit dem Schlüssel name. Beachten Sie, dass keine Exception geworfen wird, wenn kein Attribut mit dem Schlüssel name existiert.

e.setAttribute(name, value)

Erzeugt ein neues Attribut mit dem Schlüssel name und dem Wert value oder überschreibt ein bereits bestehendes Attribut.

Die Klasse Text

Die Klasse Text erbt von Node und fügt ein einziges Attribut hinzu:

t.data

Das Attribut data referenziert den String, den die Text-Instanz t repräsentiert.

Schreiben einer XML-Datei

Im vorangegangenen Beispiel wurde gezeigt, wie die in einer XML-Datei enthaltenen Daten zu einem Baum aufbereitet werden können. Zudem haben Sie soeben einige Methoden der Knotenklassen des Baums kennengelernt, die dazu in der Lage sind, den Baum zu modifizieren. Der nächste logische Schritt ist es, den modifizierten Baum wieder als XML-Datei abzuspeichern.

In diesem Abschnitt wird ein Beispielprogramm besprochen, das den umgekehrten Weg des ersten Beispiels geht. Das heißt, es erzeugt aus einem Dictionary einen DOM-Baum und speichert diesen als XML-Datei ab. Diese XML-Datei soll so aufgebaut sein, dass sie von dem vorherigen Beispielprogramm wieder ausgelesen werden kann.

Das Schreiben der XML-Datei soll durch eine Funktion schreibe_dict erfolgen, die das zu schreibende Dictionary d und den Dateinamen der Ausgabedatei als Parameter übergeben bekommt. Der Quelltext des Beispielprogramms sieht folgendermaßen aus:

import xml.dom.minidom as dom
def _erstelle_eintrag(schluessel, wert): tag_eintrag = dom.Element("eintrag") tag_schluessel = dom.Element("schluessel") tag_wert = dom.Element("wert")
tag_schluessel.setAttribute("typ", type(schluessel).__name__) tag_wert.setAttribute("typ", type(wert).__name__)
text = dom.Text() text.data = str(schluessel) tag_schluessel.appendChild(text)
text = dom.Text() text.data = str(wert) tag_wert.appendChild(text)
tag_eintrag.appendChild(tag_schluessel) tag_eintrag.appendChild(tag_wert) return tag_eintrag

Auch hier wird, ähnlich wie beim vorherigen Beispiel, zuerst eine Hilfsfunktion angelegt, die einen Schlüssel und einen Wert übergeben bekommt und daraus eine Element-Instanz erzeugt, die das entsprechende eintrag-Tag repräsentiert. Die Funktion an sich bedarf eigentlich keiner weiteren Erläuterung. Einzig erwähnenswert ist folgender Ausdruck:

type(schluessel).__name__

Dieser Ausdruck ermittelt den Namen des Datentyps der von schluessel referenzierten Instanz. Das wäre beispielsweise "int" für ganze Zahlen oder "str" für Strings. Jetzt folgt die Hauptfunktion des Beispielprogramms:

def schreibe_dict(d, dateiname): 
    baum = dom.Document() 
    tag_dict = dom.Element("dictionary") 
    baum.appendChild(tag_dict)
for schluessel, wert in d.iteritems(): tag_eintrag = _erstelle_eintrag(schluessel, wert) tag_dict.appendChild(tag_eintrag)
f = open(dateiname, "w") baum.writexml(f, "", "\t", "\n") f.close()

Im Funktionskörper wird zunächst eine neue Instanz der Klasse Document angelegt. Diese Instanz soll die Wurzel des DOM-Baums werden, den wir im Laufe der Funktion erzeugen, und wird von baum referenziert. Danach wird das oberste Element, das dictionary-Tag, erzeugt und an die Document-Instanz als Kindelement angefügt. Das dictionary-Tag wird von tag_dict referenziert.

Danach werden in einer for-Schleife alle Schlüssel/Wert-Paare des Dictionarys d durchlaufen. In jedem Schleifendurchlauf wird eine neue Element-Instanz für das jeweilige eintrag-Tag mithilfe der Funktion _erstelle_eintrag erzeugt. Danach wird die erzeugte Element-Instanz als Kindelement des dictionary-Tags in den DOM-Baum eingefügt.

Am Ende der Funktion wird die Datei dateiname zum Schreiben geöffnet und die XML-Daten mittels der Methode writexml hineingeschrieben.

Die hier vorgestellte Funktion schreibe_dict arbeitet perfekt mit der Funktion lade_dict des vorherigen Beispiels zusammen. Das bedeutet, dass eine von schreibe_dict erzeugte XML-Datei problemlos von lade_dict wieder eingelesen werden kann.

Damit wäre das Konzept des Document Object Model umrissen und anhand zweier grundlegender Beispiele erklärt. Beachten Sie, dass hier nicht alle Möglichkeiten von DOM angesprochen wurden. Fühlen Sie sich also dazu ermutigt, weiter zu recherchieren und auszuprobieren, wenn Sie weitere Details zu speziellen Features des DOM erfahren möchten.


Galileo Computing - Zum Seitenanfang

19.2.2 SAX – Simple API for XML  Zur nächsten ÜberschriftZur vorigen Überschrift

Nachdem wir uns im letzten Abschnitt ausführlich der DOM-Herangehensweise an XML-Dateien gewidmet haben, möchten wir nun einen zweiten Weg vorstellen, diese Dateien zu verarbeiten. Die Simple API for XML, kurz SAX, baut im Gegensatz zu DOM kein vollständiges Abbild der XML-Datei im Speicher auf, sondern liest die Datei fortlaufend ein und setzt den Programmierer durch Aufrufen bestimmter Funktionen davon in Kenntnis, dass beispielsweise ein öffnendes oder schließendes Tag gelesen wurde. Diese Herangehensweise hat neben der Speichereffizienz noch einen weiteren Vorteil: Beim Laden von sehr großen XML-Dateien können bereits eingelesene Teile weiterverarbeitet werden, obwohl die Datei noch nicht vollständig eingelesen worden ist.

Allerdings sind mit der Verwendung von SAX auch einige Nachteile verbunden. So ist beispielsweise kein wahlfreier Zugriff auf einzelne Elemente der XML-Daten möglich, wie es beispielsweise bei DOM praktiziert werden kann. Außerdem sieht SAX keine Möglichkeit vor, die XML-Daten komfortabel zu verändern oder wieder zu speichern. Doch nun zur Funktionsweise von SAX.

Das Einlesen einer XML-Datei durch einen SAX-Parser, in der SAX-Terminologie auch Reader genannt, geschieht event-gesteuert. Das bedeutet, dass der Programmierer beim Erstellen des Readers verschiedene sogenannte Callback-Funktionen einrichten und mit einem bestimmten Event verknüpfen muss. Wenn beim Einlesen der XML-Datei durch den Reader dann das besagte Event auftritt, wird die damit verknüpfte Callback-Funktion aufgerufen und somit der Code ausgeführt, den der Programmierer für diesen Zweck vorgesehen hat. Ein Event könnte beispielsweise das Auffinden eines öffnenden Tags sein.

Man könnte also sagen, dass der SAX-Reader nur die Infrastruktur zum Einlesen der XML-Datei bereitstellt. Ob und in welcher Form die gelesenen Daten aufbereitet werden, entscheidet allein der Programmierer. Damit bietet SAX wesentlich mehr Flexibilität als DOM, auf Kosten eines mitunter höheren Aufwandes selbstverständlich.

Beispiel

Die Verwendung von SAX soll direkt an einem einfachen Beispiel gezeigt werden. Dazu dient uns das bereits bekannte Szenario: Ein Python-Dictionary wurde in einer XML-Datei abgespeichert und soll durch das Programm eingelesen und wieder in ein Dictionary verwandelt werden. Die Daten liegen im folgenden Format vor:

<?xml version="1.0" encoding="UTF-8"?> 
<dictionary> 
    <eintrag> 
        <schluessel typ="str">Hallo</schluessel> 
        <wert typ="int">0</wert> 
    </eintrag> 
</dictionary>

Zum Einlesen dieser Datei dient folgendes Programm, das einen SAX-Reader verwendet:

import xml.sax as sax
class DictHandler(sax.handler.ContentHandler):
def __init__(self): self.ergebnis = {} self.schluessel = "" self.wert = "" self.aktiv = None self.typ = None
def startElement(self, name, attrs): if name == "eintrag": self.schluessel = "" self.wert = "" elif name == "schluessel" or name == "wert": self.aktiv = name self.typ = eval(attrs["typ"])
def endElement(self, name): if name == "eintrag": self.ergebnis[self.schluessel] = self.typ(self.wert) elif name == "schluessel" or name == "wert": self.aktiv = None
def characters(self, content): if self.aktiv == "schluessel": self.schluessel += content elif self.aktiv == "wert": self.wert += content

Zunächst wird die Klasse DictHandler angelegt, in der alle interessanten Callback-Funktionen, auch Callback-Handler genannt, in Form von Methoden implementiert werden. Die Klasse muss von der Basisklasse sax.handler.Content Handler abgeleitet werden.

Ein Nachteil des SAX-Modells ist es, dass man nach jedem Schritt den aktuellen Status speichern muss, damit beim nächsten Aufruf einer der Callback-Funktionen klar ist, ob der eingelesene Text beispielsweise innerhalb eines schluessel- oder eines wert-Tags gelesen wurde. Aus diesem Grund legen wir im Konstruktor der Klasse einige Attribute an:

  • self.ergebnis für das resultierende Dictionary,
  • self.schluessel für den Inhalt des aktuell bearbeiteten Schlüssels,
  • self.wert für den Inhalt des aktuell bearbeiteten Wertes,
  • self.aktiv für den Tag-Namen des Tags, das zuletzt eingelesen wurde, und
  • self.typ für den Datentyp, der im Attribut typ eines schluessel- oder wert-Tags steht.

Zuerst implementieren wir die Methode startElement, die immer dann aufgerufen wird, wenn ein öffnendes Tag eingelesen wurde. Die Methode bekommt den Tag-Namen und die enthaltenen Attribute als Parameter übergeben. In dieser Methode wird zunächst ausgelesen, um welches öffnende Tag es sich handelt. Im Falle eines schluessel- oder wert-Tags wird self.name entsprechend angepasst und das Attribut typ des Tags ausgelesen.

Die Methode endElement wird aufgerufen, wenn ein schließendes Tag eingelesen wurde. Auch sie bekommt den Tag-Namen als Parameter übergeben. Im Falle eines schließenden eintrag-Tags fügen wir das eingelesene Schlüssel/Wert-Paar, das aus self.schluessel und self.wert besteht, in das Dictionary self.ergeb nis ein. Wenn ein schließendes schluessel- oder wert-Tag gefunden wurde, wird das Attribut self.aktiv wieder auf None gesetzt, sodass keine weiteren Zeichen mehr verarbeitet werden.

Die letzte Methode characters wird aufgerufen, wenn Zeichen eingelesen wurden, die nicht zu einem Tag gehören. Beachten Sie, dass der SAX-Reader nicht garantiert, dass eine zusammenhängende Zeichenfolge auch in einem einzelnen Aufruf von characters resultiert. Je nachdem, welchen Namen das zuletzt eingelesene Tag hatte, werden die gelesenen Zeichen an self.schluessel oder self.wert angehängt.

Schlussendlich fehlt noch die Hauptfunktion lade_dict des Beispielprogramms, in der der SAX-Parser erzeugt und gestartet wird.

def lade_dict(dateiname): 
    handler = DictHandler() 
    parser = sax.make_parser() 
    parser.setContentHandler(handler) 
    parser.parse(dateiname) 
    return handler.ergebnis

Im Funktionskörper wird die Klasse DictHandler instanziiert, und durch die Funktion make_parser des Moduls xml.sax wird ein SAX-Parser erzeugt. Dann wird die Methode setContentHandler des Parsers aufgerufen, um die DictHand ler-Instanz mit den enthaltenen Callback-Handlern anzumelden. Zum Schluss wird der Parsing-Prozess durch die Methode parse eingeleitet.

Die Klasse ContentHandler

Die Klasse ContentHandler dient als Basisklasse und implementiert alle SAX-Callback-Handler als Methoden. Um einen SAX-Parser einsetzen zu können, muss eine eigene Klasse erstellt werden, die von ContentHandler erbt und die benötigten Callback-Handler überschreibt. Eine Instanz einer von ContentHandler abgeleiteten Klasse wird von der Methode setContentHandler des SAX-Parsers erwartet.

Es folgt eine Auflistung der wichtigsten Callback-Handler, die in einer von ContentHandler abgeleiteten Klasse überschrieben werden können. Dabei sei c eine Instanz der Klasse ContentHandler.

c.startDocument()

Wird einmalig aufgerufen, wenn der SAX-Parser damit beginnt, ein XML-Dokument einzulesen.

c.endDocument()

Wird einmalig aufgerufen, wenn der SAX-Parser ein XML-Dokument vollständig eingelesen hat.

c.startElement(name, attrs)

Wird aufgerufen, wenn ein öffnendes Tag eingelesen wurde. Die Methode bekommt weitere Informationen über das Tag in Form von zwei Parametern übergeben: den Tag-Namen (name) und die im Tag angegebenen Attribute (attrs) als Attributes-Instanz. Auf eine solche Instanz kann wie auf ein Dictionary zugegriffen werden, um einzelne Attribute abzufragen.

c.endElement(name)

Wird aufgerufen, wenn ein schließendes Tag mit dem Tag-Namen name eingelesen wurde.

c.characters(content)

Wird aufgerufen, wenn ein Textabschnitt eingelesen wurde. Beachten Sie, dass es dem SAX-Parser freisteht, den gesamten Textabschnitt in einem Event zu verarbeiten oder auf mehrere Events aufzuteilen.

Über den Parameter content können Sie auf den gelesenen Text zugreifen.

c.ignorableWhitespace(whitespace)

Wird aufgerufen, wenn Whitespace-Zeichen eingelesen wurden. Diese könnten von Bedeutung sein, sind jedoch in den meisten Fällen allein aus Gründen der Formatierung vorhanden und können ignoriert werden. Beachten Sie, dass der SAX-Parser auch hier eine Folge von mehreren Whitespace-Zeichen auf mehrere Events aufteilen kann.

Über den Parameter whitespace können Sie auf die gelesenen Zeichen zugreifen.

So viel zur DOM- und SAX-Implementierung in Python. Diese Kapitel sollten nicht als DOM- bzw. SAX-Referenz verstanden werden, sondern als projektorientierte Einführung in die Thematik. Bedenken Sie, dass XML, aber auch DOM und SAX standardisiert sind bzw. De-facto-Standards darstellen. Es existieren DOM- und SAX-Implementierungen für so gut wie jede nennenswerte Programmiersprache, und dementsprechend einfach sollte es sein, weitere Informationen zu diesen Themen zu finden.

Im nun folgenden Abschnitt möchten wir uns einer dritten Herangehensweise an XML namens ElementTree widmen.


Galileo Computing - Zum Seitenanfang

19.2.3 ElementTree  topZur vorigen Überschrift

Seit Python 2.5 ist im Modul xml.etree.ElementTree der Standardbibliothek der Datentyp ElementTree enthalten, der in einer gewissen Konkurrenz zu DOM steht. Der Datentyp ElementTree speichert ein XML-Dokument und stellt außerordentlich komfortable Möglichkeiten zur Verfügung, sich in diesem Dokument zu bewegen und Daten auszulesen. Im Gegensatz zu DOM ist ElementTree nicht für mehrere Sprachen verfügbar oder gar standardisiert, weswegen es spezielle Sprachfeatures von Python, beispielsweise Iteratoren, nutzen kann und sich somit perfekt in die Sprache Python integriert.

Auch eine ElementTree-Instanz kann, ähnlich wie bei DOM, als Baum betrachtet werden. Dieser Baum besteht aus Instanzen der Klasse Element, die jeweils ein Tag repräsentieren. Attribute und Textinhalt der Tags werden ebenfalls in der jeweiligen Element-Instanz gespeichert.

Im Folgenden sollen zunächst die im Modul xml.etree.ElementTree enthaltenen Funktionen und danach die Klassen ElementTree und Element erläutert werden.

Der Inhalt des Moduls ElementTree

In diesem Abschnitt sollen die wichtigsten Funktionen besprochen werden, die im Modul xml.etree.ElementTree enthalten sind. Mit diesen Funktionen ist es beispielsweise möglich, eine XML-Datei einzulesen und zu einer ElementTree-Instanz aufzubereiten.

ElementTree.parse(source[, parser])

Liest die XML-Datei source ein und gibt die aufbereiteten XML-Daten in Form einer ElementTree-Instanz zurück. Für den Parameter source kann sowohl ein Dateiname als auch ein geöffnetes Dateiobjekt übergeben werden. Durch Angabe des optionalen Parameters parser kann ein eigener XML-Parser verwendet werden. Ein solcher Parser muss von der Klasse TreeBuilder abgeleitet werden, was wir an dieser Stelle nicht näher erläutern möchten. Der Standardparser ist die Klasse XMLTreeBuilder.

ElementTree.tostring(element[, encoding])

Schreibt die Element-Instanz element mit all ihren Unterelementen als XML in einen String und gibt diesen zurück. Durch den optionalen Parameter encoding kann das Encoding des resultierenden Strings festgelegt werden.

Die Klasse ElementTree

Die Klasse ElementTree repräsentiert ein XML-Dokument und enthält damit den vollständigen Baum, der daraus aufgebaut worden ist. Eine Instanz der Klasse ElementTree stellt die folgenden Methoden bereit. Im Folgenden sei et eine Instanz der Klasse ElementTree.

et.getiterator([tag])

Die Methode getiterator gibt einen Iterator zurück, der alle Elemente des Baums inklusive des Wurzelelements durchläuft. Die Elemente werden dabei in der Reihenfolge durchlaufen, in der ihre öffnenden Tags in der XML-Datei vorkommen. Wenn der optionale Parameter tag angegeben wurde, durchläuft der zurückgegebene Iterator alle Elemente des Baums mit dem Tag-Namen tag.

et.getroot()

Gibt die Element-Instanz des Wurzelelements zurück.

et.write(file[, encoding])

Speichert den vollständigen Baum als XML-Datei file ab. Dabei kann für file sowohl ein Dateiname als auch ein zum Schreiben geöffnetes Dateiobjekt übergeben werden. Über den optionalen Parameter encoding kann das Encoding der geschriebenen Daten festgelegt werden.

Die Klasse Element

Die Klasse Element repräsentiert ein Tag des XML-Dokuments im ElementTree-Baum. Dafür kann eine Element-Instanz über beliebig viele Kindelemente verfügen.

Die Klasse Element erbt alle Eigenschaften einer Liste. Es ist also möglich, auf Kindelemente wie bei einer Liste mit ihrem Index zuzugreifen. Außerdem können insbesondere die Methoden append, insert, items, keys und remove einer Liste verwendet werden. Im Folgenden sei e eine Instanz der Klasse Element.

e.find(path)

Gibt das erste direkte Kindelement von e mit dem Tag-Namen path zurück. Statt eines einzelnen Tag-Namens kann für path, wie der Name bereits andeutet, auch ein Pfad übergeben werden. So würde ein Aufruf von find mit einem Parameter path von "element1/element2" das erste Kindelement namens element2 des ersten direkten Kindelements mit dem Tag-Namen element1 zurückgeben. Auch das Wildcard-Zeichen * kann verwendet werden, um einen beliebigen Tag-Namen zu kennzeichnen.

e.findall(path)

Wie find, gibt aber eine Liste aller passenden Element-Instanzen zurück statt nur des zuerst gefundenen Elements.

e.findtext(path[, default])

Wenn für path ein leerer String übergeben wird, gibt die Methode findtext den Text als String zurück, den e enthält. Ansonsten kann der Parameter path wie bei den Methoden find und findall verwendet werden. Wenn eine Element-Instanz keinen Text enthält, wird None zurückgegeben. Sollte dies nicht Ihren Wünschen entsprechen, können Sie über den Parameter default festlegen, was in diesen Fällen stattdessen zurückgegeben werden soll.

Beachten Sie, dass auch Whitespace-Zeichen wie beispielsweise ein Zeilenumbruch zum Text einer Element-Instanz zählen.

e.get(key[, default])

Mithilfe der Methode get kann auf den Wert des Attributs key der Element-Instanz e zugegriffen werden. Wenn kein Attribut mit dem Schlüssel key vorhanden ist, wird default zurückgegeben. Der Parameter default ist mit None vorbelegt.

e.set(key, value)

Durch Aufruf der Methode set wird ein neues Attribut mit dem Schlüssel key und dem Wert value im Element e angelegt.

e.getiterator([tag])

Die Methode getiterator hat die gleiche Bedeutung wie die gleichnamige Methode der Klasse ElementTree, allerdings nur für alle Kindelemente von e.

e.getchildren()

Gibt eine Liste aller Kindelemente zurück.

Neben den soeben besprochenen Methoden verfügen alle Element-Instanzen über die folgenden Attribute:

e.attrib

Das Attribut attrib referenziert ein Dictionary, das alle in der Element-Instanz e vorhandenen XML-Attribute als Schlüssel/Wert-Paare enthält.

e.tag

Das Attribut tag enthält den Tag-Namen des Elements e.

e.text

Das Attribut text enthält den Text, der in der XML-Datei zwischen dem öffnenden Tag der Element-Instanz e und dem öffnenden Tag des ersten Kindelements steht. Wenn kein Kindelement existiert, enthält das Attribut text den vollständigen im Körper des Tags enthaltenen Text.

e.tail

Das Attribut tail enthält den Text, der in der XML-Datei zwischen dem schließenden Tag der Element-Instanz e und dem nächsten öffnenden oder schließenden Tag steht.

Beispiel

Als Beispiel für die Verwendung des Datentyps ElementTree soll das Beispielprogramm der vorherigen Abschnitte an diesen Datentyp angepasst werden und somit seine Stärken demonstrieren. Das Beispielprogramm soll eine XML-Datei des folgenden Formats einlesen und zu einem Dictionary aufbereiten:

<?xml version="1.0" encoding="UTF-8"?> 
<dictionary> 
    <eintrag> 
        <schluessel typ="str">Hallo</schluessel> 
        <wert typ="int">0</wert> 
    </eintrag> 
</dictionary>

Der Quelltext des Beispielprogramms sieht folgendermaßen aus:

import xml.etree.ElementTree as ElementTree
def _lese_text(element): typ = element.get("typ", "str") return eval("%s('%s')" % (typ, element.text))
def lade_dict(dateiname): d = {} baum = ElementTree.parse(dateiname) tag_dict = baum.getroot() for eintrag in tag_dict.getchildren(): tag_schluessel = eintrag.find("schluessel") tag_wert = eintrag.find("wert") d[_lese_text(tag_schluessel)] = _lese_text(tag_wert) return d

Zunächst wird die Funktion _lese_text implementiert, die aus der Element-Instanz eines schluessel- oder wert-Tags das Attribut typ ausliest und den vom jeweiligen Tag umschlossenen Text in den durch typ angegebenen Datentyp konvertiert. Dazu wird die Built-in Function eval wie bei den Beispielen der vorherigen Kapitel verwendet. Der Inhalt des Tags wird dann als Instanz des passenden Datentyps zurückgegeben.

Die Hauptfunktion des Beispielprogramms lade_dict bekommt den Dateinamen einer XML-Datei übergeben und soll die darin enthaltenen Daten zu einem Python-Dictionary aufbereiten. Dazu wird die XML-Datei zunächst mithilfe der Funktion parse des Moduls xml.etree.ElementTree zu einem Baum aufbereitet. Danach wird der Referenz tag_dict das Wurzelelement des Baums zugewiesen, um auf diesem weiter zu operieren.

In der nun folgenden Schleife wird über alle Kindelemente des Wurzelelements, also über alle eintrag-Tags, iteriert. In jedem Iterationsschritt werden die ersten Kindelemente mit den Tag-Namen schluessel und wert gesucht und den Referenzen tag_schluessel und tag_wert zugewiesen. Am Ende des Schleifenkörpers werden die Element-Instanzen der jeweiligen schluessel- oder wert-Tags durch die Funktion _lese_text geschleust und der im Tagkörper enthaltene Text damit in eine Instanz des korrekten Datentyps konvertiert. Die resultierenden Instanzen werden als Schlüssel bzw. als Wert in das Dictionary d eingetragen. Schlussendlich wird das erzeugte Dictionary d zurückgegeben.

So viel zum Datentyp ElementTree. Wir behalten die grobe Richtung Datenspeicherung bei und werden uns im nächsten Abschnitt um das Thema Datenbanken kümmern.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






 <<   zurück
  
  Zum Katalog
Zum Katalog: Python






Python
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Linux






 Linux


Zum Katalog: Ubuntu GNU/Linux






 Ubuntu GNU/Linux


Zum Katalog: Praxisbuch Web 2.0






 Praxisbuch Web 2.0


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Praxisbuch Objektorientierung






 Praxisbuch Objektorientierung


Zum Katalog: Einstieg in SQL






 Einstieg in SQL


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für Fachinformatiker


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo





Copyright © Galileo Press 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de