10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"""Simple implementation of the Level 1 DOM.
20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiNamespaces and other minor Level 2 features are also supported.
40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiparse("foo.xml")
60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiparseString("<foo><bar/></foo>")
80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTodo:
100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi=====
110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi * convenience methods for getting elements and text.
120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi * more testing
130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi * bring some of the writer and linearizer code into conformance with this
140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        interface
150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi * SAX 2 namespaces
160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"""
170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport xml.dom
190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom xml.dom.minicompat import *
220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS
230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# This is used by the ID-cache invalidation checks; the list isn't
250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# actually complete, since the nodes being checked will never be the
260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE.  (The node being checked is
270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# the node being added or removed, not the node being modified.)
280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#
290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE,
300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            xml.dom.Node.ENTITY_REFERENCE_NODE)
310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Node(xml.dom.Node):
340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    namespaceURI = None # this is non-null only for elements and attributes
350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    parentNode = None
360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    ownerDocument = None
370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nextSibling = None
380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    previousSibling = None
390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __nonzero__(self):
430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return True
440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def toxml(self, encoding = None):
460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.toprettyxml("", "", encoding)
470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def toprettyxml(self, indent="\t", newl="\n", encoding = None):
490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # indent = the indentation string to prepend, per level
500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # newl = the newline string to append
510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        writer = _get_StringIO()
520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if encoding is not None:
530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            import codecs
540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Can't use codecs.getwriter to preserve 2.0 compatibility
550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer = codecs.lookup(encoding)[3](writer)
560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.nodeType == Node.DOCUMENT_NODE:
570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Can pass encoding only to document, to put it into XML header
580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.writexml(writer, "", indent, newl, encoding)
590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.writexml(writer, "", indent, newl)
610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return writer.getvalue()
620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def hasChildNodes(self):
640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.childNodes:
650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return True
660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return False
680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_childNodes(self):
700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.childNodes
710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_firstChild(self):
730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.childNodes:
740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self.childNodes[0]
750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_lastChild(self):
770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.childNodes:
780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self.childNodes[-1]
790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def insertBefore(self, newChild, refChild):
810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for c in tuple(newChild.childNodes):
830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.insertBefore(c, refChild)
840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            ### The DOM does not clearly specify what to return in this case
850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return newChild
860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if newChild.nodeType not in self._child_node_types:
870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.HierarchyRequestErr(
880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "%s cannot be child of %s" % (repr(newChild), repr(self)))
890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if newChild.parentNode is not None:
900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newChild.parentNode.removeChild(newChild)
910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if refChild is None:
920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.appendChild(newChild)
930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                index = self.childNodes.index(refChild)
960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except ValueError:
970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                raise xml.dom.NotFoundErr()
980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if newChild.nodeType in _nodeTypes_with_children:
990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                _clear_id_cache(self)
1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.childNodes.insert(index, newChild)
1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newChild.nextSibling = refChild
1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            refChild.previousSibling = newChild
1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if index:
1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                node = self.childNodes[index-1]
1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                node.nextSibling = newChild
1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                newChild.previousSibling = node
1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                newChild.previousSibling = None
1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newChild.parentNode = self
1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return newChild
1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def appendChild(self, node):
1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for c in tuple(node.childNodes):
1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.appendChild(c)
1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            ### The DOM does not clearly specify what to return in this case
1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return node
1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.nodeType not in self._child_node_types:
1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.HierarchyRequestErr(
1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "%s cannot be child of %s" % (repr(node), repr(self)))
1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elif node.nodeType in _nodeTypes_with_children:
1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _clear_id_cache(self)
1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.parentNode is not None:
1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            node.parentNode.removeChild(node)
1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _append_child(self, node)
1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node.nextSibling = None
1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return node
1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def replaceChild(self, newChild, oldChild):
1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            refChild = oldChild.nextSibling
1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.removeChild(oldChild)
1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self.insertBefore(newChild, refChild)
1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if newChild.nodeType not in self._child_node_types:
1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.HierarchyRequestErr(
1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "%s cannot be child of %s" % (repr(newChild), repr(self)))
1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if newChild is oldChild:
1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return
1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if newChild.parentNode is not None:
1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newChild.parentNode.removeChild(newChild)
1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            index = self.childNodes.index(oldChild)
1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except ValueError:
1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.childNodes[index] = newChild
1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        newChild.parentNode = self
1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        oldChild.parentNode = None
1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if (newChild.nodeType in _nodeTypes_with_children
1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            or oldChild.nodeType in _nodeTypes_with_children):
1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _clear_id_cache(self)
1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        newChild.nextSibling = oldChild.nextSibling
1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        newChild.previousSibling = oldChild.previousSibling
1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        oldChild.nextSibling = None
1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        oldChild.previousSibling = None
1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if newChild.previousSibling:
1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newChild.previousSibling.nextSibling = newChild
1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if newChild.nextSibling:
1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newChild.nextSibling.previousSibling = newChild
1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return oldChild
1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeChild(self, oldChild):
1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.childNodes.remove(oldChild)
1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except ValueError:
1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if oldChild.nextSibling is not None:
1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            oldChild.nextSibling.previousSibling = oldChild.previousSibling
1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if oldChild.previousSibling is not None:
1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            oldChild.previousSibling.nextSibling = oldChild.nextSibling
1700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        oldChild.nextSibling = oldChild.previousSibling = None
1710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if oldChild.nodeType in _nodeTypes_with_children:
1720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _clear_id_cache(self)
1730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        oldChild.parentNode = None
1750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return oldChild
1760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def normalize(self):
1780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        L = []
1790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for child in self.childNodes:
1800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if child.nodeType == Node.TEXT_NODE:
1810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if not child.data:
1820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # empty text node; discard
1830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if L:
1840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        L[-1].nextSibling = child.nextSibling
1850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if child.nextSibling:
1860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        child.nextSibling.previousSibling = child.previousSibling
1870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    child.unlink()
1880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                elif L and L[-1].nodeType == child.nodeType:
1890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # collapse text node
1900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    node = L[-1]
1910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    node.data = node.data + child.data
1920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    node.nextSibling = child.nextSibling
1930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if child.nextSibling:
1940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        child.nextSibling.previousSibling = node
1950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    child.unlink()
1960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                else:
1970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    L.append(child)
1980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
1990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                L.append(child)
2000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if child.nodeType == Node.ELEMENT_NODE:
2010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    child.normalize()
2020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.childNodes[:] = L
2030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def cloneNode(self, deep):
2050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _clone_node(self, deep, self.ownerDocument or self)
2060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def isSupported(self, feature, version):
2080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.ownerDocument.implementation.hasFeature(feature, version)
2090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_localName(self):
2110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Overridden in Element and Attr where localName can be Non-Null
2120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return None
2130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Node interfaces from Level 3 (WD 9 April 2002)
2150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def isSameNode(self, other):
2170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self is other
2180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getInterface(self, feature):
2200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.isSupported(feature, None):
2210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self
2220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
2230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
2240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # The "user data" functions use a dictionary that is only present
2260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # if some user data has been set, so be careful not to assume it
2270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # exists.
2280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getUserData(self, key):
2300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
2310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self._user_data[key][0]
2320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except (AttributeError, KeyError):
2330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
2340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setUserData(self, key, data, handler):
2360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        old = None
2370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
2380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self._user_data
2390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except AttributeError:
2400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = {}
2410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self._user_data = d
2420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if key in d:
2430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            old = d[key][0]
2440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if data is None:
2450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # ignore handlers passed for None
2460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            handler = None
2470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if old is not None:
2480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                del d[key]
2490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
2500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d[key] = (data, handler)
2510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return old
2520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _call_user_data_handler(self, operation, src, dst):
2540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if hasattr(self, "_user_data"):
2550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for key, (data, handler) in self._user_data.items():
2560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if handler is not None:
2570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    handler.handle(operation, key, data, src, dst)
2580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # minidom-specific API:
2600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def unlink(self):
2620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.parentNode = self.ownerDocument = None
2630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.childNodes:
2640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for child in self.childNodes:
2650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                child.unlink()
2660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.childNodes = NodeList()
2670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.previousSibling = None
2680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.nextSibling = None
2690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Node, "firstChild", doc="First child node, or None.")
2710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Node, "lastChild",  doc="Last child node, or None.")
2720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Node, "localName",  doc="Namespace-local name of this node.")
2730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _append_child(self, node):
2760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # fast path with less checks; usable by DOM builders if careful
2770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    childNodes = self.childNodes
2780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if childNodes:
2790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        last = childNodes[-1]
2800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node.__dict__["previousSibling"] = last
2810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        last.__dict__["nextSibling"] = node
2820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    childNodes.append(node)
2830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    node.__dict__["parentNode"] = self
2840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _in_document(node):
2860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # return True iff node is part of a document tree
2870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    while node is not None:
2880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.nodeType == Node.DOCUMENT_NODE:
2890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return True
2900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node = node.parentNode
2910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return False
2920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _write_data(writer, data):
2940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    "Writes datachars to writer."
2950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if data:
2960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        data = data.replace("&", "&amp;").replace("<", "&lt;"). \
2970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    replace("\"", "&quot;").replace(">", "&gt;")
2980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        writer.write(data)
2990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _get_elements_by_tagName_helper(parent, name, rc):
3010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    for node in parent.childNodes:
3020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.nodeType == Node.ELEMENT_NODE and \
3030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            (name == "*" or node.tagName == name):
3040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            rc.append(node)
3050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _get_elements_by_tagName_helper(node, name, rc)
3060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return rc
3070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
3090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    for node in parent.childNodes:
3100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.nodeType == Node.ELEMENT_NODE:
3110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if ((localName == "*" or node.localName == localName) and
3120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                (nsURI == "*" or node.namespaceURI == nsURI)):
3130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                rc.append(node)
3140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
3150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return rc
3160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass DocumentFragment(Node):
3180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.DOCUMENT_FRAGMENT_NODE
3190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeName = "#document-fragment"
3200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeValue = None
3210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    attributes = None
3220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    parentNode = None
3230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _child_node_types = (Node.ELEMENT_NODE,
3240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.TEXT_NODE,
3250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.CDATA_SECTION_NODE,
3260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.ENTITY_REFERENCE_NODE,
3270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.PROCESSING_INSTRUCTION_NODE,
3280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.COMMENT_NODE,
3290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.NOTATION_NODE)
3300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self):
3320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.childNodes = NodeList()
3330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Attr(Node):
3360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.ATTRIBUTE_NODE
3370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    attributes = None
3380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    ownerElement = None
3390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    specified = False
3400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _is_id = False
3410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
3430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
3450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 prefix=None):
3460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # skip setattr for performance
3470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.__dict__
3480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d["nodeName"] = d["name"] = qName
3490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d["namespaceURI"] = namespaceURI
3500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d["prefix"] = prefix
3510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['childNodes'] = NodeList()
3520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Add the single child node that represents the value of the attr
3540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.childNodes.append(Text())
3550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # nodeValue and value are set elsewhere
3570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_localName(self):
3590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.nodeName.split(":", 1)[-1]
3600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_name(self):
3620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.name
3630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_specified(self):
3650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.specified
3660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __setattr__(self, name, value):
3680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.__dict__
3690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if name in ("value", "nodeValue"):
3700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d["value"] = d["nodeValue"] = value
3710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d2 = self.childNodes[0].__dict__
3720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d2["data"] = d2["nodeValue"] = value
3730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if self.ownerElement is not None:
3740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                _clear_id_cache(self.ownerElement)
3750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elif name in ("name", "nodeName"):
3760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d["name"] = d["nodeName"] = value
3770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if self.ownerElement is not None:
3780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                _clear_id_cache(self.ownerElement)
3790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
3800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d[name] = value
3810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _set_prefix(self, prefix):
3830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nsuri = self.namespaceURI
3840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if prefix == "xmlns":
3850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if nsuri and nsuri != XMLNS_NAMESPACE:
3860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                raise xml.dom.NamespaceErr(
3870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    "illegal use of 'xmlns' prefix for the wrong namespace")
3880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.__dict__
3890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['prefix'] = prefix
3900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if prefix is None:
3910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newName = self.localName
3920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
3930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newName = "%s:%s" % (prefix, self.localName)
3940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.ownerElement:
3950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _clear_id_cache(self.ownerElement)
3960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['nodeName'] = d['name'] = newName
3970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _set_value(self, value):
3990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.__dict__
4000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['value'] = d['nodeValue'] = value
4010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.ownerElement:
4020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _clear_id_cache(self.ownerElement)
4030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.childNodes[0].data = value
4040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def unlink(self):
4060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # This implementation does not call the base implementation
4070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # since most of that is not needed, and the expense of the
4080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # method call is not warranted.  We duplicate the removal of
4090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # children, but that's all we needed from the base class.
4100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elem = self.ownerElement
4110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if elem is not None:
4120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            del elem._attrs[self.nodeName]
4130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            del elem._attrsNS[(self.namespaceURI, self.localName)]
4140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if self._is_id:
4150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self._is_id = False
4160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                elem._magic_id_nodes -= 1
4170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.ownerDocument._magic_id_count -= 1
4180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for child in self.childNodes:
4190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            child.unlink()
4200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        del self.childNodes[:]
4210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_isId(self):
4230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self._is_id:
4240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return True
4250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        doc = self.ownerDocument
4260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elem = self.ownerElement
4270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if doc is None or elem is None:
4280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return False
4290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        info = doc._get_elem_info(elem)
4310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if info is None:
4320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return False
4330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.namespaceURI:
4340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return info.isIdNS(self.namespaceURI, self.localName)
4350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
4360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return info.isId(self.nodeName)
4370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_schemaType(self):
4390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        doc = self.ownerDocument
4400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elem = self.ownerElement
4410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if doc is None or elem is None:
4420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return _no_type
4430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        info = doc._get_elem_info(elem)
4450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if info is None:
4460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return _no_type
4470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.namespaceURI:
4480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return info.getAttributeTypeNS(self.namespaceURI, self.localName)
4490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
4500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return info.getAttributeType(self.nodeName)
4510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Attr, "isId",       doc="True if this attribute is an ID.")
4530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Attr, "localName",  doc="Namespace-local name of this attribute.")
4540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Attr, "schemaType", doc="Schema type for this attribute.")
4550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass NamedNodeMap(object):
4580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """The attribute list is a transient interface to the underlying
4590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    dictionaries.  Mutations here will change the underlying element's
4600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    dictionary.
4610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    Ordering is imposed artificially and does not reflect the order of
4630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    attributes as found in an input document.
4640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """
4650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
4670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, attrs, attrsNS, ownerElement):
4690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._attrs = attrs
4700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._attrsNS = attrsNS
4710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._ownerElement = ownerElement
4720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_length(self):
4740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return len(self._attrs)
4750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def item(self, index):
4770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
4780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self[self._attrs.keys()[index]]
4790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except IndexError:
4800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
4810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def items(self):
4830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        L = []
4840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for node in self._attrs.values():
4850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            L.append((node.nodeName, node.value))
4860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return L
4870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def itemsNS(self):
4890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        L = []
4900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for node in self._attrs.values():
4910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            L.append(((node.namespaceURI, node.localName), node.value))
4920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return L
4930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def has_key(self, key):
4950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if isinstance(key, StringTypes):
4960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return key in self._attrs
4970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
4980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return key in self._attrsNS
4990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def keys(self):
5010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self._attrs.keys()
5020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def keysNS(self):
5040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self._attrsNS.keys()
5050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def values(self):
5070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self._attrs.values()
5080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def get(self, name, value=None):
5100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self._attrs.get(name, value)
5110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    __len__ = _get_length
5130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    __hash__ = None # Mutable type can't be correctly hashed
5150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __cmp__(self, other):
5160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self._attrs is getattr(other, "_attrs", None):
5170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return 0
5180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
5190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return cmp(id(self), id(other))
5200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __getitem__(self, attname_or_tuple):
5220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if isinstance(attname_or_tuple, tuple):
5230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self._attrsNS[attname_or_tuple]
5240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
5250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self._attrs[attname_or_tuple]
5260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # same as set
5280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __setitem__(self, attname, value):
5290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if isinstance(value, StringTypes):
5300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
5310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                node = self._attrs[attname]
5320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except KeyError:
5330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                node = Attr(attname)
5340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                node.ownerDocument = self._ownerElement.ownerDocument
5350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.setNamedItem(node)
5360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            node.value = value
5370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
5380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if not isinstance(value, Attr):
5390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                raise TypeError, "value must be a string or Attr object"
5400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            node = value
5410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.setNamedItem(node)
5420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getNamedItem(self, name):
5440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
5450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self._attrs[name]
5460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except KeyError:
5470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
5480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getNamedItemNS(self, namespaceURI, localName):
5500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
5510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self._attrsNS[(namespaceURI, localName)]
5520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except KeyError:
5530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
5540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeNamedItem(self, name):
5560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n = self.getNamedItem(name)
5570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if n is not None:
5580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _clear_id_cache(self._ownerElement)
5590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            del self._attrs[n.nodeName]
5600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            del self._attrsNS[(n.namespaceURI, n.localName)]
5610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if 'ownerElement' in n.__dict__:
5620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                n.__dict__['ownerElement'] = None
5630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return n
5640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
5650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
5660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeNamedItemNS(self, namespaceURI, localName):
5680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n = self.getNamedItemNS(namespaceURI, localName)
5690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if n is not None:
5700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _clear_id_cache(self._ownerElement)
5710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            del self._attrsNS[(n.namespaceURI, n.localName)]
5720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            del self._attrs[n.nodeName]
5730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if 'ownerElement' in n.__dict__:
5740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                n.__dict__['ownerElement'] = None
5750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return n
5760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
5770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
5780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setNamedItem(self, node):
5800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not isinstance(node, Attr):
5810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.HierarchyRequestErr(
5820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "%s cannot be child of %s" % (repr(node), repr(self)))
5830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        old = self._attrs.get(node.name)
5840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if old:
5850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            old.unlink()
5860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._attrs[node.name] = node
5870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._attrsNS[(node.namespaceURI, node.localName)] = node
5880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node.ownerElement = self._ownerElement
5890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _clear_id_cache(node.ownerElement)
5900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return old
5910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setNamedItemNS(self, node):
5930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.setNamedItem(node)
5940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __delitem__(self, attname_or_tuple):
5960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node = self[attname_or_tuple]
5970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _clear_id_cache(node.ownerElement)
5980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node.unlink()
5990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __getstate__(self):
6010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self._attrs, self._attrsNS, self._ownerElement
6020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __setstate__(self, state):
6040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._attrs, self._attrsNS, self._ownerElement = state
6050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(NamedNodeMap, "length",
6070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            doc="Number of nodes in the NamedNodeMap.")
6080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiAttributeList = NamedNodeMap
6100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TypeInfo(object):
6130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    __slots__ = 'namespace', 'name'
6140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, namespace, name):
6160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.namespace = namespace
6170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.name = name
6180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __repr__(self):
6200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.namespace:
6210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return "<TypeInfo %r (from %r)>" % (self.name, self.namespace)
6220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
6230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return "<TypeInfo %r>" % self.name
6240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_name(self):
6260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.name
6270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_namespace(self):
6290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.namespace
6300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi_no_type = TypeInfo(None, None)
6320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Element(Node):
6340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.ELEMENT_NODE
6350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeValue = None
6360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    schemaType = _no_type
6370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _magic_id_nodes = 0
6390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _child_node_types = (Node.ELEMENT_NODE,
6410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.PROCESSING_INSTRUCTION_NODE,
6420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.COMMENT_NODE,
6430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.TEXT_NODE,
6440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.CDATA_SECTION_NODE,
6450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.ENTITY_REFERENCE_NODE)
6460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
6480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 localName=None):
6490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.tagName = self.nodeName = tagName
6500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.prefix = prefix
6510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.namespaceURI = namespaceURI
6520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.childNodes = NodeList()
6530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._attrs = {}   # attributes are double-indexed:
6550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._attrsNS = {} #    tagName -> Attribute
6560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           #    URI,localName -> Attribute
6570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           # in the future: consider lazy generation
6580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           # of attribute objects this is too tricky
6590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           # for now because of headaches with
6600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           # namespaces.
6610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_localName(self):
6630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.tagName.split(":", 1)[-1]
6640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_tagName(self):
6660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.tagName
6670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def unlink(self):
6690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for attr in self._attrs.values():
6700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            attr.unlink()
6710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._attrs = None
6720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._attrsNS = None
6730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        Node.unlink(self)
6740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getAttribute(self, attname):
6760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
6770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self._attrs[attname].value
6780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except KeyError:
6790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return ""
6800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getAttributeNS(self, namespaceURI, localName):
6820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
6830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self._attrsNS[(namespaceURI, localName)].value
6840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except KeyError:
6850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return ""
6860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setAttribute(self, attname, value):
6880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        attr = self.getAttributeNode(attname)
6890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if attr is None:
6900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            attr = Attr(attname)
6910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # for performance
6920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = attr.__dict__
6930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d["value"] = d["nodeValue"] = value
6940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d["ownerDocument"] = self.ownerDocument
6950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.setAttributeNode(attr)
6960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elif value != attr.value:
6970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = attr.__dict__
6980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d["value"] = d["nodeValue"] = value
6990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if attr.isId:
7000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                _clear_id_cache(self)
7010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setAttributeNS(self, namespaceURI, qualifiedName, value):
7030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        prefix, localname = _nssplit(qualifiedName)
7040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        attr = self.getAttributeNodeNS(namespaceURI, localname)
7050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if attr is None:
7060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # for performance
7070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            attr = Attr(qualifiedName, namespaceURI, localname, prefix)
7080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = attr.__dict__
7090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d["prefix"] = prefix
7100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d["nodeName"] = qualifiedName
7110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d["value"] = d["nodeValue"] = value
7120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d["ownerDocument"] = self.ownerDocument
7130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.setAttributeNode(attr)
7140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
7150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = attr.__dict__
7160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if value != attr.value:
7170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                d["value"] = d["nodeValue"] = value
7180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if attr.isId:
7190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    _clear_id_cache(self)
7200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if attr.prefix != prefix:
7210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                d["prefix"] = prefix
7220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                d["nodeName"] = qualifiedName
7230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getAttributeNode(self, attrname):
7250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self._attrs.get(attrname)
7260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getAttributeNodeNS(self, namespaceURI, localName):
7280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self._attrsNS.get((namespaceURI, localName))
7290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setAttributeNode(self, attr):
7310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if attr.ownerElement not in (None, self):
7320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.InuseAttributeErr("attribute node already owned")
7330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        old1 = self._attrs.get(attr.name, None)
7340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if old1 is not None:
7350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.removeAttributeNode(old1)
7360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
7370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if old2 is not None and old2 is not old1:
7380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.removeAttributeNode(old2)
7390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _set_attribute_node(self, attr)
7400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if old1 is not attr:
7420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # It might have already been part of this node, in which case
7430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # it doesn't represent a change, and should not be returned.
7440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return old1
7450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if old2 is not attr:
7460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return old2
7470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    setAttributeNodeNS = setAttributeNode
7490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeAttribute(self, name):
7510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
7520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            attr = self._attrs[name]
7530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except KeyError:
7540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
7550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.removeAttributeNode(attr)
7560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeAttributeNS(self, namespaceURI, localName):
7580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
7590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            attr = self._attrsNS[(namespaceURI, localName)]
7600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except KeyError:
7610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
7620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.removeAttributeNode(attr)
7630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeAttributeNode(self, node):
7650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node is None:
7660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
7670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
7680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self._attrs[node.name]
7690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except KeyError:
7700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
7710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _clear_id_cache(self)
7720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node.unlink()
7730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Restore this since the node is still useful and otherwise
7740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # unlinked
7750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node.ownerDocument = self.ownerDocument
7760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    removeAttributeNodeNS = removeAttributeNode
7780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def hasAttribute(self, name):
7800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return name in self._attrs
7810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def hasAttributeNS(self, namespaceURI, localName):
7830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return (namespaceURI, localName) in self._attrsNS
7840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getElementsByTagName(self, name):
7860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _get_elements_by_tagName_helper(self, name, NodeList())
7870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getElementsByTagNameNS(self, namespaceURI, localName):
7890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _get_elements_by_tagName_ns_helper(
7900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self, namespaceURI, localName, NodeList())
7910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __repr__(self):
7930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
7940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def writexml(self, writer, indent="", addindent="", newl=""):
7960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # indent = current indentation
7970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # addindent = indentation to add to higher levels
7980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # newl = newline string
7990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        writer.write(indent+"<" + self.tagName)
8000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        attrs = self._get_attributes()
8020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a_names = attrs.keys()
8030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a_names.sort()
8040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for a_name in a_names:
8060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write(" %s=\"" % a_name)
8070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _write_data(writer, attrs[a_name].value)
8080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write("\"")
8090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.childNodes:
8100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write(">")
8110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if (len(self.childNodes) == 1 and
8120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.childNodes[0].nodeType == Node.TEXT_NODE):
8130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.childNodes[0].writexml(writer, '', '', '')
8140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
8150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                writer.write(newl)
8160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                for node in self.childNodes:
8170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    node.writexml(writer, indent+addindent, addindent, newl)
8180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                writer.write(indent)
8190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write("</%s>%s" % (self.tagName, newl))
8200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
8210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write("/>%s"%(newl))
8220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_attributes(self):
8240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return NamedNodeMap(self._attrs, self._attrsNS, self)
8250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def hasAttributes(self):
8270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self._attrs:
8280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return True
8290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
8300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return False
8310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # DOM Level 3 attributes, based on the 22 Oct 2002 draft
8330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setIdAttribute(self, name):
8350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        idAttr = self.getAttributeNode(name)
8360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.setIdAttributeNode(idAttr)
8370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setIdAttributeNS(self, namespaceURI, localName):
8390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        idAttr = self.getAttributeNodeNS(namespaceURI, localName)
8400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.setIdAttributeNode(idAttr)
8410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setIdAttributeNode(self, idAttr):
8430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if idAttr is None or not self.isSameNode(idAttr.ownerElement):
8440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
8450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if _get_containing_entref(self) is not None:
8460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NoModificationAllowedErr()
8470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not idAttr._is_id:
8480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            idAttr.__dict__['_is_id'] = True
8490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self._magic_id_nodes += 1
8500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.ownerDocument._magic_id_count += 1
8510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _clear_id_cache(self)
8520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Element, "attributes",
8540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            doc="NamedNodeMap of attributes on the element.")
8550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Element, "localName",
8560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            doc="Namespace-local name of this element.")
8570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _set_attribute_node(element, attr):
8600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _clear_id_cache(element)
8610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    element._attrs[attr.name] = attr
8620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
8630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # This creates a circular reference, but Element.unlink()
8650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # breaks the cycle since the references to the attribute
8660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # dictionaries are tossed.
8670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    attr.__dict__['ownerElement'] = element
8680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Childless:
8710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """Mixin that makes childless-ness easy to implement and avoids
8720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    the complexity of the Node methods that deal with children.
8730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """
8740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    attributes = None
8760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    childNodes = EmptyNodeList()
8770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    firstChild = None
8780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    lastChild = None
8790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_firstChild(self):
8810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return None
8820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_lastChild(self):
8840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return None
8850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def appendChild(self, node):
8870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.HierarchyRequestErr(
8880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.nodeName + " nodes cannot have children")
8890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def hasChildNodes(self):
8910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return False
8920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def insertBefore(self, newChild, refChild):
8940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.HierarchyRequestErr(
8950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.nodeName + " nodes do not have children")
8960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeChild(self, oldChild):
8980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.NotFoundErr(
8990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.nodeName + " nodes do not have children")
9000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def normalize(self):
9020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # For childless nodes, normalize() has nothing to do.
9030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        pass
9040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def replaceChild(self, newChild, oldChild):
9060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.HierarchyRequestErr(
9070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.nodeName + " nodes do not have children")
9080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass ProcessingInstruction(Childless, Node):
9110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.PROCESSING_INSTRUCTION_NODE
9120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, target, data):
9140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.target = self.nodeName = target
9150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.data = self.nodeValue = data
9160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_data(self):
9180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.data
9190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _set_data(self, value):
9200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.__dict__
9210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['data'] = d['nodeValue'] = value
9220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_target(self):
9240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.target
9250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _set_target(self, value):
9260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.__dict__
9270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['target'] = d['nodeName'] = value
9280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __setattr__(self, name, value):
9300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if name == "data" or name == "nodeValue":
9310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.__dict__['data'] = self.__dict__['nodeValue'] = value
9320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elif name == "target" or name == "nodeName":
9330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.__dict__['target'] = self.__dict__['nodeName'] = value
9340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
9350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.__dict__[name] = value
9360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def writexml(self, writer, indent="", addindent="", newl=""):
9380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
9390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass CharacterData(Childless, Node):
9420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_length(self):
9430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return len(self.data)
9440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    __len__ = _get_length
9450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_data(self):
9470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.__dict__['data']
9480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _set_data(self, data):
9490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.__dict__
9500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['data'] = d['nodeValue'] = data
9510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _get_nodeValue = _get_data
9530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _set_nodeValue = _set_data
9540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __setattr__(self, name, value):
9560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if name == "data" or name == "nodeValue":
9570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.__dict__['data'] = self.__dict__['nodeValue'] = value
9580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
9590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.__dict__[name] = value
9600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __repr__(self):
9620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        data = self.data
9630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if len(data) > 10:
9640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dotdotdot = "..."
9650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
9660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dotdotdot = ""
9670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return '<DOM %s node "%r%s">' % (
9680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.__class__.__name__, data[0:10], dotdotdot)
9690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def substringData(self, offset, count):
9710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if offset < 0:
9720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("offset cannot be negative")
9730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if offset >= len(self.data):
9740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
9750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if count < 0:
9760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("count cannot be negative")
9770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.data[offset:offset+count]
9780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def appendData(self, arg):
9800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.data = self.data + arg
9810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def insertData(self, offset, arg):
9830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if offset < 0:
9840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("offset cannot be negative")
9850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if offset >= len(self.data):
9860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
9870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if arg:
9880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.data = "%s%s%s" % (
9890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.data[:offset], arg, self.data[offset:])
9900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def deleteData(self, offset, count):
9920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if offset < 0:
9930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("offset cannot be negative")
9940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if offset >= len(self.data):
9950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
9960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if count < 0:
9970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("count cannot be negative")
9980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if count:
9990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.data = self.data[:offset] + self.data[offset+count:]
10000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def replaceData(self, offset, count, arg):
10020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if offset < 0:
10030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("offset cannot be negative")
10040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if offset >= len(self.data):
10050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
10060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if count < 0:
10070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("count cannot be negative")
10080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if count:
10090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.data = "%s%s%s" % (
10100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.data[:offset], arg, self.data[offset+count:])
10110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(CharacterData, "length", doc="Length of the string data.")
10130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Text(CharacterData):
10160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Make sure we don't add an instance __dict__ if we don't already
10170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # have one, at least when that's possible:
10180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # XXX this does not work, CharacterData is an old-style class
10190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # __slots__ = ()
10200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.TEXT_NODE
10220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeName = "#text"
10230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    attributes = None
10240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def splitText(self, offset):
10260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if offset < 0 or offset > len(self.data):
10270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.IndexSizeErr("illegal offset value")
10280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        newText = self.__class__()
10290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        newText.data = self.data[offset:]
10300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        newText.ownerDocument = self.ownerDocument
10310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        next = self.nextSibling
10320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.parentNode and self in self.parentNode.childNodes:
10330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if next is None:
10340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.parentNode.appendChild(newText)
10350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
10360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.parentNode.insertBefore(newText, next)
10370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.data = self.data[:offset]
10380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return newText
10390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def writexml(self, writer, indent="", addindent="", newl=""):
10410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _write_data(writer, "%s%s%s" % (indent, self.data, newl))
10420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # DOM Level 3 (WD 9 April 2002)
10440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_wholeText(self):
10460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        L = [self.data]
10470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n = self.previousSibling
10480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        while n is not None:
10490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
10500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                L.insert(0, n.data)
10510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                n = n.previousSibling
10520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
10530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
10540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n = self.nextSibling
10550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        while n is not None:
10560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
10570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                L.append(n.data)
10580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                n = n.nextSibling
10590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
10600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
10610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return ''.join(L)
10620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def replaceWholeText(self, content):
10640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # XXX This needs to be seriously changed if minidom ever
10650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # supports EntityReference nodes.
10660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        parent = self.parentNode
10670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n = self.previousSibling
10680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        while n is not None:
10690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
10700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                next = n.previousSibling
10710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                parent.removeChild(n)
10720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                n = next
10730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
10740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
10750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n = self.nextSibling
10760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not content:
10770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            parent.removeChild(self)
10780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        while n is not None:
10790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
10800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                next = n.nextSibling
10810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                parent.removeChild(n)
10820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                n = next
10830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
10840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
10850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if content:
10860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.__dict__
10870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d['data'] = content
10880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d['nodeValue'] = content
10890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self
10900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
10910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
10920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_isWhitespaceInElementContent(self):
10940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.data.strip():
10950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return False
10960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elem = _get_containing_element(self)
10970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if elem is None:
10980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return False
10990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        info = self.ownerDocument._get_elem_info(elem)
11000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if info is None:
11010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return False
11020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
11030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return info.isElementContent()
11040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Text, "isWhitespaceInElementContent",
11060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            doc="True iff this text node contains only whitespace"
11070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                " and is in element content.")
11080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Text, "wholeText",
11090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            doc="The text of all logically-adjacent text nodes.")
11100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _get_containing_element(node):
11130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    c = node.parentNode
11140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    while c is not None:
11150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if c.nodeType == Node.ELEMENT_NODE:
11160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return c
11170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        c = c.parentNode
11180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return None
11190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _get_containing_entref(node):
11210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    c = node.parentNode
11220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    while c is not None:
11230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if c.nodeType == Node.ENTITY_REFERENCE_NODE:
11240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return c
11250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        c = c.parentNode
11260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return None
11270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Comment(Childless, CharacterData):
11300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.COMMENT_NODE
11310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeName = "#comment"
11320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, data):
11340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.data = self.nodeValue = data
11350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def writexml(self, writer, indent="", addindent="", newl=""):
11370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if "--" in self.data:
11380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise ValueError("'--' is not allowed in a comment node")
11390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
11400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass CDATASection(Text):
11430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Make sure we don't add an instance __dict__ if we don't already
11440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # have one, at least when that's possible:
11450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # XXX this does not work, Text is an old-style class
11460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # __slots__ = ()
11470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.CDATA_SECTION_NODE
11490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeName = "#cdata-section"
11500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def writexml(self, writer, indent="", addindent="", newl=""):
11520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.data.find("]]>") >= 0:
11530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise ValueError("']]>' not allowed in a CDATA section")
11540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        writer.write("<![CDATA[%s]]>" % self.data)
11550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass ReadOnlySequentialNamedNodeMap(object):
11580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    __slots__ = '_seq',
11590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, seq=()):
11610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # seq should be a list or tuple
11620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._seq = seq
11630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __len__(self):
11650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return len(self._seq)
11660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_length(self):
11680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return len(self._seq)
11690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getNamedItem(self, name):
11710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for n in self._seq:
11720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if n.nodeName == name:
11730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return n
11740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getNamedItemNS(self, namespaceURI, localName):
11760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for n in self._seq:
11770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if n.namespaceURI == namespaceURI and n.localName == localName:
11780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return n
11790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __getitem__(self, name_or_tuple):
11810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if isinstance(name_or_tuple, tuple):
11820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            node = self.getNamedItemNS(*name_or_tuple)
11830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
11840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            node = self.getNamedItem(name_or_tuple)
11850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node is None:
11860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise KeyError, name_or_tuple
11870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return node
11880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def item(self, index):
11900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if index < 0:
11910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
11920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
11930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self._seq[index]
11940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except IndexError:
11950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
11960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeNamedItem(self, name):
11980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.NoModificationAllowedErr(
11990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            "NamedNodeMap instance is read-only")
12000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeNamedItemNS(self, namespaceURI, localName):
12020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.NoModificationAllowedErr(
12030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            "NamedNodeMap instance is read-only")
12040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setNamedItem(self, node):
12060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.NoModificationAllowedErr(
12070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            "NamedNodeMap instance is read-only")
12080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setNamedItemNS(self, node):
12100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.NoModificationAllowedErr(
12110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            "NamedNodeMap instance is read-only")
12120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __getstate__(self):
12140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return [self._seq]
12150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __setstate__(self, state):
12170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._seq = state[0]
12180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(ReadOnlySequentialNamedNodeMap, "length",
12200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            doc="Number of entries in the NamedNodeMap.")
12210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Identified:
12240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """Mix-in class that supports the publicId and systemId attributes."""
12250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # XXX this does not work, this is an old-style class
12270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # __slots__ = 'publicId', 'systemId'
12280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _identified_mixin_init(self, publicId, systemId):
12300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.publicId = publicId
12310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.systemId = systemId
12320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_publicId(self):
12340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.publicId
12350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_systemId(self):
12370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.systemId
12380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass DocumentType(Identified, Childless, Node):
12400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.DOCUMENT_TYPE_NODE
12410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeValue = None
12420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    name = None
12430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    publicId = None
12440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    systemId = None
12450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    internalSubset = None
12460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, qualifiedName):
12480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.entities = ReadOnlySequentialNamedNodeMap()
12490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.notations = ReadOnlySequentialNamedNodeMap()
12500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if qualifiedName:
12510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            prefix, localname = _nssplit(qualifiedName)
12520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.name = localname
12530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.nodeName = self.name
12540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_internalSubset(self):
12560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.internalSubset
12570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def cloneNode(self, deep):
12590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.ownerDocument is None:
12600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # it's ok
12610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            clone = DocumentType(None)
12620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            clone.name = self.name
12630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            clone.nodeName = self.name
12640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            operation = xml.dom.UserDataHandler.NODE_CLONED
12650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if deep:
12660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                clone.entities._seq = []
12670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                clone.notations._seq = []
12680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                for n in self.notations._seq:
12690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    notation = Notation(n.nodeName, n.publicId, n.systemId)
12700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    clone.notations._seq.append(notation)
12710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    n._call_user_data_handler(operation, n, notation)
12720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                for e in self.entities._seq:
12730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    entity = Entity(e.nodeName, e.publicId, e.systemId,
12740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                    e.notationName)
12750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    entity.actualEncoding = e.actualEncoding
12760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    entity.encoding = e.encoding
12770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    entity.version = e.version
12780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    clone.entities._seq.append(entity)
12790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    e._call_user_data_handler(operation, n, entity)
12800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self._call_user_data_handler(operation, self, clone)
12810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return clone
12820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
12830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
12840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def writexml(self, writer, indent="", addindent="", newl=""):
12860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        writer.write("<!DOCTYPE ")
12870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        writer.write(self.name)
12880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.publicId:
12890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write("%s  PUBLIC '%s'%s  '%s'"
12900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         % (newl, self.publicId, newl, self.systemId))
12910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elif self.systemId:
12920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write("%s  SYSTEM '%s'" % (newl, self.systemId))
12930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.internalSubset is not None:
12940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write(" [")
12950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write(self.internalSubset)
12960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write("]")
12970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        writer.write(">"+newl)
12980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Entity(Identified, Node):
13000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    attributes = None
13010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.ENTITY_NODE
13020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeValue = None
13030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    actualEncoding = None
13050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    encoding = None
13060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    version = None
13070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, name, publicId, systemId, notation):
13090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.nodeName = name
13100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.notationName = notation
13110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.childNodes = NodeList()
13120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._identified_mixin_init(publicId, systemId)
13130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_actualEncoding(self):
13150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.actualEncoding
13160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_encoding(self):
13180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.encoding
13190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_version(self):
13210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.version
13220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def appendChild(self, newChild):
13240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.HierarchyRequestErr(
13250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            "cannot append children to an entity node")
13260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def insertBefore(self, newChild, refChild):
13280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.HierarchyRequestErr(
13290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            "cannot insert children below an entity node")
13300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeChild(self, oldChild):
13320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.HierarchyRequestErr(
13330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            "cannot remove children from an entity node")
13340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def replaceChild(self, newChild, oldChild):
13360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.HierarchyRequestErr(
13370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            "cannot replace children of an entity node")
13380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Notation(Identified, Childless, Node):
13400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.NOTATION_NODE
13410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeValue = None
13420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, name, publicId, systemId):
13440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.nodeName = name
13450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._identified_mixin_init(publicId, systemId)
13460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass DOMImplementation(DOMImplementationLS):
13490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _features = [("core", "1.0"),
13500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 ("core", "2.0"),
13510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 ("core", None),
13520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 ("xml", "1.0"),
13530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 ("xml", "2.0"),
13540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 ("xml", None),
13550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 ("ls-load", "3.0"),
13560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 ("ls-load", None),
13570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 ]
13580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def hasFeature(self, feature, version):
13600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if version == "":
13610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            version = None
13620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return (feature.lower(), version) in self._features
13630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createDocument(self, namespaceURI, qualifiedName, doctype):
13650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if doctype and doctype.parentNode is not None:
13660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.WrongDocumentErr(
13670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "doctype object owned by another DOM tree")
13680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        doc = self._create_document()
13690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        add_root_element = not (namespaceURI is None
13710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                and qualifiedName is None
13720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                and doctype is None)
13730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not qualifiedName and add_root_element:
13750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # The spec is unclear what to raise here; SyntaxErr
13760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # would be the other obvious candidate. Since Xerces raises
13770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # InvalidCharacterErr, and since SyntaxErr is not listed
13780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # for createDocument, that seems to be the better choice.
13790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # XXX: need to check for illegal characters here and in
13800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # createElement.
13810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # DOM Level III clears this up when talking about the return value
13830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # of this function.  If namespaceURI, qName and DocType are
13840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Null the document is returned without a document element
13850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Otherwise if doctype or namespaceURI are not None
13860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Then we go back to the above problem
13870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.InvalidCharacterErr("Element with no name")
13880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if add_root_element:
13900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            prefix, localname = _nssplit(qualifiedName)
13910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if prefix == "xml" \
13920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi               and namespaceURI != "http://www.w3.org/XML/1998/namespace":
13930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
13940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if prefix and not namespaceURI:
13950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                raise xml.dom.NamespaceErr(
13960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    "illegal use of prefix without namespaces")
13970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            element = doc.createElementNS(namespaceURI, qualifiedName)
13980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if doctype:
13990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                doc.appendChild(doctype)
14000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            doc.appendChild(element)
14010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if doctype:
14030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            doctype.parentNode = doctype.ownerDocument = doc
14040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        doc.doctype = doctype
14060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        doc.implementation = self
14070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return doc
14080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createDocumentType(self, qualifiedName, publicId, systemId):
14100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        doctype = DocumentType(qualifiedName)
14110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        doctype.publicId = publicId
14120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        doctype.systemId = systemId
14130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return doctype
14140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # DOM Level 3 (WD 9 April 2002)
14160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getInterface(self, feature):
14180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.hasFeature(feature, None):
14190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self
14200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
14210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
14220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # internal
14240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _create_document(self):
14250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return Document()
14260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass ElementInfo(object):
14280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """Object that represents content-model information for an element.
14290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    This implementation is not expected to be used in practice; DOM
14310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    builders should provide implementations which do the right thing
14320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    using information available to it.
14330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """
14350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    __slots__ = 'tagName',
14370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, name):
14390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.tagName = name
14400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getAttributeType(self, aname):
14420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _no_type
14430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getAttributeTypeNS(self, namespaceURI, localName):
14450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _no_type
14460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def isElementContent(self):
14480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return False
14490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def isEmpty(self):
14510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        """Returns true iff this element is declared to have an EMPTY
14520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        content model."""
14530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return False
14540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def isId(self, aname):
14560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        """Returns true iff the named attribute is a DTD-style ID."""
14570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return False
14580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def isIdNS(self, namespaceURI, localName):
14600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        """Returns true iff the identified attribute is a DTD-style ID."""
14610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return False
14620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __getstate__(self):
14640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.tagName
14650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __setstate__(self, state):
14670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.tagName = state
14680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _clear_id_cache(node):
14700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if node.nodeType == Node.DOCUMENT_NODE:
14710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node._id_cache.clear()
14720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node._id_search_stack = None
14730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    elif _in_document(node):
14740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node.ownerDocument._id_cache.clear()
14750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node.ownerDocument._id_search_stack= None
14760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Document(Node, DocumentLS):
14780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
14790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
14800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeType = Node.DOCUMENT_NODE
14820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeName = "#document"
14830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    nodeValue = None
14840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    attributes = None
14850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    doctype = None
14860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    parentNode = None
14870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    previousSibling = nextSibling = None
14880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    implementation = DOMImplementation()
14900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Document attributes from Level 3 (WD 9 April 2002)
14920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    actualEncoding = None
14940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    encoding = None
14950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    standalone = None
14960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    version = None
14970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    strictErrorChecking = False
14980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    errorHandler = None
14990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    documentURI = None
15000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    _magic_id_count = 0
15020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self):
15040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.childNodes = NodeList()
15050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # mapping of (namespaceURI, localName) -> ElementInfo
15060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #        and tagName -> ElementInfo
15070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._elem_info = {}
15080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._id_cache = {}
15090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._id_search_stack = None
15100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_elem_info(self, element):
15120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if element.namespaceURI:
15130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            key = element.namespaceURI, element.localName
15140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
15150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            key = element.tagName
15160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self._elem_info.get(key)
15170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_actualEncoding(self):
15190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.actualEncoding
15200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_doctype(self):
15220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.doctype
15230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_documentURI(self):
15250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.documentURI
15260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_encoding(self):
15280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.encoding
15290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_errorHandler(self):
15310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.errorHandler
15320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_standalone(self):
15340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.standalone
15350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_strictErrorChecking(self):
15370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.strictErrorChecking
15380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_version(self):
15400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.version
15410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def appendChild(self, node):
15430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.nodeType not in self._child_node_types:
15440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.HierarchyRequestErr(
15450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "%s cannot be child of %s" % (repr(node), repr(self)))
15460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.parentNode is not None:
15470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # This needs to be done before the next test since this
15480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # may *be* the document element, in which case it should
15490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # end up re-ordered to the end.
15500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            node.parentNode.removeChild(node)
15510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.nodeType == Node.ELEMENT_NODE \
15530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi           and self._get_documentElement():
15540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.HierarchyRequestErr(
15550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "two document elements disallowed")
15560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return Node.appendChild(self, node)
15570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def removeChild(self, oldChild):
15590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
15600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.childNodes.remove(oldChild)
15610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except ValueError:
15620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotFoundErr()
15630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        oldChild.nextSibling = oldChild.previousSibling = None
15640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        oldChild.parentNode = None
15650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.documentElement is oldChild:
15660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.documentElement = None
15670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return oldChild
15690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _get_documentElement(self):
15710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for node in self.childNodes:
15720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if node.nodeType == Node.ELEMENT_NODE:
15730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return node
15740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def unlink(self):
15760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.doctype is not None:
15770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.doctype.unlink()
15780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.doctype = None
15790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        Node.unlink(self)
15800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def cloneNode(self, deep):
15820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not deep:
15830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
15840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone = self.implementation.createDocument(None, None, None)
15850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone.encoding = self.encoding
15860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone.standalone = self.standalone
15870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone.version = self.version
15880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for n in self.childNodes:
15890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            childclone = _clone_node(n, deep, clone)
15900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            assert childclone.ownerDocument.isSameNode(clone)
15910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            clone.childNodes.append(childclone)
15920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if childclone.nodeType == Node.DOCUMENT_NODE:
15930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                assert clone.documentElement is None
15940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
15950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                assert clone.doctype is None
15960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                clone.doctype = childclone
15970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            childclone.parentNode = clone
15980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
15990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                     self, clone)
16000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return clone
16010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createDocumentFragment(self):
16030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = DocumentFragment()
16040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d.ownerDocument = self
16050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return d
16060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createElement(self, tagName):
16080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e = Element(tagName)
16090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e.ownerDocument = self
16100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return e
16110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createTextNode(self, data):
16130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not isinstance(data, StringTypes):
16140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise TypeError, "node contents must be a string"
16150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = Text()
16160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t.data = data
16170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t.ownerDocument = self
16180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return t
16190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createCDATASection(self, data):
16210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not isinstance(data, StringTypes):
16220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise TypeError, "node contents must be a string"
16230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        c = CDATASection()
16240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        c.data = data
16250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        c.ownerDocument = self
16260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return c
16270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createComment(self, data):
16290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        c = Comment(data)
16300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        c.ownerDocument = self
16310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return c
16320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createProcessingInstruction(self, target, data):
16340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        p = ProcessingInstruction(target, data)
16350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        p.ownerDocument = self
16360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return p
16370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createAttribute(self, qName):
16390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = Attr(qName)
16400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a.ownerDocument = self
16410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a.value = ""
16420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return a
16430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createElementNS(self, namespaceURI, qualifiedName):
16450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        prefix, localName = _nssplit(qualifiedName)
16460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e = Element(qualifiedName, namespaceURI, prefix)
16470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e.ownerDocument = self
16480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return e
16490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def createAttributeNS(self, namespaceURI, qualifiedName):
16510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        prefix, localName = _nssplit(qualifiedName)
16520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = Attr(qualifiedName, namespaceURI, localName, prefix)
16530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a.ownerDocument = self
16540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a.value = ""
16550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return a
16560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # A couple of implementation-specific helpers to create node types
16580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # not supported by the W3C DOM specs:
16590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _create_entity(self, name, publicId, systemId, notationName):
16610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e = Entity(name, publicId, systemId, notationName)
16620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e.ownerDocument = self
16630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return e
16640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def _create_notation(self, name, publicId, systemId):
16660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n = Notation(name, publicId, systemId)
16670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n.ownerDocument = self
16680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return n
16690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getElementById(self, id):
16710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if id in self._id_cache:
16720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self._id_cache[id]
16730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not (self._elem_info or self._magic_id_count):
16740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
16750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        stack = self._id_search_stack
16770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if stack is None:
16780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # we never searched before, or the cache has been cleared
16790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            stack = [self.documentElement]
16800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self._id_search_stack = stack
16810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elif not stack:
16820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Previous search was completed and cache is still valid;
16830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # no matching node.
16840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return None
16850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        result = None
16870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        while stack:
16880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            node = stack.pop()
16890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # add child elements to stack for continued searching
16900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            stack.extend([child for child in node.childNodes
16910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          if child.nodeType in _nodeTypes_with_children])
16920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # check this node
16930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            info = self._get_elem_info(node)
16940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if info:
16950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # We have to process all ID attributes before
16960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # returning in order to get all the attributes set to
16970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # be IDs using Element.setIdAttribute*().
16980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                for attr in node.attributes.values():
16990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if attr.namespaceURI:
17000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        if info.isIdNS(attr.namespaceURI, attr.localName):
17010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            self._id_cache[attr.value] = node
17020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            if attr.value == id:
17030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                result = node
17040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            elif not node._magic_id_nodes:
17050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                break
17060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    elif info.isId(attr.name):
17070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        self._id_cache[attr.value] = node
17080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        if attr.value == id:
17090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            result = node
17100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        elif not node._magic_id_nodes:
17110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            break
17120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    elif attr._is_id:
17130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        self._id_cache[attr.value] = node
17140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        if attr.value == id:
17150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            result = node
17160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        elif node._magic_id_nodes == 1:
17170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            break
17180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            elif node._magic_id_nodes:
17190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                for attr in node.attributes.values():
17200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if attr._is_id:
17210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        self._id_cache[attr.value] = node
17220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        if attr.value == id:
17230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            result = node
17240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if result is not None:
17250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
17260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return result
17270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getElementsByTagName(self, name):
17290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _get_elements_by_tagName_helper(self, name, NodeList())
17300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def getElementsByTagNameNS(self, namespaceURI, localName):
17320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _get_elements_by_tagName_ns_helper(
17330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self, namespaceURI, localName, NodeList())
17340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def isSupported(self, feature, version):
17360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.implementation.hasFeature(feature, version)
17370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def importNode(self, node, deep):
17390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if node.nodeType == Node.DOCUMENT_NODE:
17400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotSupportedErr("cannot import document nodes")
17410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
17420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotSupportedErr("cannot import document type nodes")
17430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _clone_node(node, deep, self)
17440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def writexml(self, writer, indent="", addindent="", newl="",
17460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                 encoding = None):
17470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if encoding is None:
17480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write('<?xml version="1.0" ?>'+newl)
17490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
17500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            writer.write('<?xml version="1.0" encoding="%s"?>%s' % (encoding, newl))
17510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for node in self.childNodes:
17520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            node.writexml(writer, indent, addindent, newl)
17530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # DOM Level 3 (WD 9 April 2002)
17550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def renameNode(self, n, namespaceURI, name):
17570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if n.ownerDocument is not self:
17580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.WrongDocumentErr(
17590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "cannot rename nodes from other documents;\n"
17600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "expected %s,\nfound %s" % (self, n.ownerDocument))
17610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
17620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            raise xml.dom.NotSupportedErr(
17630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                "renameNode() only applies to element and attribute nodes")
17640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if namespaceURI != EMPTY_NAMESPACE:
17650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if ':' in name:
17660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                prefix, localName = name.split(':', 1)
17670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if (  prefix == "xmlns"
17680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                      and namespaceURI != xml.dom.XMLNS_NAMESPACE):
17690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    raise xml.dom.NamespaceErr(
17700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        "illegal use of 'xmlns' prefix")
17710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
17720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if (  name == "xmlns"
17730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                      and namespaceURI != xml.dom.XMLNS_NAMESPACE
17740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                      and n.nodeType == Node.ATTRIBUTE_NODE):
17750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    raise xml.dom.NamespaceErr(
17760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        "illegal use of the 'xmlns' attribute")
17770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                prefix = None
17780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                localName = name
17790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
17800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            prefix = None
17810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            localName = None
17820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if n.nodeType == Node.ATTRIBUTE_NODE:
17830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            element = n.ownerElement
17840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if element is not None:
17850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                is_id = n._is_id
17860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                element.removeAttributeNode(n)
17870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
17880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            element = None
17890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # avoid __setattr__
17900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = n.__dict__
17910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['prefix'] = prefix
17920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['localName'] = localName
17930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['namespaceURI'] = namespaceURI
17940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d['nodeName'] = name
17950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if n.nodeType == Node.ELEMENT_NODE:
17960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d['tagName'] = name
17970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
17980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # attribute node
17990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d['name'] = name
18000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if element is not None:
18010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                element.setAttributeNode(n)
18020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if is_id:
18030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    element.setIdAttributeNode(n)
18040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # It's not clear from a semantic perspective whether we should
18050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # call the user data handlers for the NODE_RENAMED event since
18060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # we're re-using the existing node.  The draft spec has been
18070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # interpreted as meaning "no, don't call the handler unless a
18080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # new node is created."
18090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return n
18100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidefproperty(Document, "documentElement",
18120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            doc="Top-level element of this document.")
18130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _clone_node(node, deep, newOwnerDocument):
18160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """
18170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    Clone a node and give it the new owner document.
18180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    Called by Node.cloneNode and Document.importNode
18190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """
18200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if node.ownerDocument.isSameNode(newOwnerDocument):
18210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        operation = xml.dom.UserDataHandler.NODE_CLONED
18220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    else:
18230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        operation = xml.dom.UserDataHandler.NODE_IMPORTED
18240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if node.nodeType == Node.ELEMENT_NODE:
18250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone = newOwnerDocument.createElementNS(node.namespaceURI,
18260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                                 node.nodeName)
18270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for attr in node.attributes.values():
18280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
18290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
18300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            a.specified = attr.specified
18310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if deep:
18330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for child in node.childNodes:
18340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                c = _clone_node(child, deep, newOwnerDocument)
18350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                clone.appendChild(c)
18360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
18380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone = newOwnerDocument.createDocumentFragment()
18390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if deep:
18400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for child in node.childNodes:
18410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                c = _clone_node(child, deep, newOwnerDocument)
18420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                clone.appendChild(c)
18430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    elif node.nodeType == Node.TEXT_NODE:
18450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone = newOwnerDocument.createTextNode(node.data)
18460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    elif node.nodeType == Node.CDATA_SECTION_NODE:
18470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone = newOwnerDocument.createCDATASection(node.data)
18480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
18490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone = newOwnerDocument.createProcessingInstruction(node.target,
18500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                                             node.data)
18510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    elif node.nodeType == Node.COMMENT_NODE:
18520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone = newOwnerDocument.createComment(node.data)
18530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    elif node.nodeType == Node.ATTRIBUTE_NODE:
18540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
18550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                                   node.nodeName)
18560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone.specified = True
18570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone.value = node.value
18580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
18590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        assert node.ownerDocument is not newOwnerDocument
18600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        operation = xml.dom.UserDataHandler.NODE_IMPORTED
18610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone = newOwnerDocument.implementation.createDocumentType(
18620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            node.name, node.publicId, node.systemId)
18630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        clone.ownerDocument = newOwnerDocument
18640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if deep:
18650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            clone.entities._seq = []
18660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            clone.notations._seq = []
18670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for n in node.notations._seq:
18680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                notation = Notation(n.nodeName, n.publicId, n.systemId)
18690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                notation.ownerDocument = newOwnerDocument
18700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                clone.notations._seq.append(notation)
18710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if hasattr(n, '_call_user_data_handler'):
18720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    n._call_user_data_handler(operation, n, notation)
18730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for e in node.entities._seq:
18740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                entity = Entity(e.nodeName, e.publicId, e.systemId,
18750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                e.notationName)
18760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                entity.actualEncoding = e.actualEncoding
18770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                entity.encoding = e.encoding
18780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                entity.version = e.version
18790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                entity.ownerDocument = newOwnerDocument
18800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                clone.entities._seq.append(entity)
18810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if hasattr(e, '_call_user_data_handler'):
18820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    e._call_user_data_handler(operation, n, entity)
18830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    else:
18840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Note the cloning of Document and DocumentType nodes is
18850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # implementation specific.  minidom handles those cases
18860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # directly in the cloneNode() methods.
18870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
18880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Check for _call_user_data_handler() since this could conceivably
18900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # used with other DOM implementations (one of the FourThought
18910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # DOMs, perhaps?).
18920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if hasattr(node, '_call_user_data_handler'):
18930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        node._call_user_data_handler(operation, node, clone)
18940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return clone
18950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _nssplit(qualifiedName):
18980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    fields = qualifiedName.split(':', 1)
18990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if len(fields) == 2:
19000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return fields
19010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    else:
19020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return (None, fields[0])
19030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _get_StringIO():
19060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # we can't use cStringIO since it doesn't support Unicode strings
19070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    from StringIO import StringIO
19080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return StringIO()
19090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _do_pulldom_parse(func, args, kwargs):
19110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    events = func(*args, **kwargs)
19120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    toktype, rootNode = events.getEvent()
19130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    events.expandNode(rootNode)
19140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    events.clear()
19150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return rootNode
19160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef parse(file, parser=None, bufsize=None):
19180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """Parse a file into a DOM by filename or file object."""
19190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if parser is None and not bufsize:
19200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        from xml.dom import expatbuilder
19210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return expatbuilder.parse(file)
19220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    else:
19230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        from xml.dom import pulldom
19240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _do_pulldom_parse(pulldom.parse, (file,),
19250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            {'parser': parser, 'bufsize': bufsize})
19260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef parseString(string, parser=None):
19280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    """Parse a file into a DOM from a string."""
19290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if parser is None:
19300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        from xml.dom import expatbuilder
19310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return expatbuilder.parseString(string)
19320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    else:
19330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        from xml.dom import pulldom
19340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return _do_pulldom_parse(pulldom.parseString, (string,),
19350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                 {'parser': parser})
19360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef getDOMImplementation(features=None):
19380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if features:
19390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if isinstance(features, StringTypes):
19400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            features = domreg._parse_feature_string(features)
19410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for f, v in features:
19420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if not Document.implementation.hasFeature(f, v):
19430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return None
19440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return Document.implementation
1945