xml.dom.minidom — Minimal DOM-implementering

Källkod: Lib/xml/dom/minidom.py


xml.dom.minidom är en minimal implementation av Document Object Model-gränssnittet, med ett API som liknar det i andra språk. Den är avsedd att vara enklare än den fullständiga DOM och också betydligt mindre. Användare som inte redan är bekanta med DOM bör överväga att använda modulen xml.etree.ElementTree för sin XML-bearbetning istället.

Anteckning

Om du behöver analysera otillförlitliga eller oautentiserade data, se XML-säkerhet.

DOM-applikationer börjar vanligtvis med att parsa XML till en DOM. Med xml.dom.minidom görs detta genom parse-funktionerna:

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>')

Funktionen parse() kan ta emot antingen ett filnamn eller ett objekt med en öppen fil.

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

Returnerar ett Document från den angivna indata. filename_or_file kan vara antingen ett filnamn eller ett filliknande objekt. parser, om det anges, måste vara ett SAX2-parserobjekt. Denna funktion kommer att ändra dokumenthanteraren i parsern och aktivera namnrymdsstöd; annan parserkonfiguration (som att ställa in en entitetsresolver) måste ha gjorts i förväg.

Om du har XML i en sträng kan du använda funktionen parseString() istället:

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

Returnerar ett Document som representerar strängen. Den här metoden skapar ett io.StringIO-objekt för strängen och skickar det vidare till parse().

Båda funktionerna returnerar ett Document-objekt som representerar innehållet i dokumentet.

Funktionerna parse() och parseString() kopplar samman en XML-parser med en ”DOM-byggare” som kan ta emot parse-händelser från vilken SAX-parser som helst och konvertera dem till ett DOM-träd. Namnet på funktionerna är kanske missvisande, men är lätta att förstå när man lär sig gränssnitten. Parsningen av dokumentet kommer att vara klar innan dessa funktioner returneras; det är helt enkelt så att dessa funktioner inte själva tillhandahåller en parserimplementation.

Du kan också skapa en Document genom att anropa en metod på ett ”DOM Implementation”-objekt. Du kan få detta objekt antingen genom att anropa funktionen getDOMImplementation() i paketet xml.dom eller modulen xml.dom.minidom. När du har en Document, kan du lägga till underordnade noder till den för att fylla DOM:

från xml.dom.minidom import getDOMImplementation

impl = getDOMImplementation()

newdoc = impl.createDocument(None, "some_tag", None)
top_element = newdoc.documentElement
text = newdoc.createTextNode("Något textinnehåll.")
top_element.appendChild(text)

När du har ett DOM-dokumentobjekt kan du komma åt delarna av ditt XML-dokument genom dess egenskaper och metoder. Dessa egenskaper definieras i DOM-specifikationen. Den viktigaste egenskapen hos dokumentobjektet är egenskapen documentElement. Den ger dig huvudelementet i XML-dokumentet: det som innehåller alla andra. Här är ett exempel på ett program:

dom3 = parseString(<myxml>"Några data</myxml>")
assert dom3.documentElement.tagName == "myxml"

När du är klar med ett DOM-träd kan du eventuellt anropa metoden unlink() för att uppmuntra tidig upprensning av de nu obehövliga objekten. unlink() är ett xml.dom.minidom-specifikt tillägg till DOM API som gör noden och dess ättlingar i huvudsak värdelösa. Annars kommer Pythons skräpsamlare så småningom att ta hand om objekten i trädet.

Se även

Dokumentobjektmodell (DOM) Nivå 1-specifikation

W3C:s rekommendation för DOM som stöds av xml.dom.minidom.

DOM-objekt

Definitionen av DOM API för Python ges som en del av moduldokumentationen för xml.dom. I detta avsnitt listas skillnaderna mellan API:et och xml.dom.minidom.

Bryter interna referenser inom DOM så att det kommer att samlas in på versioner av Python utan cyklisk GC. Även när cyklisk GC är tillgänglig kan användningen av detta göra stora mängder minne tillgängligt tidigare, så att anropa detta på DOM-objekt så snart de inte längre behövs är god praxis. Detta behöver bara anropas på Document-objektet, men kan anropas på underordnade noder för att kasta bort barn till den noden.

Du kan undvika att anropa denna metod explicit genom att använda with-satsen. Följande kod kommer automatiskt att avlänka dom när with-blocket avslutas:

med xml.dom.minidom.parse(datasource) som dom:
    ... # Arbeta med dom.
Node.writexml(writer, indent='', addindent='', newl='', encoding=None, standalone=None)

Skriv XML till writer-objektet. Skrivaren tar emot texter men inte bytes som indata, den bör ha en write()-metod som matchar den för filobjektets gränssnitt. Parametern indent är indenteringen för den aktuella noden. Parametern addindent är den inkrementella indragning som ska användas för undernoder till den aktuella noden. Parametern newl anger den sträng som ska användas för att avsluta nya linjer.

För Document-noden kan ett ytterligare nyckelordsargument encoding användas för att ange kodningsfältet i XML-huvudet.

På samma sätt leder en explicit angivelse av argumentet standalone till att deklarationerna för det fristående dokumentet läggs till i XML-dokumentets prolog. Om värdet är satt till True, läggs standalone="yes" till, annars sätts det till "no". Om argumentet inte anges kommer deklarationen att utelämnas från dokumentet.

Ändrad i version 3.8: Metoden writexml() bevarar nu den attributordning som anges av användaren.

Ändrad i version 3.9: Parametern standalone har lagts till.

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

Returnerar en sträng eller byte-sträng som innehåller den XML som representeras av DOM-noden.

Med ett explicit encoding [1]-argument blir resultatet en byte-sträng i den angivna kodningen. Utan argumentet encoding blir resultatet en Unicode-sträng och XML-deklarationen i den resulterande strängen anger inte någon kodning. Att koda denna sträng i en annan kodning än UTF-8 är troligen felaktigt, eftersom UTF-8 är standardkodningen för XML.

Argumentet standalone beter sig exakt som i writexml().

Ändrad i version 3.8: Metoden toxml() bevarar nu den attributordning som anges av användaren.

Ändrad i version 3.9: Parametern standalone har lagts till.

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

Returnerar en vackert utskriven version av dokumentet. indent anger indragningssträngen och standardvärdet är en tabulator; newl anger strängen som visas i slutet av varje rad och standardvärdet är n.

Argumentet encoding beter sig som motsvarande argument i toxml().

Argumentet standalone beter sig exakt som i writexml().

Ändrad i version 3.8: Metoden toprettyxml() bevarar nu den attributordning som anges av användaren.

Ändrad i version 3.9: Parametern standalone har lagts till.

DOM-exempel

Detta exempelprogram är ett ganska realistiskt exempel på ett enkelt program. I det här fallet utnyttjar vi inte DOM:s flexibilitet särskilt mycket.

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 och DOM-standarden

Modulen xml.dom.minidom är i huvudsak en DOM 1.0-kompatibel DOM med vissa DOM 2-egenskaper (främst namnrymdsfunktioner).

Användningen av DOM-gränssnittet i Python är enkel. Följande mappningsregler gäller:

  • Gränssnitt nås via instansobjekt. Program bör inte instansiera klasserna själva, utan använda de skapande funktioner som finns tillgängliga på Document-objektet. Härledda gränssnitt stöder alla operationer (och attribut) från basgränssnitten, plus eventuella nya operationer.

  • Operationer används som metoder. Eftersom DOM endast använder in-parametrar, skickas argumenten i normal ordning (från vänster till höger). Det finns inga valfria argument. void operationer returnerar None.

  • IDL-attribut mappas till instansattribut. För kompatibilitet med OMG IDL-språkmappningen för Python kan ett attribut foo också nås via accessormetoderna _get_foo() och _set_foo(). Readonly-attribut får inte ändras; detta verkställs inte vid körning.

  • Typerna short int, unsigned int, unsigned long long och boolean mappar alla till Python integer-objekt.

  • Typen DOMString mappar till Python-strängar. xml.dom.minidom stöder antingen bytes eller strängar, men kommer normalt att producera strängar. Värden av typen DOMString kan också vara None om det är tillåtet att ha IDL-värdet null enligt DOM-specifikationen från W3C.

  • const-deklarationer mappar till variabler i deras respektive omfattning (t.ex. xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE); de får inte ändras.

  • DOMException stöds för närvarande inte i xml.dom.minidom. Istället använder xml.dom.minidom standard Python-undantag som TypeError och AttributeError.

  • NodeList-objekt implementeras med hjälp av Pythons inbyggda listtyp. Dessa objekt tillhandahåller det gränssnitt som definieras i DOM-specifikationen, men med tidigare versioner av Python stöder de inte det officiella API:et. De är dock mycket mer ”Pythonic” än det gränssnitt som definieras i W3C:s rekommendationer.

Följande gränssnitt har ingen implementation i xml.dom.minidom:

  • DOMTimeStamp

  • EntityReference

De flesta av dessa återspeglar information i XML-dokumentet som inte är till allmän nytta för de flesta DOM-användare.

Fotnoter