mirror of https://github.com/python/cpython.git
615 lines
19 KiB
TeX
615 lines
19 KiB
TeX
\section{\module{xml.dom.minidom} ---
|
|
The Document Object Model}
|
|
|
|
\declaremodule{standard}{xml.dom.minidom}
|
|
\modulesynopsis{Lightweight Document Object Model (DOM) implementation.}
|
|
\moduleauthor{Paul Prescod}{paul@prescod.net}
|
|
\sectionauthor{Paul Prescod}{paul@prescod.net}
|
|
\sectionauthor{Martin v. L\"owis}{loewis@informatik.hu-berlin.de}
|
|
|
|
\versionadded{2.0}
|
|
|
|
The \module{xml.dom.minidom} provides a light-weight implementation of
|
|
the W3C Document Object Model. The DOM is a cross-language API from
|
|
the Web Consortium (W3C) for accessing and modifying XML documents. A
|
|
DOM implementation allows to convert an XML document into a tree-like
|
|
structure, or to build such a structure from scratch. It then gives
|
|
access to the structure through a set of objects which provided
|
|
well-known interfaces. Minidom is intended to be simpler than the full
|
|
DOM and also significantly smaller.
|
|
|
|
The DOM is extremely useful for random-access applications. SAX only
|
|
allows you a view of one bit of the document at a time. If you are
|
|
looking at one SAX element, you have no access to another. If you are
|
|
looking at a text node, you have no access to a containing
|
|
element. When you write a SAX application, you need to keep track of
|
|
your program's position in the document somewhere in your own
|
|
code. Sax does not do it for you. Also, if you need to look ahead in
|
|
the XML document, you are just out of luck.
|
|
|
|
Some applications are simply impossible in an event driven model with
|
|
no access to a tree. Of course you could build some sort of tree
|
|
yourself in SAX events, but the DOM allows you to avoid writing that
|
|
code. The DOM is a standard tree representation for XML data.
|
|
|
|
%What if your needs are somewhere between SAX and the DOM? Perhaps you cannot
|
|
%afford to load the entire tree in memory but you find the SAX model
|
|
%somewhat cumbersome and low-level. There is also an experimental module
|
|
%called pulldom that allows you to build trees of only the parts of a
|
|
%document that you need structured access to. It also has features that allow
|
|
%you to find your way around the DOM.
|
|
% See http://www.prescod.net/python/pulldom
|
|
|
|
DOM applications typically start by parsing some XML into a DOM. This
|
|
is done through the parse functions:
|
|
|
|
\begin{verbatim}
|
|
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>')
|
|
\end{verbatim}
|
|
|
|
The parse function can take either a filename or an open file object.
|
|
|
|
\begin{funcdesc}{parse}{filename_or_file{, parser}}
|
|
Return a \class{Document} from the given input. \var{filename_or_file}
|
|
may be either a file name, or a file-like object. \var{parser}, if
|
|
given, must be a SAX2 parser object. This function will change the
|
|
document handler of the parser and activate namespace support; other
|
|
parser configuration (like setting an entity resolver) must have been
|
|
done in advance.
|
|
\end{funcdesc}
|
|
|
|
If you have XML in a string, you can use the parseString function
|
|
instead:
|
|
|
|
\begin{funcdesc}{parseString}{string\optional{, parser}}
|
|
Return a \class{Document} that represents the \var{string}. This
|
|
method creates a \class{StringIO} object for the string and passes
|
|
that on to \function{parse}.
|
|
\end{funcdesc}
|
|
|
|
Both functions return a document object representing the content of
|
|
the document.
|
|
|
|
You can also create a document node merely by instantiating a
|
|
document object. Then you could add child nodes to it to populate
|
|
the DOM.
|
|
|
|
\begin{verbatim}
|
|
from xml.dom.minidom import Document
|
|
|
|
newdoc = Document()
|
|
newel = newdoc.createElement("some_tag")
|
|
newdoc.appendChild(newel)
|
|
\end{verbatim}
|
|
|
|
Once you have a DOM document object, you can access the parts of your
|
|
XML document through its properties and methods. These properties are
|
|
defined in the DOM specification. The main property of the document
|
|
object is the documentElement property. It gives you the main element
|
|
in the XML document: the one that holds all others. Here is an
|
|
example program:
|
|
|
|
\begin{verbatim}
|
|
dom3 = parseString("<myxml>Some data</myxml>")
|
|
assert dom3.documentElement.tagName == "myxml"
|
|
\end{verbatim}
|
|
|
|
When you are finished with a DOM, you should clean it up. This is
|
|
necessary because some versions of Python do not support garbage
|
|
collection of objects that refer to each other in a cycle. Until this
|
|
restriction is removed from all versions of Python, it is safest to
|
|
write your code as if cycles would not be cleaned up.
|
|
|
|
The way to clean up a DOM is to call its \method{unlink()} method:
|
|
|
|
\begin{verbatim}
|
|
dom1.unlink()
|
|
dom2.unlink()
|
|
dom3.unlink()
|
|
\end{verbatim}
|
|
|
|
\method{unlink()} is a \module{minidom}-specific extension to the DOM
|
|
API. After calling \method{unlink()}, a DOM is basically useless.
|
|
|
|
\begin{seealso}
|
|
\seetitle[http://www.w3.org/TR/REC-DOM-Level-1/]{DOM Specification}
|
|
{This is the canonical specification for the level of the
|
|
DOM supported by \module{xml.dom.minidom}.}
|
|
\seetitle[http://pyxml.sourceforge.net]{PyXML}{Users that require a
|
|
full-featured implementation of DOM should use the PyXML
|
|
package.}
|
|
\end{seealso}
|
|
|
|
|
|
\subsection{DOM objects \label{dom-objects}}
|
|
|
|
The definitive documentation for the DOM is the DOM specification from
|
|
the W3C. This section lists the properties and methods supported by
|
|
\refmodule{xml.dom.minidom}.
|
|
|
|
\begin{classdesc}{Node}{}
|
|
All of the components of an XML document are subclasses of
|
|
\class{Node}.
|
|
|
|
\begin{memberdesc}{nodeType}
|
|
An integer representing the node type. Symbolic constants for the
|
|
types are on the \class{Node} object: \constant{DOCUMENT_NODE},
|
|
\constant{ELEMENT_NODE}, \constant{ATTRIBUTE_NODE},
|
|
\constant{TEXT_NODE}, \constant{CDATA_SECTION_NODE},
|
|
\constant{ENTITY_NODE}, \constant{PROCESSING_INSTRUCTION_NODE},
|
|
\constant{COMMENT_NODE}, \constant{DOCUMENT_NODE},
|
|
\constant{DOCUMENT_TYPE_NODE}, \constant{NOTATION_NODE}.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{parentNode}
|
|
The parent of the current node. \code{None} for the document node.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{attributes}
|
|
An \class{AttributeList} of attribute objects. Only
|
|
elements have this attribute. Others return \code{None}.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{previousSibling}
|
|
The node that immediately precedes this one with the same parent. For
|
|
instance the element with an end-tag that comes just before the
|
|
\var{self} element's start-tag. Of course, XML documents are made
|
|
up of more than just elements so the previous sibling could be text, a
|
|
comment, or something else.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{nextSibling}
|
|
The node that immediately follows this one with the same parent. See
|
|
also \member{previousSibling}.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{childNodes}
|
|
A list of nodes contained within this node.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{firstChild}
|
|
Equivalent to \code{childNodes[0]}.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{lastChild}
|
|
Equivalent to \code{childNodes[-1]}.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{nodeName}
|
|
Has a different meaning for each node type. See the DOM specification
|
|
for details. You can always get the information you would get here
|
|
from another property such as the \member{tagName} property for
|
|
elements or the \member{name} property for attributes.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{nodeValue}
|
|
Has a different meaning for each node type. See the DOM specification
|
|
for details. The situation is similar to that with \member{nodeName}.
|
|
\end{memberdesc}
|
|
|
|
\begin{methoddesc}{unlink}{}
|
|
Break internal references within the DOM so that it will be garbage
|
|
collected on versions of Python without cyclic GC.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{writexml}{writer}
|
|
Write XML to the writer object. The writer should have a
|
|
\method{write()} method which matches that of the file object
|
|
interface.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{toxml}{}
|
|
Return the XML string that the DOM represents.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{hasChildNodes}{}
|
|
Returns true the node has any child nodes.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{insertBefore}{newChild, refChild}
|
|
Insert a new child node before an existing child. It must be the case
|
|
that \var{refChild} is a child of this node; if not,
|
|
\exception{ValueError} is raised.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{replaceChild}{newChild, oldChild}
|
|
Replace an existing node with a new node. It must be the case that
|
|
\var{oldChild} is a child of this node; if not,
|
|
\exception{ValueError} is raised.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{removeChild}{oldChild}
|
|
Remove a child node. \var{oldChild} must be a child of this node; if
|
|
not, \exception{ValueError} is raised.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{appendChild}{newChild}
|
|
Add a new child node to this node list.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{cloneNode}{deep}
|
|
Clone this node. Deep means to clone all children also. Deep cloning
|
|
is not implemented in Python 2 so the deep parameter should always be
|
|
0 for now.
|
|
\end{methoddesc}
|
|
|
|
\end{classdesc}
|
|
|
|
|
|
\begin{classdesc}{Document}{}
|
|
Represents an entire XML document, including its constituent elements,
|
|
attributes, processing instructions, comments etc. Remeber that it
|
|
inherits properties from \class{Node}.
|
|
|
|
\begin{memberdesc}{documentElement}
|
|
The one and only root element of the document.
|
|
\end{memberdesc}
|
|
|
|
\begin{methoddesc}{createElement}{tagName}
|
|
Create a new element. The element is not inserted into the document
|
|
when it is created. You need to explicitly insert it with one of the
|
|
other methods such as \method{insertBefore()} or
|
|
\method{appendChild()}.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{createTextNode}{data}
|
|
Create a text node containing the data passed as a parameter. As with
|
|
the other creation methods, this one does not insert the node into the
|
|
tree.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{createComment}{data}
|
|
Create a comment node containing the data passed as a parameter. As
|
|
with the other creation methods, this one does not insert the node
|
|
into the tree.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{createProcessingInstruction}{target, data}
|
|
Create a processing instruction node containing the \var{target} and
|
|
\var{data} passed as parameters. As with the other creation methods,
|
|
this one does not insert the node into the tree.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{createAttribute}{name}
|
|
Create an attribute node. This method does not associate the
|
|
attribute node with any particular element. You must use
|
|
\method{setAttributeNode()} on the appropriate \class{Element} object
|
|
to use the newly created attribute instance.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{createElementNS}{namespaceURI, tagName}
|
|
Create a new element with a namespace. The \var{tagName} may have a
|
|
prefix. The element is not inserted into the document when it is
|
|
created. You need to explicitly insert it with one of the other
|
|
methods such as \method{insertBefore()} or \method{appendChild()}.
|
|
\end{methoddesc}
|
|
|
|
|
|
\begin{methoddesc}{createAttributeNS}{namespaceURI, qualifiedName}
|
|
Create an attribute node with a namespace. The \var{tagName} may have
|
|
a prefix. This method does not associate the attribute node with any
|
|
particular element. You must use \method{setAttributeNode()} on the
|
|
appropriate \class{Element} object to use the newly created attribute
|
|
instance.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{getElementsByTagName}{tagName}
|
|
Search for all descendants (direct children, children's children,
|
|
etc.) with a particular element type name.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{getElementsByTagNameNS}{namespaceURI, localName}
|
|
Search for all descendants (direct children, children's children,
|
|
etc.) with a particular namespace URI and localname. The localname is
|
|
the part of the namespace after the prefix.
|
|
\end{methoddesc}
|
|
|
|
\end{classdesc}
|
|
|
|
|
|
\begin{classdesc}{Element}{}
|
|
\begin{memberdesc}{tagName}
|
|
The element type name. In a namespace-using document it may have
|
|
colons in it.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{localName}
|
|
The part of the \member{tagName} following the colon if there is one,
|
|
else the entire \member{tagName}.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{prefix}
|
|
The part of the \member{tagName} preceding the colon if there is one,
|
|
else the empty string.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{namespaceURI}
|
|
The namespace associated with the tagName.
|
|
\end{memberdesc}
|
|
|
|
\begin{methoddesc}{getAttribute}{attname}
|
|
Return an attribute value as a string.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{setAttribute}{attname, value}
|
|
Set an attribute value from a string.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{removeAttribute}{attname}
|
|
Remove an attribute by name.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{getAttributeNS}{namespaceURI, localName}
|
|
Return an attribute value as a string, given a \var{namespaceURI} and
|
|
\var{localName}. Note that a localname is the part of a prefixed
|
|
attribute name after the colon (if there is one).
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{setAttributeNS}{namespaceURI, qname, value}
|
|
Set an attribute value from a string, given a \var{namespaceURI} and a
|
|
\var{qname}. Note that a qname is the whole attribute name. This is
|
|
different than above.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{removeAttributeNS}{namespaceURI, localName}
|
|
Remove an attribute by name. Note that it uses a localName, not a
|
|
qname.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{getElementsByTagName}{tagName}
|
|
Same as equivalent method in the \class{Document} class.
|
|
\end{methoddesc}
|
|
|
|
\begin{methoddesc}{getElementsByTagNameNS}{tagName}
|
|
Same as equivalent method in the \class{Document} class.
|
|
\end{methoddesc}
|
|
|
|
\end{classdesc}
|
|
|
|
|
|
\begin{classdesc}{Attribute}{}
|
|
|
|
\begin{memberdesc}{name}
|
|
The attribute name. In a namespace-using document it may have colons
|
|
in it.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{localName}
|
|
The part of the name following the colon if there is one, else the
|
|
entire name.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{prefix}
|
|
The part of the name preceding the colon if there is one, else the
|
|
empty string.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{namespaceURI}
|
|
The namespace associated with the attribute name.
|
|
\end{memberdesc}
|
|
|
|
\end{classdesc}
|
|
|
|
|
|
\begin{classdesc}{AttributeList}{}
|
|
|
|
\begin{memberdesc}{length}
|
|
The length of the attribute list.
|
|
\end{memberdesc}
|
|
|
|
\begin{methoddesc}{item}{index}
|
|
Return an attribute with a particular index. The order you get the
|
|
attributes in is arbitrary but will be consistent for the life of a
|
|
DOM. Each item is an attribute node. Get its value with the
|
|
\member{value} attribbute.
|
|
\end{methoddesc}
|
|
|
|
There are also experimental methods that give this class more
|
|
dictionary-like behavior. You can use them or you can use the
|
|
standardized \method{getAttribute*()}-family methods.
|
|
|
|
\end{classdesc}
|
|
|
|
|
|
\begin{classdesc}{Comment}{}
|
|
Represents a comment in the XML document.
|
|
|
|
\begin{memberdesc}{data}
|
|
The content of the comment.
|
|
\end{memberdesc}
|
|
\end{classdesc}
|
|
|
|
|
|
\begin{classdesc}{Text}{}
|
|
Represents text in the XML document.
|
|
|
|
\begin{memberdesc}{data}
|
|
The content of the text node.
|
|
\end{memberdesc}
|
|
\end{classdesc}
|
|
|
|
|
|
\begin{classdesc}{ProcessingInstruction}{}
|
|
Represents a processing instruction in the XML document.
|
|
|
|
\begin{memberdesc}{target}
|
|
The content of the processing instruction up to the first whitespace
|
|
character.
|
|
\end{memberdesc}
|
|
|
|
\begin{memberdesc}{data}
|
|
The content of the processing instruction following the first
|
|
whitespace character.
|
|
\end{memberdesc}
|
|
\end{classdesc}
|
|
|
|
Note that DOM attributes may also be manipulated as nodes instead of as
|
|
simple strings. It is fairly rare that you must do this, however, so this
|
|
usage is not yet documented here.
|
|
|
|
|
|
\begin{seealso}
|
|
\seetitle[http://www.w3.org/TR/REC-DOM-Level-1/]{DOM Specification}
|
|
{This is the canonical specification for the level of the
|
|
DOM supported by \module{xml.dom.minidom}.}
|
|
\end{seealso}
|
|
|
|
|
|
\subsection{DOM Example \label{dom-example}}
|
|
|
|
This example program is a fairly realistic example of a simple
|
|
program. In this particular case, we do not take much advantage
|
|
of the flexibility of the DOM.
|
|
|
|
\begin{verbatim}
|
|
from xml.dom.minidom import parse, parseString
|
|
|
|
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 = parseString(document)
|
|
|
|
space=" "
|
|
def getText(nodelist):
|
|
rc=""
|
|
for node in nodelist:
|
|
if node.nodeType==node.TEXT_NODE:
|
|
rc=rc+node.data
|
|
return 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 "<title>%s</title>"%getText(title.childNodes)
|
|
|
|
def handleSlideTitle(title):
|
|
print "<h2>%s</h2>"%getText(title.childNodes)
|
|
|
|
def handlePoints(points):
|
|
print "<ul>"
|
|
for point in points:
|
|
handlePoint(point)
|
|
print "</ul>"
|
|
|
|
def handlePoint(point):
|
|
print "<li>%s</li>"%getText(point.childNodes)
|
|
|
|
def handleToc(slides):
|
|
for slide in slides:
|
|
title = slide.getElementsByTagName("title")[0]
|
|
print "<p>%s</p>"%getText(title.childNodes)
|
|
|
|
handleSlideshow(dom)
|
|
\end{verbatim}
|
|
|
|
\subsection{minidom and the DOM standard \label{minidom-and-dom}}
|
|
|
|
Minidom is basically a DOM 1.0-compatible DOM with some DOM 2 features
|
|
(primarily namespace features).
|
|
|
|
Usage of the other DOM interfaces in Python is straight-forward. The
|
|
following mapping rules apply:
|
|
|
|
\begin{itemize}
|
|
|
|
\item Interfaces are accessed through instance objects. Applications
|
|
should
|
|
not instantiate the classes themselves; they should use the creator
|
|
functions. Derived interfaces support all operations (and attributes)
|
|
from the base interfaces, plus any new operations.
|
|
|
|
\item Operations are used as methods. Since the DOM uses only
|
|
\code{in}
|
|
parameters, the arguments are passed in normal order (from left to
|
|
right).
|
|
There are no optional arguments. \code{void} operations return
|
|
\code{None}.
|
|
|
|
\item IDL attributes map to instance attributes. For compatibility
|
|
with
|
|
the OMG IDL language mapping for Python, an attribute \code{foo} can
|
|
also be accessed through accessor functions \code{_get_foo} and
|
|
\code{_set_foo}. \code{readonly} attributes must not be changed.
|
|
|
|
\item The types \code{short int},\code{unsigned int},\code{unsigned
|
|
long long},
|
|
and \code{boolean} all map to Python integer objects.
|
|
|
|
\item The type \code{DOMString} maps to Python strings. \code{minidom}
|
|
supports either byte or Unicode strings, but will normally produce
|
|
Unicode
|
|
strings. Attributes of type \code{DOMString} may also be \code{None}.
|
|
|
|
\item \code{const} declarations map to variables in their respective
|
|
scope
|
|
(e.g. \code{xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE}); they
|
|
must
|
|
not be changed.
|
|
|
|
\item \code{DOMException} is currently not supported in
|
|
\module{minidom}. Instead, minidom returns standard Python exceptions
|
|
such as TypeError and AttributeError.
|
|
|
|
\end{itemize}
|
|
|
|
The following interfaces have no equivalent in minidom:
|
|
|
|
\begin{itemize}
|
|
|
|
\item DOMTimeStamp
|
|
|
|
\item DocumentType
|
|
|
|
\item DOMImplementation
|
|
|
|
\item CharacterData
|
|
|
|
\item CDATASection
|
|
|
|
\item Notation
|
|
|
|
\item Entity
|
|
|
|
\item EntityReference
|
|
|
|
\item DocumentFragment
|
|
|
|
\end{itemize}
|
|
|
|
Most of these reflect information in the XML document that is not of
|
|
general utility to most DOM users.
|