xml.dom.minidom — Minimale DOM-Implementierung

Quellcode: Lib/xml/dom/minidom.py


xml.dom.minidom ist eine minimale Implementierung der Document Object Model Schnittstelle mit einer API, die der in anderen Sprachen ähnelt. Sie ist dafür gedacht, einfacher als die vollständige DOM und auch deutlich kleiner zu sein. Benutzer, die mit DOM nicht bereits vertraut sind, sollten stattdessen in Erwägung ziehen, das Modul xml.etree.ElementTree für ihre XML-Verarbeitung zu verwenden.

Hinweis

Wenn Sie nicht vertrauenswürdige oder nicht authentifizierte Daten parsen müssen, siehe XML-Sicherheit.

DOM-Anwendungen beginnen typischerweise damit, XML in ein DOM zu parsen. Mit xml.dom.minidom geschieht dies über die parse-Funktionen

from xml.dom.minidom import parse, parseString

dom1 = parse('c:\\temp\\mydata.xml')  # parse an XML file by name

datasource = open('c:\\temp\\mydata.xml')
dom2 = parse(datasource)  # parse an open file

dom3 = parseString('<myxml>Some data<empty/> some more data</myxml>')

Die Funktion parse() kann entweder einen Dateinamen oder ein geöffnetes Datei-Objekt entgegennehmen.

xml.dom.minidom.parse(filename_or_file, parser=None, bufsize=None)

Gibt ein Document aus den gegebenen Eingaben zurück. filename_or_file kann entweder ein Dateiname oder ein dateiähnliches Objekt sein. parser muss, falls angegeben, ein SAX2-Parser-Objekt sein. Diese Funktion ändert den Dokumenten-Handler des Parsers und aktiviert die Namensraum-Unterstützung; andere Parser-Konfigurationen (wie das Setzen eines Entitäts-Resolvers) müssen im Voraus erfolgt sein.

Wenn Sie XML in einem String haben, können Sie stattdessen die Funktion parseString() verwenden

xml.dom.minidom.parseString(string, parser=None)

Gibt ein Document zurück, das den string repräsentiert. Diese Methode erstellt ein io.StringIO-Objekt für den String und übergibt dieses an parse().

Beide Funktionen geben ein Document-Objekt zurück, das den Inhalt des Dokuments repräsentiert.

Was die Funktionen parse() und parseString() tun, ist, einen XML-Parser mit einem „DOM Builder“ zu verbinden, der Parse-Events von jedem SAX-Parser entgegennehmen und sie in einen DOM-Baum umwandeln kann. Der Name der Funktionen ist vielleicht irreführend, aber leicht verständlich, wenn man die Schnittstellen lernt. Das Parsen des Dokuments ist abgeschlossen, bevor diese Funktionen zurückkehren; es ist lediglich so, dass diese Funktionen selbst keine Parser-Implementierung bereitstellen.

Sie können ein Document auch erstellen, indem Sie eine Methode eines „DOM Implementation“-Objekts aufrufen. Sie können dieses Objekt entweder durch Aufruf der Funktion getDOMImplementation() im Paket xml.dom oder im Modul xml.dom.minidom erhalten. Sobald Sie ein Document haben, können Sie ihm Kindknoten hinzufügen, um das DOM zu füllen.

from xml.dom.minidom import getDOMImplementation

impl = getDOMImplementation()

newdoc = impl.createDocument(None, "some_tag", None)
top_element = newdoc.documentElement
text = newdoc.createTextNode('Some textual content.')
top_element.appendChild(text)

Sobald Sie ein DOM-Dokumentobjekt haben, können Sie über seine Eigenschaften und Methoden auf die Teile Ihres XML-Dokuments zugreifen. Diese Eigenschaften sind in der DOM-Spezifikation definiert. Die wichtigste Eigenschaft des Dokumentobjekts ist die Eigenschaft documentElement. Sie gibt Ihnen das Hauptelement im XML-Dokument: dasjenige, das alle anderen enthält. Hier ist ein Beispielprogramm

dom3 = parseString("<myxml>Some data</myxml>")
assert dom3.documentElement.tagName == "myxml"

Wenn Sie mit einem DOM-Baum fertig sind, können Sie optional die Methode unlink() aufrufen, um eine frühzeitige Bereinigung der nun unnötigen Objekte zu fördern. unlink() ist eine xml.dom.minidom-spezifische Erweiterung der DOM-API, die den Knoten und seine Nachkommen im Wesentlichen nutzlos macht. Andernfalls kümmert sich Pythons Garbage Collector irgendwann um die Objekte im Baum.

Siehe auch

Document Object Model (DOM) Level 1 Specification

Die W3C-Empfehlung für das DOM, das von xml.dom.minidom unterstützt wird.

DOM-Objekte

Die Definition der DOM-API für Python ist Teil der Dokumentation des Moduls xml.dom. Dieser Abschnitt listet die Unterschiede zwischen der API und xml.dom.minidom auf.

Unterbricht interne Referenzen innerhalb des DOM, damit es von Versionen von Python ohne zyklisches GC gesammelt werden kann. Selbst wenn zyklisches GC verfügbar ist, kann die Verwendung davon große Mengen an Speicher früher verfügbar machen, daher ist es eine gute Praxis, dies bei DOM-Objekten aufzurufen, sobald sie nicht mehr benötigt werden. Dies muss nur auf dem Document-Objekt aufgerufen werden, kann aber auf Kindknoten aufgerufen werden, um die Kinder dieses Knotens zu verwerfen.

Sie können den expliziten Aufruf dieser Methode vermeiden, indem Sie die with-Anweisung verwenden. Der folgende Code wird dom automatisch entlinken, wenn der with-Block verlassen wird

with xml.dom.minidom.parse(datasource) as dom:
    ... # Work with dom.
Node.writexml(writer, indent='', addindent='', newl='', encoding=None, standalone=None)

Schreibt XML in das Writer-Objekt. Der Writer empfängt Texte, aber keine Bytes als Eingabe, er sollte eine write()-Methode haben, die der Datei-Objekt-Schnittstelle entspricht. Der Parameter indent ist die Einrückung des aktuellen Knotens. Der Parameter addindent ist die inkrementelle Einrückung, die für Unterknoten des aktuellen verwendet werden soll. Der Parameter newl gibt die Zeichenkette an, die zum Beenden von Zeilenumbrüchen verwendet werden soll.

Für den Document-Knoten kann ein zusätzliches Schlüsselwortargument encoding verwendet werden, um das Feld encoding im XML-Header anzugeben.

Ebenso bewirkt die explizite Angabe des Arguments standalone, dass die Deklarationen für eigenständige Dokumente zum Prolog des XML-Dokuments hinzugefügt werden. Wenn der Wert auf True gesetzt ist, wird standalone="yes" hinzugefügt, andernfalls wird er auf "no" gesetzt. Das Nicht-Angeben des Arguments lässt die Deklaration aus dem Dokument weg.

Geändert in Version 3.8: Die Methode writexml() behält nun die vom Benutzer angegebene Reihenfolge der Attribute bei.

Geändert in Version 3.9: Der Parameter standalone wurde hinzugefügt.

Node.toxml(encoding=None, standalone=None)

Gibt einen String oder Byte-String zurück, der das vom DOM-Knoten dargestellte XML enthält.

Mit einem expliziten Argument encoding [1] ist das Ergebnis ein Byte-String in der angegebenen Kodierung. Ohne das Argument encoding ist das Ergebnis ein Unicode-String, und die XML-Deklaration im resultierenden String gibt keine Kodierung an. Das Kodieren dieses Strings in einer anderen Kodierung als UTF-8 ist wahrscheinlich falsch, da UTF-8 die Standardkodierung von XML ist.

Das Argument standalone verhält sich exakt wie im Argument von writexml().

Geändert in Version 3.8: Die Methode toxml() behält nun die vom Benutzer angegebene Reihenfolge der Attribute bei.

Geändert in Version 3.9: Der Parameter standalone wurde hinzugefügt.

Node.toprettyxml(indent='\t', newl='\n', encoding=None, standalone=None)

Gibt eine schön formatierte Version des Dokuments zurück. indent gibt die Einrückungszeichenkette an und ist standardmäßig ein Tabulator; newl gibt die Zeichenkette an, die am Ende jeder Zeile ausgegeben wird, und ist standardmäßig \n.

Das Argument encoding verhält sich wie das entsprechende Argument von toxml().

Das Argument standalone verhält sich exakt wie im Argument von writexml().

Geändert in Version 3.8: Die Methode toprettyxml() behält nun die vom Benutzer angegebene Reihenfolge der Attribute bei.

Geändert in Version 3.9: Der Parameter standalone wurde hinzugefügt.

DOM-Beispiel

Dieses Beispielprogramm ist ein recht realistisches Beispiel für ein einfaches Programm. In diesem speziellen Fall nutzen wir die Flexibilität des DOM nicht sehr stark aus.

import xml.dom.minidom

document = """\
<slideshow>
<title>Demo slideshow</title>
<slide><title>Slide title</title>
<point>This is a demo</point>
<point>Of a program for processing slides</point>
</slide>

<slide><title>Another demo slide</title>
<point>It is important</point>
<point>To have more than</point>
<point>one slide</point>
</slide>
</slideshow>
"""

dom = xml.dom.minidom.parseString(document)

def getText(nodelist):
    rc = []
    for node in nodelist:
        if node.nodeType == node.TEXT_NODE:
            rc.append(node.data)
    return ''.join(rc)

def handleSlideshow(slideshow):
    print("<html>")
    handleSlideshowTitle(slideshow.getElementsByTagName("title")[0])
    slides = slideshow.getElementsByTagName("slide")
    handleToc(slides)
    handleSlides(slides)
    print("</html>")

def handleSlides(slides):
    for slide in slides:
        handleSlide(slide)

def handleSlide(slide):
    handleSlideTitle(slide.getElementsByTagName("title")[0])
    handlePoints(slide.getElementsByTagName("point"))

def handleSlideshowTitle(title):
    print(f"<title>{getText(title.childNodes)}</title>")

def handleSlideTitle(title):
    print(f"<h2>{getText(title.childNodes)}</h2>")

def handlePoints(points):
    print("<ul>")
    for point in points:
        handlePoint(point)
    print("</ul>")

def handlePoint(point):
    print(f"<li>{getText(point.childNodes)}</li>")

def handleToc(slides):
    for slide in slides:
        title = slide.getElementsByTagName("title")[0]
        print(f"<p>{getText(title.childNodes)}</p>")

handleSlideshow(dom)

minidom und der DOM-Standard

Das Modul xml.dom.minidom ist im Wesentlichen ein DOM 1.0-kompatibles DOM mit einigen DOM 2-Features (hauptsächlich Namensraum-Features).

Die Verwendung der DOM-Schnittstelle in Python ist unkompliziert. Die folgenden Zuordnungsregeln gelten

  • Schnittstellen werden über Instanzobjekte aufgerufen. Anwendungen sollten die Klassen nicht selbst instanziieren; sie sollten die auf dem Document-Objekt verfügbaren Erzeugerfunktionen verwenden. Abgeleitete Schnittstellen unterstützen alle Operationen (und Attribute) von den Basisschnittstellen sowie alle neuen Operationen.

  • Operationen werden als Methoden verwendet. Da das DOM nur in-Parameter verwendet, werden die Argumente in normaler Reihenfolge (von links nach rechts) übergeben. Es gibt keine optionalen Argumente. void-Operationen geben None zurück.

  • IDL-Attribute werden Instanzattributen zugeordnet. Für die Kompatibilität mit der OMG IDL-Sprachzuordnung für Python kann ein Attribut foo auch über Zugriffsmethoden _get_foo() und _set_foo() aufgerufen werden. readonly-Attribute dürfen nicht geändert werden; dies wird zur Laufzeit nicht erzwungen.

  • Die Typen short int, unsigned int, unsigned long long und boolean werden alle zu Python-Integer-Objekten zugeordnet.

  • Der Typ DOMString wird zu Python-Strings zugeordnet. xml.dom.minidom unterstützt entweder Bytes oder Strings, wird aber normalerweise Strings produzieren. Werte vom Typ DOMString können auch None sein, wo sie gemäß der DOM-Spezifikation des W3C den IDL-Wert null haben dürfen.

  • const-Deklarationen werden Variablen in ihrem jeweiligen Geltungsbereich zugeordnet (z. B. xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE); sie dürfen nicht geändert werden.

  • DOMException wird derzeit in xml.dom.minidom nicht unterstützt. Stattdessen verwendet xml.dom.minidom Standard-Python-Ausnahmen wie TypeError und AttributeError.

  • NodeList-Objekte werden mit Pythons integriertem Listen-Typ implementiert. Diese Objekte bieten die in der DOM-Spezifikation definierte Schnittstelle, unterstützen aber mit früheren Python-Versionen nicht die offizielle API. Sie sind jedoch viel „pythonischer“ als die in den W3C-Empfehlungen definierte Schnittstelle.

Die folgenden Schnittstellen haben keine Implementierung in xml.dom.minidom

  • DOMTimeStamp

  • EntityReference

Die meisten davon spiegeln Informationen im XML-Dokument wider, die für die meisten DOM-Benutzer nicht von allgemeinem Nutzen sind.

Fußnoten