\section{\module{xml.dom} ---
         The Document Object Model API}

\declaremodule{standard}{xml.dom}
\modulesynopsis{Document Object Model API for Python.}
\sectionauthor{Paul Prescod}{paul@prescod.net}
\sectionauthor{Martin v. L\"owis}{loewis@informatik.hu-berlin.de}

\versionadded{2.0}

The Document Object Model, or ``DOM,'' is a cross-language API from
the World Wide Web Consortium (W3C) for accessing and modifying XML
documents.  A DOM implementation presents an XML document as a tree
structure, or allows client code to build such a structure from
scratch.  It then gives access to the structure through a set of
objects which provided well-known interfaces.

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 a module
%called xml.dom.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

The Document Object Model is being defined by the W3C in stages, or
``levels'' in their terminology.  The Python mapping of the API is
substantially based on the DOM Level 2 recommendation.  Some aspects
of the API will only became available in Python 2.1, or may only be
available in particular DOM implementations.

DOM applications typically start by parsing some XML into a DOM.  How
this is accomplished is not covered at all by DOM Level 1, and Level 2
provides only limited improvements.  There is a
\class{DOMImplementation} object class which provides access to
\class{Document} creation methods, but these methods were only added
in DOM Level 2 and were not implemented in time for Python 2.0.  There
is also no well-defined way to access this functions without an
existing \class{Document} object.  For Python 2.0, consult the
documentation for each particular DOM implementation to determine the
bootstrap procedure needed to create and initialize \class{Document}
instances.

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; this portion of the reference manual
describes the interpretation of the specification in Python.

The specification provided by the W3C defines the DOM API for Java,
ECMAScript, and OMG IDL.  The Python mapping defined here is based in
large part on the IDL version of the specification, but strict
compliance is not required (though implementations are free to support
the strict mapping from IDL).  See section \ref{dom-conformance},
``Conformance,'' for a detailed discussion of mapping requirements.


\begin{seealso}
  \seetitle[http://www.w3.org/TR/DOM-Level-2-Core/]{Document Object
            Model (DOM) Level 2 Specification}
           {The W3C recommendation upon which the Python DOM API is
            based.}
  \seetitle[http://www.w3.org/TR/REC-DOM-Level-1/]{Document Object
            Model (DOM) Level 1 Specification}
           {The W3C recommendation for 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.}
  \seetitle[http://cgi.omg.org/cgi-bin/doc?orbos/99-08-02.pdf]{CORBA
            Scripting with Python}
           {This specifies the mapping from OMG IDL to Python.}
\end{seealso}


\subsection{Objects in the DOM \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}.

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.


\begin{tableiii}{l|l|l}{class}{Interface}{Section}{Purpose}
  \lineiii{Node}{\ref{dom-node-objects}}
          {Base interface for most objects in a document.}
  \lineiii{Document}{\ref{dom-document-objects}}
          {Object which represents an entire document.}
  \lineiii{Element}{\ref{dom-element-objects}}
          {Element nodes in the document hierarchy.}
  \lineiii{Attr}{\ref{dom-attr-objects}}
          {Attribute value nodes on element nodes.}
  \lineiii{Comment}{\ref{dom-comment-objects}}
          {Representation of comments in the source document.}
  \lineiii{Text}{\ref{dom-text-objects}}
          {Nodes containing textual content from the document.}
  \lineiii{ProcessingInstruction}{\ref{dom-pi-objects}}
          {Processing instruction representation.}
\end{tableiii}


\subsubsection{Node Objects \label{dom-node-objects}}

All of the components of an XML document are subclasses of
\class{Node}.

\begin{memberdesc}[Node]{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}[Node]{parentNode}
The parent of the current node.  \code{None} for the document node.
\end{memberdesc}

\begin{memberdesc}[Node]{attributes}
An \class{AttributeList} of attribute objects.  Only elements have
actual values for this; others provide \code{None} for this attribute.
\end{memberdesc}

\begin{memberdesc}[Node]{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}[Node]{nextSibling}
The node that immediately follows this one with the same parent.  See
also \member{previousSibling}.
\end{memberdesc}

\begin{memberdesc}[Node]{childNodes}
A list of nodes contained within this node.
\end{memberdesc}

\begin{memberdesc}[Node]{firstChild}
The first child of the node, if there are any, or \code{None}.
\end{memberdesc}

\begin{memberdesc}[Node]{lastChild}
The last child of the node, if there are any, or \code{None}.
\end{memberdesc}

\begin{memberdesc}[Node]{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}[Node]{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}[Node]{hasChildNodes}{}
Returns true if the node has any child nodes.
\end{methoddesc}

\begin{methoddesc}[Node]{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}[Node]{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}[Node]{removeChild}{oldChild}
Remove a child node.  \var{oldChild} must be a child of this node; if
not, \exception{ValueError} is raised.  \var{oldChild} is returned on
success.  If \var{oldChild} will not be used further, its
\method{unlink()} method should be called.
\end{methoddesc}

\begin{methoddesc}[Node]{appendChild}{newChild}
Add a new child node to this node at the end of the list of children,
returning \var{newChild}.
\end{methoddesc}

\begin{methoddesc}[Node]{normalize}{}
Join adjacent text nodes so that all stretches of text are stored as
single \class{Text} instances.  This simplifies processing text from a
DOM tree for many applications.
\versionadded{2.1}
\end{methoddesc}

\begin{methoddesc}[Node]{cloneNode}{deep}
Clone this node.  Setting \var{deep} means to clone all child nodes as
well.

\strong{Warning:}  Although this method was present in the version of
\refmodule{xml.dom.minidom} packaged with Python 2.0, it was seriously
broken.  This has been corrected for subsequent releases.
\end{methoddesc}


\subsubsection{Document Objects \label{dom-document-objects}}

A \class{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}[Document]{documentElement}
The one and only root element of the document.
\end{memberdesc}

\begin{methoddesc}[Document]{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}[Document]{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}[Document]{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}[Document]{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}[Document]{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}[Document]{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}[Document]{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}[Document]{getElementsByTagName}{tagName}
Search for all descendants (direct children, children's children,
etc.) with a particular element type name.
\end{methoddesc}

\begin{methoddesc}[Document]{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}


\subsubsection{Element Objects \label{dom-element-objects}}

\class{Element} is a subclass of \class{Node}, so inherits all the
attributes of that class.

\begin{memberdesc}[Element]{tagName}
The element type name.  In a namespace-using document it may have
colons in it.
\end{memberdesc}

\begin{memberdesc}[Element]{localName}
The part of the \member{tagName} following the colon if there is one,
else the entire \member{tagName}.
\end{memberdesc}

\begin{memberdesc}[Element]{prefix}
The part of the \member{tagName} preceding the colon if there is one,
else the empty string.
\end{memberdesc}

\begin{memberdesc}[Element]{namespaceURI}
The namespace associated with the tagName.
\end{memberdesc}

\begin{methoddesc}[Element]{getAttribute}{attname}
Return an attribute value as a string.
\end{methoddesc}

\begin{methoddesc}[Element]{setAttribute}{attname, value}
Set an attribute value from a string.
\end{methoddesc}

\begin{methoddesc}[Element]{removeAttribute}{attname}
Remove an attribute by name.
\end{methoddesc}

\begin{methoddesc}[Element]{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}[Element]{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}[Element]{removeAttributeNS}{namespaceURI, localName}
Remove an attribute by name.  Note that it uses a localName, not a
qname.
\end{methoddesc}

\begin{methoddesc}[Element]{getElementsByTagName}{tagName}
Same as equivalent method in the \class{Document} class.
\end{methoddesc}

\begin{methoddesc}[Element]{getElementsByTagNameNS}{tagName}
Same as equivalent method in the \class{Document} class.
\end{methoddesc}


\subsubsection{Attr Objects \label{dom-attr-objects}}

\class{Attr} inherits from \class{Node}, so inherits all its
attributes.

\begin{memberdesc}[Attr]{name}
The attribute name.  In a namespace-using document it may have colons
in it.
\end{memberdesc}

\begin{memberdesc}[Attr]{localName}
The part of the name following the colon if there is one, else the
entire name.
\end{memberdesc}

\begin{memberdesc}[Attr]{prefix}
The part of the name preceding the colon if there is one, else the
empty string.
\end{memberdesc}

\begin{memberdesc}[Attr]{namespaceURI}
The namespace associated with the attribute name.
\end{memberdesc}


\subsubsection{NamedNodeMap Objects \label{dom-attributelist-objects}}

\class{NamedNodeMap} does \emph{not} inherit from \class{Node}.

\begin{memberdesc}[NamedNodeMap]{length}
The length of the attribute list.
\end{memberdesc}

\begin{methoddesc}[NamedNodeMap]{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 mapping
behavior.  You can use them or you can use the standardized
\method{getAttribute*()}-family methods on the \class{Element} objects.


\subsubsection{Comment Objects \label{dom-comment-objects}}

\class{Comment} represents a comment in the XML document.  It is a
subclass of \class{Node}.

\begin{memberdesc}[Comment]{data}
The content of the comment.
\end{memberdesc}


\subsubsection{Text Objects \label{dom-text-objects}}

The \class{Text} interface represents text in the XML document.  It
inherits from \class{Node}.

\begin{memberdesc}[Text]{data}
The content of the text node.
\end{memberdesc}


\subsubsection{ProcessingInstruction Objects \label{dom-pi-objects}}

Represents a processing instruction in the XML document; this inherits
from the \class{Node} interface.

\begin{memberdesc}[ProcessingInstruction]{target}
The content of the processing instruction up to the first whitespace
character.
\end{memberdesc}

\begin{memberdesc}[ProcessingInstruction]{data}
The content of the processing instruction following the first
whitespace character.
\end{memberdesc}


\subsection{Conformance \label{dom-conformance}}

This section describes the conformance requirements and relationships
between the Python DOM API, the W3C DOM recommendations, and the OMG
IDL mapping for Python.

\subsubsection{Type Mapping \label{dom-type-mapping}}

XXX  Explain what a \class{DOMString} maps to...

\subsubsection{Accessor Methods \label{dom-accessor-methods}}

The mapping from OMG IDL to Python defines accessor functions for IDL
\keyword{attribute} declarations in much the way the Java mapping
does.  Mapping the IDL declarations

\begin{verbatim}
readonly attribute string someValue;
         attribute string anotherValue;
\end{verbatim}

yeilds three accessor functions:  a ``get'' method for
\member{someValue} (\method{_get_someValue()}), and ``get'' and
``set'' methods for
\member{anotherValue} (\method{_get_anotherValue()} and
\method{_set_anotherValue()}).  The mapping, in particular, does not
require that the IDL attributes are accessible as normal Python
attributes:  \code{\var{object}.someValue} is \emph{not} required to
work, and may raise an \exception{AttributeError}.

The Python DOM API, however, \emph{does} require that normal attribute
access work.  This means that the typical surrogates generated by
Python IDL compilers are not likely to work, and wrapper objects may
be needed on the client if the DOM objects are accessed via CORBA.
While this does require some additional consideration for CORBA DOM
clients, the implementers with experience using DOM over CORBA from
Python do not consider this a problem.  Attributes that are declared
\keyword{readonly} may not restrict write access in all DOM
implementations.

Additionally, the accessor functions are not required.  If provided,
they should take the form defined by the Python IDL mapping, but
these methods are considered unnecessary since the attributes are
accessible directly from Python.
