13257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel"""Simple implementation of the Level 1 DOM.
23257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
33257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielNamespaces and other minor Level 2 features are also supported.
43257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
53257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielparse("foo.xml")
63257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
73257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielparseString("<foo><bar/></foo>")
83257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
93257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielTodo:
103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel=====
113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel * convenience methods for getting elements and text.
123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel * more testing
133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel * bring some of the writer and linearizer code into conformance with this
143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        interface
153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel * SAX 2 namespaces
163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel"""
173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport xml.dom
193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfrom xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfrom xml.dom.minicompat import *
223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfrom xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS
233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel# This is used by the ID-cache invalidation checks; the list isn't
253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel# actually complete, since the nodes being checked will never be the
263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE.  (The node being checked is
273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel# the node being added or removed, not the node being modified.)
283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel#
293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE,
303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                            xml.dom.Node.ENTITY_REFERENCE_NODE)
313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Node(xml.dom.Node):
343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    namespaceURI = None # this is non-null only for elements and attributes
353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    parentNode = None
363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    ownerDocument = None
373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nextSibling = None
383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    previousSibling = None
393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __nonzero__(self):
433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return True
443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def toxml(self, encoding = None):
463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.toprettyxml("", "", encoding)
473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def toprettyxml(self, indent="\t", newl="\n", encoding = None):
493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # indent = the indentation string to prepend, per level
503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # newl = the newline string to append
513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        writer = _get_StringIO()
523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if encoding is not None:
533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            import codecs
543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # Can't use codecs.getwriter to preserve 2.0 compatibility
553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer = codecs.lookup(encoding)[3](writer)
563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.nodeType == Node.DOCUMENT_NODE:
573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # Can pass encoding only to document, to put it into XML header
583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.writexml(writer, "", indent, newl, encoding)
593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.writexml(writer, "", indent, newl)
613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return writer.getvalue()
623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def hasChildNodes(self):
643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.childNodes:
653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return True
663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return False
683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_childNodes(self):
703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.childNodes
713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_firstChild(self):
733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.childNodes:
743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self.childNodes[0]
753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_lastChild(self):
773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.childNodes:
783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self.childNodes[-1]
793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def insertBefore(self, newChild, refChild):
813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            for c in tuple(newChild.childNodes):
833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.insertBefore(c, refChild)
843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            ### The DOM does not clearly specify what to return in this case
853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return newChild
863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if newChild.nodeType not in self._child_node_types:
873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.HierarchyRequestErr(
883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "%s cannot be child of %s" % (repr(newChild), repr(self)))
893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if newChild.parentNode is not None:
903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            newChild.parentNode.removeChild(newChild)
913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if refChild is None:
923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.appendChild(newChild)
933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            try:
953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                index = self.childNodes.index(refChild)
963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            except ValueError:
973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                raise xml.dom.NotFoundErr()
983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if newChild.nodeType in _nodeTypes_with_children:
993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                _clear_id_cache(self)
1003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.childNodes.insert(index, newChild)
1013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            newChild.nextSibling = refChild
1023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            refChild.previousSibling = newChild
1033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if index:
1043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                node = self.childNodes[index-1]
1053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                node.nextSibling = newChild
1063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                newChild.previousSibling = node
1073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
1083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                newChild.previousSibling = None
1093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            newChild.parentNode = self
1103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return newChild
1113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def appendChild(self, node):
1133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
1143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            for c in tuple(node.childNodes):
1153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.appendChild(c)
1163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            ### The DOM does not clearly specify what to return in this case
1173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return node
1183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.nodeType not in self._child_node_types:
1193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.HierarchyRequestErr(
1203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "%s cannot be child of %s" % (repr(node), repr(self)))
1213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elif node.nodeType in _nodeTypes_with_children:
1223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _clear_id_cache(self)
1233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.parentNode is not None:
1243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            node.parentNode.removeChild(node)
1253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        _append_child(self, node)
1263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node.nextSibling = None
1273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return node
1283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def replaceChild(self, newChild, oldChild):
1303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
1313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            refChild = oldChild.nextSibling
1323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.removeChild(oldChild)
1333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self.insertBefore(newChild, refChild)
1343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if newChild.nodeType not in self._child_node_types:
1353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.HierarchyRequestErr(
1363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "%s cannot be child of %s" % (repr(newChild), repr(self)))
1373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if newChild is oldChild:
1383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return
1393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if newChild.parentNode is not None:
1403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            newChild.parentNode.removeChild(newChild)
1413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
1423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            index = self.childNodes.index(oldChild)
1433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except ValueError:
1443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
1453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.childNodes[index] = newChild
1463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        newChild.parentNode = self
1473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        oldChild.parentNode = None
1483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if (newChild.nodeType in _nodeTypes_with_children
1493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            or oldChild.nodeType in _nodeTypes_with_children):
1503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _clear_id_cache(self)
1513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        newChild.nextSibling = oldChild.nextSibling
1523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        newChild.previousSibling = oldChild.previousSibling
1533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        oldChild.nextSibling = None
1543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        oldChild.previousSibling = None
1553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if newChild.previousSibling:
1563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            newChild.previousSibling.nextSibling = newChild
1573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if newChild.nextSibling:
1583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            newChild.nextSibling.previousSibling = newChild
1593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return oldChild
1603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeChild(self, oldChild):
1623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
1633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.childNodes.remove(oldChild)
1643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except ValueError:
1653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
1663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if oldChild.nextSibling is not None:
1673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            oldChild.nextSibling.previousSibling = oldChild.previousSibling
1683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if oldChild.previousSibling is not None:
1693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            oldChild.previousSibling.nextSibling = oldChild.nextSibling
1703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        oldChild.nextSibling = oldChild.previousSibling = None
1713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if oldChild.nodeType in _nodeTypes_with_children:
1723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _clear_id_cache(self)
1733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        oldChild.parentNode = None
1753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return oldChild
1763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def normalize(self):
1783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        L = []
1793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for child in self.childNodes:
1803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if child.nodeType == Node.TEXT_NODE:
1813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if not child.data:
1823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    # empty text node; discard
1833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    if L:
1843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        L[-1].nextSibling = child.nextSibling
1853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    if child.nextSibling:
1863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        child.nextSibling.previousSibling = child.previousSibling
1873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    child.unlink()
1883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                elif L and L[-1].nodeType == child.nodeType:
1893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    # collapse text node
1903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    node = L[-1]
1913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    node.data = node.data + child.data
1923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    node.nextSibling = child.nextSibling
1933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    if child.nextSibling:
1943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        child.nextSibling.previousSibling = node
1953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    child.unlink()
1963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                else:
1973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    L.append(child)
1983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
1993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                L.append(child)
2003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if child.nodeType == Node.ELEMENT_NODE:
2013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    child.normalize()
2023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.childNodes[:] = L
2033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def cloneNode(self, deep):
2053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _clone_node(self, deep, self.ownerDocument or self)
2063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def isSupported(self, feature, version):
2083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.ownerDocument.implementation.hasFeature(feature, version)
2093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_localName(self):
2113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # Overridden in Element and Attr where localName can be Non-Null
2123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return None
2133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # Node interfaces from Level 3 (WD 9 April 2002)
2153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def isSameNode(self, other):
2173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self is other
2183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getInterface(self, feature):
2203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.isSupported(feature, None):
2213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self
2223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
2233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
2243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # The "user data" functions use a dictionary that is only present
2263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # if some user data has been set, so be careful not to assume it
2273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # exists.
2283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getUserData(self, key):
2303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
2313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self._user_data[key][0]
2323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except (AttributeError, KeyError):
2333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
2343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setUserData(self, key, data, handler):
2363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        old = None
2373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
2383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d = self._user_data
2393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except AttributeError:
2403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d = {}
2413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self._user_data = d
2423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if key in d:
2433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            old = d[key][0]
2443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if data is None:
2453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # ignore handlers passed for None
2463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            handler = None
2473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if old is not None:
2483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                del d[key]
2493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
2503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d[key] = (data, handler)
2513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return old
2523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _call_user_data_handler(self, operation, src, dst):
2543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if hasattr(self, "_user_data"):
2553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            for key, (data, handler) in self._user_data.items():
2563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if handler is not None:
2573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    handler.handle(operation, key, data, src, dst)
2583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # minidom-specific API:
2603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def unlink(self):
2623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.parentNode = self.ownerDocument = None
2633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.childNodes:
2643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            for child in self.childNodes:
2653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                child.unlink()
2663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.childNodes = NodeList()
2673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.previousSibling = None
2683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.nextSibling = None
2693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Node, "firstChild", doc="First child node, or None.")
2713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Node, "lastChild",  doc="Last child node, or None.")
2723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Node, "localName",  doc="Namespace-local name of this node.")
2733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _append_child(self, node):
2763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # fast path with less checks; usable by DOM builders if careful
2773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    childNodes = self.childNodes
2783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if childNodes:
2793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        last = childNodes[-1]
2803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node.__dict__["previousSibling"] = last
2813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        last.__dict__["nextSibling"] = node
2823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    childNodes.append(node)
2833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    node.__dict__["parentNode"] = self
2843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _in_document(node):
2863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # return True iff node is part of a document tree
2873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    while node is not None:
2883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.nodeType == Node.DOCUMENT_NODE:
2893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return True
2903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node = node.parentNode
2913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    return False
2923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _write_data(writer, data):
2943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    "Writes datachars to writer."
2953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if data:
2963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        data = data.replace("&", "&amp;").replace("<", "&lt;"). \
2973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    replace("\"", "&quot;").replace(">", "&gt;")
2983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        writer.write(data)
2993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _get_elements_by_tagName_helper(parent, name, rc):
3013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    for node in parent.childNodes:
3023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.nodeType == Node.ELEMENT_NODE and \
3033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            (name == "*" or node.tagName == name):
3043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            rc.append(node)
3053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        _get_elements_by_tagName_helper(node, name, rc)
3063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    return rc
3073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
3093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    for node in parent.childNodes:
3103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.nodeType == Node.ELEMENT_NODE:
3113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if ((localName == "*" or node.localName == localName) and
3123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                (nsURI == "*" or node.namespaceURI == nsURI)):
3133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                rc.append(node)
3143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
3153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    return rc
3163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass DocumentFragment(Node):
3183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.DOCUMENT_FRAGMENT_NODE
3193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeName = "#document-fragment"
3203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeValue = None
3213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    attributes = None
3223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    parentNode = None
3233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _child_node_types = (Node.ELEMENT_NODE,
3243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.TEXT_NODE,
3253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.CDATA_SECTION_NODE,
3263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.ENTITY_REFERENCE_NODE,
3273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.PROCESSING_INSTRUCTION_NODE,
3283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.COMMENT_NODE,
3293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.NOTATION_NODE)
3303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self):
3323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.childNodes = NodeList()
3333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Attr(Node):
3363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.ATTRIBUTE_NODE
3373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    attributes = None
3383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    ownerElement = None
3393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    specified = False
3403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _is_id = False
3413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
3433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
3453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 prefix=None):
3463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # skip setattr for performance
3473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d = self.__dict__
3483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d["nodeName"] = d["name"] = qName
3493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d["namespaceURI"] = namespaceURI
3503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d["prefix"] = prefix
3513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['childNodes'] = NodeList()
3523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # Add the single child node that represents the value of the attr
3543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.childNodes.append(Text())
3553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # nodeValue and value are set elsewhere
3573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_localName(self):
3593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.nodeName.split(":", 1)[-1]
3603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_specified(self):
3623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.specified
3633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __setattr__(self, name, value):
3653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d = self.__dict__
3663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if name in ("value", "nodeValue"):
3673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d["value"] = d["nodeValue"] = value
3683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d2 = self.childNodes[0].__dict__
3693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d2["data"] = d2["nodeValue"] = value
3703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if self.ownerElement is not None:
3713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                _clear_id_cache(self.ownerElement)
3723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elif name in ("name", "nodeName"):
3733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d["name"] = d["nodeName"] = value
3743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if self.ownerElement is not None:
3753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                _clear_id_cache(self.ownerElement)
3763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
3773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d[name] = value
3783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _set_prefix(self, prefix):
3803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        nsuri = self.namespaceURI
3813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if prefix == "xmlns":
3823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if nsuri and nsuri != XMLNS_NAMESPACE:
3833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                raise xml.dom.NamespaceErr(
3843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    "illegal use of 'xmlns' prefix for the wrong namespace")
3853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d = self.__dict__
3863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['prefix'] = prefix
3873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if prefix is None:
3883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            newName = self.localName
3893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
3903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            newName = "%s:%s" % (prefix, self.localName)
3913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.ownerElement:
3923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _clear_id_cache(self.ownerElement)
3933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['nodeName'] = d['name'] = newName
3943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
3953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _set_value(self, value):
3963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d = self.__dict__
3973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['value'] = d['nodeValue'] = value
3983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.ownerElement:
3993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _clear_id_cache(self.ownerElement)
4003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.childNodes[0].data = value
4013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def unlink(self):
4033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # This implementation does not call the base implementation
4043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # since most of that is not needed, and the expense of the
4053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # method call is not warranted.  We duplicate the removal of
4063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # children, but that's all we needed from the base class.
4073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elem = self.ownerElement
4083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if elem is not None:
4093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            del elem._attrs[self.nodeName]
4103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            del elem._attrsNS[(self.namespaceURI, self.localName)]
4113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if self._is_id:
4123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self._is_id = False
4133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                elem._magic_id_nodes -= 1
4143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.ownerDocument._magic_id_count -= 1
4153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for child in self.childNodes:
4163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            child.unlink()
4173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        del self.childNodes[:]
4183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_isId(self):
4203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self._is_id:
4213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return True
4223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        doc = self.ownerDocument
4233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elem = self.ownerElement
4243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if doc is None or elem is None:
4253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return False
4263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        info = doc._get_elem_info(elem)
4283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if info is None:
4293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return False
4303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.namespaceURI:
4313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return info.isIdNS(self.namespaceURI, self.localName)
4323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
4333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return info.isId(self.nodeName)
4343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_schemaType(self):
4363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        doc = self.ownerDocument
4373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elem = self.ownerElement
4383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if doc is None or elem is None:
4393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return _no_type
4403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        info = doc._get_elem_info(elem)
4423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if info is None:
4433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return _no_type
4443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.namespaceURI:
4453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return info.getAttributeTypeNS(self.namespaceURI, self.localName)
4463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
4473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return info.getAttributeType(self.nodeName)
4483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Attr, "isId",       doc="True if this attribute is an ID.")
4503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Attr, "localName",  doc="Namespace-local name of this attribute.")
4513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Attr, "schemaType", doc="Schema type for this attribute.")
4523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass NamedNodeMap(object):
4553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """The attribute list is a transient interface to the underlying
4563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    dictionaries.  Mutations here will change the underlying element's
4573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    dictionary.
4583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    Ordering is imposed artificially and does not reflect the order of
4603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    attributes as found in an input document.
4613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """
4623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
4643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, attrs, attrsNS, ownerElement):
4663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._attrs = attrs
4673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._attrsNS = attrsNS
4683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._ownerElement = ownerElement
4693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_length(self):
4713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return len(self._attrs)
4723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def item(self, index):
4743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
4753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self[self._attrs.keys()[index]]
4763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except IndexError:
4773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
4783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def items(self):
4803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        L = []
4813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for node in self._attrs.values():
4823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            L.append((node.nodeName, node.value))
4833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return L
4843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def itemsNS(self):
4863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        L = []
4873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for node in self._attrs.values():
4883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            L.append(((node.namespaceURI, node.localName), node.value))
4893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return L
4903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def has_key(self, key):
4923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if isinstance(key, StringTypes):
4933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return key in self._attrs
4943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
4953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return key in self._attrsNS
4963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
4973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def keys(self):
4983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self._attrs.keys()
4993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def keysNS(self):
5013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self._attrsNS.keys()
5023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def values(self):
5043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self._attrs.values()
5053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def get(self, name, value=None):
5073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self._attrs.get(name, value)
5083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    __len__ = _get_length
5103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    __hash__ = None # Mutable type can't be correctly hashed
5123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __cmp__(self, other):
5133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self._attrs is getattr(other, "_attrs", None):
5143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return 0
5153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
5163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return cmp(id(self), id(other))
5173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __getitem__(self, attname_or_tuple):
5193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if isinstance(attname_or_tuple, tuple):
5203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self._attrsNS[attname_or_tuple]
5213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
5223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self._attrs[attname_or_tuple]
5233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # same as set
5253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __setitem__(self, attname, value):
5263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if isinstance(value, StringTypes):
5273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            try:
5283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                node = self._attrs[attname]
5293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            except KeyError:
5303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                node = Attr(attname)
5313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                node.ownerDocument = self._ownerElement.ownerDocument
5323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.setNamedItem(node)
5333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            node.value = value
5343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
5353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if not isinstance(value, Attr):
5363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                raise TypeError, "value must be a string or Attr object"
5373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            node = value
5383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.setNamedItem(node)
5393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getNamedItem(self, name):
5413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
5423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self._attrs[name]
5433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except KeyError:
5443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
5453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getNamedItemNS(self, namespaceURI, localName):
5473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
5483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self._attrsNS[(namespaceURI, localName)]
5493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except KeyError:
5503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
5513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeNamedItem(self, name):
5533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        n = self.getNamedItem(name)
5543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if n is not None:
5553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _clear_id_cache(self._ownerElement)
5563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            del self._attrs[n.nodeName]
5573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            del self._attrsNS[(n.namespaceURI, n.localName)]
5583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if 'ownerElement' in n.__dict__:
5593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                n.__dict__['ownerElement'] = None
5603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return n
5613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
5623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
5633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeNamedItemNS(self, namespaceURI, localName):
5653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        n = self.getNamedItemNS(namespaceURI, localName)
5663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if n is not None:
5673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _clear_id_cache(self._ownerElement)
5683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            del self._attrsNS[(n.namespaceURI, n.localName)]
5693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            del self._attrs[n.nodeName]
5703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if 'ownerElement' in n.__dict__:
5713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                n.__dict__['ownerElement'] = None
5723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return n
5733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
5743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
5753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setNamedItem(self, node):
5773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if not isinstance(node, Attr):
5783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.HierarchyRequestErr(
5793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "%s cannot be child of %s" % (repr(node), repr(self)))
5803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        old = self._attrs.get(node.name)
5813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if old:
5823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            old.unlink()
5833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._attrs[node.name] = node
5843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._attrsNS[(node.namespaceURI, node.localName)] = node
5853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node.ownerElement = self._ownerElement
5863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        _clear_id_cache(node.ownerElement)
5873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return old
5883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setNamedItemNS(self, node):
5903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.setNamedItem(node)
5913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __delitem__(self, attname_or_tuple):
5933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node = self[attname_or_tuple]
5943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        _clear_id_cache(node.ownerElement)
5953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node.unlink()
5963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
5973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __getstate__(self):
5983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self._attrs, self._attrsNS, self._ownerElement
5993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __setstate__(self, state):
6013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._attrs, self._attrsNS, self._ownerElement = state
6023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(NamedNodeMap, "length",
6043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            doc="Number of nodes in the NamedNodeMap.")
6053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielAttributeList = NamedNodeMap
6073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass TypeInfo(object):
6103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    __slots__ = 'namespace', 'name'
6113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, namespace, name):
6133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.namespace = namespace
6143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.name = name
6153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __repr__(self):
6173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.namespace:
6183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return "<TypeInfo %r (from %r)>" % (self.name, self.namespace)
6193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
6203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return "<TypeInfo %r>" % self.name
6213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_name(self):
6233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.name
6243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_namespace(self):
6263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.namespace
6273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel_no_type = TypeInfo(None, None)
6293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Element(Node):
6313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.ELEMENT_NODE
6323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeValue = None
6333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    schemaType = _no_type
6343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _magic_id_nodes = 0
6363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _child_node_types = (Node.ELEMENT_NODE,
6383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.PROCESSING_INSTRUCTION_NODE,
6393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.COMMENT_NODE,
6403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.TEXT_NODE,
6413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.CDATA_SECTION_NODE,
6423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.ENTITY_REFERENCE_NODE)
6433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
6453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 localName=None):
6463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.tagName = self.nodeName = tagName
6473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.prefix = prefix
6483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.namespaceURI = namespaceURI
6493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.childNodes = NodeList()
6503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._attrs = {}   # attributes are double-indexed:
6523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._attrsNS = {} #    tagName -> Attribute
6533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                           #    URI,localName -> Attribute
6543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                           # in the future: consider lazy generation
6553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                           # of attribute objects this is too tricky
6563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                           # for now because of headaches with
6573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                           # namespaces.
6583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_localName(self):
6603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.tagName.split(":", 1)[-1]
6613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_tagName(self):
6633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.tagName
6643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def unlink(self):
6663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for attr in self._attrs.values():
6673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            attr.unlink()
6683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._attrs = None
6693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._attrsNS = None
6703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        Node.unlink(self)
6713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getAttribute(self, attname):
6733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
6743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self._attrs[attname].value
6753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except KeyError:
6763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return ""
6773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getAttributeNS(self, namespaceURI, localName):
6793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
6803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self._attrsNS[(namespaceURI, localName)].value
6813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except KeyError:
6823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return ""
6833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setAttribute(self, attname, value):
6853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        attr = self.getAttributeNode(attname)
6863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if attr is None:
6873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            attr = Attr(attname)
6883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # for performance
6893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d = attr.__dict__
6903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d["value"] = d["nodeValue"] = value
6913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d["ownerDocument"] = self.ownerDocument
6923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.setAttributeNode(attr)
6933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elif value != attr.value:
6943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d = attr.__dict__
6953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d["value"] = d["nodeValue"] = value
6963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if attr.isId:
6973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                _clear_id_cache(self)
6983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
6993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setAttributeNS(self, namespaceURI, qualifiedName, value):
7003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        prefix, localname = _nssplit(qualifiedName)
7013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        attr = self.getAttributeNodeNS(namespaceURI, localname)
7023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if attr is None:
7033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # for performance
7043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            attr = Attr(qualifiedName, namespaceURI, localname, prefix)
7053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d = attr.__dict__
7063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d["prefix"] = prefix
7073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d["nodeName"] = qualifiedName
7083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d["value"] = d["nodeValue"] = value
7093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d["ownerDocument"] = self.ownerDocument
7103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.setAttributeNode(attr)
7113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
7123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d = attr.__dict__
7133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if value != attr.value:
7143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                d["value"] = d["nodeValue"] = value
7153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if attr.isId:
7163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    _clear_id_cache(self)
7173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if attr.prefix != prefix:
7183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                d["prefix"] = prefix
7193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                d["nodeName"] = qualifiedName
7203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getAttributeNode(self, attrname):
7223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self._attrs.get(attrname)
7233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getAttributeNodeNS(self, namespaceURI, localName):
7253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self._attrsNS.get((namespaceURI, localName))
7263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setAttributeNode(self, attr):
7283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if attr.ownerElement not in (None, self):
7293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.InuseAttributeErr("attribute node already owned")
7303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        old1 = self._attrs.get(attr.name, None)
7313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if old1 is not None:
7323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.removeAttributeNode(old1)
7333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
7343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if old2 is not None and old2 is not old1:
7353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.removeAttributeNode(old2)
7363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        _set_attribute_node(self, attr)
7373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if old1 is not attr:
7393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # It might have already been part of this node, in which case
7403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # it doesn't represent a change, and should not be returned.
7413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return old1
7423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if old2 is not attr:
7433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return old2
7443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    setAttributeNodeNS = setAttributeNode
7463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeAttribute(self, name):
7483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
7493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            attr = self._attrs[name]
7503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except KeyError:
7513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
7523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.removeAttributeNode(attr)
7533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeAttributeNS(self, namespaceURI, localName):
7553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
7563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            attr = self._attrsNS[(namespaceURI, localName)]
7573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except KeyError:
7583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
7593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.removeAttributeNode(attr)
7603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeAttributeNode(self, node):
7623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node is None:
7633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
7643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
7653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self._attrs[node.name]
7663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except KeyError:
7673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
7683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        _clear_id_cache(self)
7693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node.unlink()
7703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # Restore this since the node is still useful and otherwise
7713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # unlinked
7723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node.ownerDocument = self.ownerDocument
7733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    removeAttributeNodeNS = removeAttributeNode
7753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def hasAttribute(self, name):
7773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return name in self._attrs
7783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def hasAttributeNS(self, namespaceURI, localName):
7803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return (namespaceURI, localName) in self._attrsNS
7813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getElementsByTagName(self, name):
7833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _get_elements_by_tagName_helper(self, name, NodeList())
7843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getElementsByTagNameNS(self, namespaceURI, localName):
7863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _get_elements_by_tagName_ns_helper(
7873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self, namespaceURI, localName, NodeList())
7883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __repr__(self):
7903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
7913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def writexml(self, writer, indent="", addindent="", newl=""):
7933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # indent = current indentation
7943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # addindent = indentation to add to higher levels
7953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # newl = newline string
7963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        writer.write(indent+"<" + self.tagName)
7973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
7983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        attrs = self._get_attributes()
7993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        a_names = attrs.keys()
8003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        a_names.sort()
8013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for a_name in a_names:
8033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write(" %s=\"" % a_name)
8043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _write_data(writer, attrs[a_name].value)
8053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write("\"")
8063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.childNodes:
8073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write(">")
8083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if (len(self.childNodes) == 1 and
8093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.childNodes[0].nodeType == Node.TEXT_NODE):
8103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.childNodes[0].writexml(writer, '', '', '')
8113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
8123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                writer.write(newl)
8133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                for node in self.childNodes:
8143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    node.writexml(writer, indent+addindent, addindent, newl)
8153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                writer.write(indent)
8163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write("</%s>%s" % (self.tagName, newl))
8173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
8183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write("/>%s"%(newl))
8193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_attributes(self):
8213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return NamedNodeMap(self._attrs, self._attrsNS, self)
8223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def hasAttributes(self):
8243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self._attrs:
8253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return True
8263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
8273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return False
8283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # DOM Level 3 attributes, based on the 22 Oct 2002 draft
8303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setIdAttribute(self, name):
8323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        idAttr = self.getAttributeNode(name)
8333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.setIdAttributeNode(idAttr)
8343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setIdAttributeNS(self, namespaceURI, localName):
8363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        idAttr = self.getAttributeNodeNS(namespaceURI, localName)
8373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.setIdAttributeNode(idAttr)
8383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setIdAttributeNode(self, idAttr):
8403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if idAttr is None or not self.isSameNode(idAttr.ownerElement):
8413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
8423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if _get_containing_entref(self) is not None:
8433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NoModificationAllowedErr()
8443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if not idAttr._is_id:
8453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            idAttr.__dict__['_is_id'] = True
8463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self._magic_id_nodes += 1
8473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.ownerDocument._magic_id_count += 1
8483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            _clear_id_cache(self)
8493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Element, "attributes",
8513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            doc="NamedNodeMap of attributes on the element.")
8523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Element, "localName",
8533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            doc="Namespace-local name of this element.")
8543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _set_attribute_node(element, attr):
8573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _clear_id_cache(element)
8583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    element._attrs[attr.name] = attr
8593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
8603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # This creates a circular reference, but Element.unlink()
8623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # breaks the cycle since the references to the attribute
8633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # dictionaries are tossed.
8643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    attr.__dict__['ownerElement'] = element
8653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Childless:
8683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """Mixin that makes childless-ness easy to implement and avoids
8693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    the complexity of the Node methods that deal with children.
8703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """
8713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    attributes = None
8733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    childNodes = EmptyNodeList()
8743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    firstChild = None
8753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    lastChild = None
8763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_firstChild(self):
8783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return None
8793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_lastChild(self):
8813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return None
8823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def appendChild(self, node):
8843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.HierarchyRequestErr(
8853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.nodeName + " nodes cannot have children")
8863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def hasChildNodes(self):
8883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return False
8893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def insertBefore(self, newChild, refChild):
8913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.HierarchyRequestErr(
8923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.nodeName + " nodes do not have children")
8933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeChild(self, oldChild):
8953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.NotFoundErr(
8963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.nodeName + " nodes do not have children")
8973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
8983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def normalize(self):
8993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # For childless nodes, normalize() has nothing to do.
9003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        pass
9013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def replaceChild(self, newChild, oldChild):
9033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.HierarchyRequestErr(
9043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.nodeName + " nodes do not have children")
9053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass ProcessingInstruction(Childless, Node):
9083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.PROCESSING_INSTRUCTION_NODE
9093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, target, data):
9113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.target = self.nodeName = target
9123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.data = self.nodeValue = data
9133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_data(self):
9153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.data
9163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _set_data(self, value):
9173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d = self.__dict__
9183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['data'] = d['nodeValue'] = value
9193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_target(self):
9213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.target
9223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _set_target(self, value):
9233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d = self.__dict__
9243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['target'] = d['nodeName'] = value
9253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __setattr__(self, name, value):
9273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if name == "data" or name == "nodeValue":
9283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.__dict__['data'] = self.__dict__['nodeValue'] = value
9293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elif name == "target" or name == "nodeName":
9303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.__dict__['target'] = self.__dict__['nodeName'] = value
9313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
9323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.__dict__[name] = value
9333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def writexml(self, writer, indent="", addindent="", newl=""):
9353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
9363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass CharacterData(Childless, Node):
9393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_length(self):
9403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return len(self.data)
9413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    __len__ = _get_length
9423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_data(self):
9443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.__dict__['data']
9453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _set_data(self, data):
9463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d = self.__dict__
9473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['data'] = d['nodeValue'] = data
9483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _get_nodeValue = _get_data
9503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _set_nodeValue = _set_data
9513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __setattr__(self, name, value):
9533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if name == "data" or name == "nodeValue":
9543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.__dict__['data'] = self.__dict__['nodeValue'] = value
9553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
9563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.__dict__[name] = value
9573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __repr__(self):
9593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        data = self.data
9603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if len(data) > 10:
9613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            dotdotdot = "..."
9623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
9633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            dotdotdot = ""
9643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return '<DOM %s node "%r%s">' % (
9653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.__class__.__name__, data[0:10], dotdotdot)
9663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def substringData(self, offset, count):
9683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if offset < 0:
9693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("offset cannot be negative")
9703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if offset >= len(self.data):
9713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
9723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if count < 0:
9733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("count cannot be negative")
9743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.data[offset:offset+count]
9753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def appendData(self, arg):
9773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.data = self.data + arg
9783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def insertData(self, offset, arg):
9803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if offset < 0:
9813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("offset cannot be negative")
9823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if offset >= len(self.data):
9833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
9843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if arg:
9853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.data = "%s%s%s" % (
9863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.data[:offset], arg, self.data[offset:])
9873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def deleteData(self, offset, count):
9893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if offset < 0:
9903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("offset cannot be negative")
9913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if offset >= len(self.data):
9923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
9933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if count < 0:
9943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("count cannot be negative")
9953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if count:
9963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.data = self.data[:offset] + self.data[offset+count:]
9973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
9983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def replaceData(self, offset, count, arg):
9993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if offset < 0:
10003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("offset cannot be negative")
10013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if offset >= len(self.data):
10023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
10033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if count < 0:
10043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("count cannot be negative")
10053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if count:
10063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.data = "%s%s%s" % (
10073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.data[:offset], arg, self.data[offset+count:])
10083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(CharacterData, "length", doc="Length of the string data.")
10103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Text(CharacterData):
10133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # Make sure we don't add an instance __dict__ if we don't already
10143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # have one, at least when that's possible:
10153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # XXX this does not work, CharacterData is an old-style class
10163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # __slots__ = ()
10173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.TEXT_NODE
10193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeName = "#text"
10203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    attributes = None
10213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def splitText(self, offset):
10233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if offset < 0 or offset > len(self.data):
10243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.IndexSizeErr("illegal offset value")
10253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        newText = self.__class__()
10263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        newText.data = self.data[offset:]
10273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        newText.ownerDocument = self.ownerDocument
10283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        next = self.nextSibling
10293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.parentNode and self in self.parentNode.childNodes:
10303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if next is None:
10313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.parentNode.appendChild(newText)
10323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
10333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.parentNode.insertBefore(newText, next)
10343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.data = self.data[:offset]
10353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return newText
10363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def writexml(self, writer, indent="", addindent="", newl=""):
10383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        _write_data(writer, "%s%s%s" % (indent, self.data, newl))
10393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # DOM Level 3 (WD 9 April 2002)
10413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_wholeText(self):
10433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        L = [self.data]
10443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        n = self.previousSibling
10453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        while n is not None:
10463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
10473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                L.insert(0, n.data)
10483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                n = n.previousSibling
10493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
10503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                break
10513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        n = self.nextSibling
10523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        while n is not None:
10533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
10543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                L.append(n.data)
10553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                n = n.nextSibling
10563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
10573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                break
10583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return ''.join(L)
10593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def replaceWholeText(self, content):
10613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # XXX This needs to be seriously changed if minidom ever
10623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # supports EntityReference nodes.
10633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        parent = self.parentNode
10643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        n = self.previousSibling
10653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        while n is not None:
10663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
10673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                next = n.previousSibling
10683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                parent.removeChild(n)
10693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                n = next
10703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
10713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                break
10723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        n = self.nextSibling
10733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if not content:
10743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            parent.removeChild(self)
10753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        while n is not None:
10763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
10773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                next = n.nextSibling
10783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                parent.removeChild(n)
10793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                n = next
10803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
10813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                break
10823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if content:
10833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d = self.__dict__
10843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d['data'] = content
10853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d['nodeValue'] = content
10863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self
10873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
10883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
10893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
10903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_isWhitespaceInElementContent(self):
10913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.data.strip():
10923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return False
10933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elem = _get_containing_element(self)
10943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if elem is None:
10953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return False
10963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        info = self.ownerDocument._get_elem_info(elem)
10973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if info is None:
10983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return False
10993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
11003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return info.isElementContent()
11013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Text, "isWhitespaceInElementContent",
11033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            doc="True iff this text node contains only whitespace"
11043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                " and is in element content.")
11053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Text, "wholeText",
11063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            doc="The text of all logically-adjacent text nodes.")
11073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _get_containing_element(node):
11103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    c = node.parentNode
11113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    while c is not None:
11123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if c.nodeType == Node.ELEMENT_NODE:
11133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return c
11143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        c = c.parentNode
11153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    return None
11163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _get_containing_entref(node):
11183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    c = node.parentNode
11193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    while c is not None:
11203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if c.nodeType == Node.ENTITY_REFERENCE_NODE:
11213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return c
11223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        c = c.parentNode
11233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    return None
11243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Comment(Childless, CharacterData):
11273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.COMMENT_NODE
11283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeName = "#comment"
11293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, data):
11313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.data = self.nodeValue = data
11323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def writexml(self, writer, indent="", addindent="", newl=""):
11343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if "--" in self.data:
11353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise ValueError("'--' is not allowed in a comment node")
11363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
11373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass CDATASection(Text):
11403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # Make sure we don't add an instance __dict__ if we don't already
11413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # have one, at least when that's possible:
11423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # XXX this does not work, Text is an old-style class
11433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # __slots__ = ()
11443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.CDATA_SECTION_NODE
11463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeName = "#cdata-section"
11473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def writexml(self, writer, indent="", addindent="", newl=""):
11493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.data.find("]]>") >= 0:
11503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise ValueError("']]>' not allowed in a CDATA section")
11513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        writer.write("<![CDATA[%s]]>" % self.data)
11523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass ReadOnlySequentialNamedNodeMap(object):
11553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    __slots__ = '_seq',
11563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, seq=()):
11583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # seq should be a list or tuple
11593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._seq = seq
11603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __len__(self):
11623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return len(self._seq)
11633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_length(self):
11653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return len(self._seq)
11663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getNamedItem(self, name):
11683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for n in self._seq:
11693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if n.nodeName == name:
11703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                return n
11713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getNamedItemNS(self, namespaceURI, localName):
11733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for n in self._seq:
11743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if n.namespaceURI == namespaceURI and n.localName == localName:
11753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                return n
11763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __getitem__(self, name_or_tuple):
11783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if isinstance(name_or_tuple, tuple):
11793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            node = self.getNamedItemNS(*name_or_tuple)
11803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
11813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            node = self.getNamedItem(name_or_tuple)
11823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node is None:
11833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise KeyError, name_or_tuple
11843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return node
11853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def item(self, index):
11873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if index < 0:
11883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
11893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
11903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self._seq[index]
11913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except IndexError:
11923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
11933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeNamedItem(self, name):
11953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.NoModificationAllowedErr(
11963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            "NamedNodeMap instance is read-only")
11973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
11983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeNamedItemNS(self, namespaceURI, localName):
11993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.NoModificationAllowedErr(
12003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            "NamedNodeMap instance is read-only")
12013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setNamedItem(self, node):
12033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.NoModificationAllowedErr(
12043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            "NamedNodeMap instance is read-only")
12053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def setNamedItemNS(self, node):
12073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.NoModificationAllowedErr(
12083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            "NamedNodeMap instance is read-only")
12093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __getstate__(self):
12113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return [self._seq]
12123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __setstate__(self, state):
12143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._seq = state[0]
12153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(ReadOnlySequentialNamedNodeMap, "length",
12173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            doc="Number of entries in the NamedNodeMap.")
12183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Identified:
12213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """Mix-in class that supports the publicId and systemId attributes."""
12223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # XXX this does not work, this is an old-style class
12243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # __slots__ = 'publicId', 'systemId'
12253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _identified_mixin_init(self, publicId, systemId):
12273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.publicId = publicId
12283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.systemId = systemId
12293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_publicId(self):
12313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.publicId
12323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_systemId(self):
12343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.systemId
12353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass DocumentType(Identified, Childless, Node):
12373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.DOCUMENT_TYPE_NODE
12383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeValue = None
12393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    name = None
12403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    publicId = None
12413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    systemId = None
12423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    internalSubset = None
12433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, qualifiedName):
12453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.entities = ReadOnlySequentialNamedNodeMap()
12463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.notations = ReadOnlySequentialNamedNodeMap()
12473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if qualifiedName:
12483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            prefix, localname = _nssplit(qualifiedName)
12493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.name = localname
12503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.nodeName = self.name
12513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_internalSubset(self):
12533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.internalSubset
12543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def cloneNode(self, deep):
12563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.ownerDocument is None:
12573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # it's ok
12583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            clone = DocumentType(None)
12593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            clone.name = self.name
12603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            clone.nodeName = self.name
12613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            operation = xml.dom.UserDataHandler.NODE_CLONED
12623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if deep:
12633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                clone.entities._seq = []
12643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                clone.notations._seq = []
12653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                for n in self.notations._seq:
12663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    notation = Notation(n.nodeName, n.publicId, n.systemId)
12673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    clone.notations._seq.append(notation)
12683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    n._call_user_data_handler(operation, n, notation)
12693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                for e in self.entities._seq:
12703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    entity = Entity(e.nodeName, e.publicId, e.systemId,
12713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                    e.notationName)
12723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    entity.actualEncoding = e.actualEncoding
12733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    entity.encoding = e.encoding
12743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    entity.version = e.version
12753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    clone.entities._seq.append(entity)
12763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    e._call_user_data_handler(operation, n, entity)
12773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self._call_user_data_handler(operation, self, clone)
12783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return clone
12793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
12803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
12813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def writexml(self, writer, indent="", addindent="", newl=""):
12833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        writer.write("<!DOCTYPE ")
12843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        writer.write(self.name)
12853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.publicId:
12863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write("%s  PUBLIC '%s'%s  '%s'"
12873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         % (newl, self.publicId, newl, self.systemId))
12883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elif self.systemId:
12893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write("%s  SYSTEM '%s'" % (newl, self.systemId))
12903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.internalSubset is not None:
12913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write(" [")
12923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write(self.internalSubset)
12933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write("]")
12943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        writer.write(">"+newl)
12953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
12963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Entity(Identified, Node):
12973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    attributes = None
12983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.ENTITY_NODE
12993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeValue = None
13003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    actualEncoding = None
13023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    encoding = None
13033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    version = None
13043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, name, publicId, systemId, notation):
13063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.nodeName = name
13073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.notationName = notation
13083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.childNodes = NodeList()
13093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._identified_mixin_init(publicId, systemId)
13103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_actualEncoding(self):
13123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.actualEncoding
13133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_encoding(self):
13153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.encoding
13163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_version(self):
13183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.version
13193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def appendChild(self, newChild):
13213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.HierarchyRequestErr(
13223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            "cannot append children to an entity node")
13233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def insertBefore(self, newChild, refChild):
13253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.HierarchyRequestErr(
13263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            "cannot insert children below an entity node")
13273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeChild(self, oldChild):
13293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.HierarchyRequestErr(
13303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            "cannot remove children from an entity node")
13313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def replaceChild(self, newChild, oldChild):
13333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.HierarchyRequestErr(
13343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            "cannot replace children of an entity node")
13353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Notation(Identified, Childless, Node):
13373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.NOTATION_NODE
13383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeValue = None
13393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, name, publicId, systemId):
13413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.nodeName = name
13423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._identified_mixin_init(publicId, systemId)
13433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass DOMImplementation(DOMImplementationLS):
13463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _features = [("core", "1.0"),
13473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 ("core", "2.0"),
13483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 ("core", None),
13493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 ("xml", "1.0"),
13503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 ("xml", "2.0"),
13513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 ("xml", None),
13523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 ("ls-load", "3.0"),
13533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 ("ls-load", None),
13543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 ]
13553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def hasFeature(self, feature, version):
13573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if version == "":
13583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            version = None
13593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return (feature.lower(), version) in self._features
13603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createDocument(self, namespaceURI, qualifiedName, doctype):
13623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if doctype and doctype.parentNode is not None:
13633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.WrongDocumentErr(
13643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "doctype object owned by another DOM tree")
13653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        doc = self._create_document()
13663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        add_root_element = not (namespaceURI is None
13683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                and qualifiedName is None
13693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                and doctype is None)
13703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if not qualifiedName and add_root_element:
13723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # The spec is unclear what to raise here; SyntaxErr
13733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # would be the other obvious candidate. Since Xerces raises
13743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # InvalidCharacterErr, and since SyntaxErr is not listed
13753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # for createDocument, that seems to be the better choice.
13763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # XXX: need to check for illegal characters here and in
13773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # createElement.
13783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # DOM Level III clears this up when talking about the return value
13803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # of this function.  If namespaceURI, qName and DocType are
13813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # Null the document is returned without a document element
13823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # Otherwise if doctype or namespaceURI are not None
13833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # Then we go back to the above problem
13843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.InvalidCharacterErr("Element with no name")
13853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if add_root_element:
13873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            prefix, localname = _nssplit(qualifiedName)
13883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if prefix == "xml" \
13893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel               and namespaceURI != "http://www.w3.org/XML/1998/namespace":
13903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
13913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if prefix and not namespaceURI:
13923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                raise xml.dom.NamespaceErr(
13933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    "illegal use of prefix without namespaces")
13943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            element = doc.createElementNS(namespaceURI, qualifiedName)
13953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if doctype:
13963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                doc.appendChild(doctype)
13973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            doc.appendChild(element)
13983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
13993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if doctype:
14003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            doctype.parentNode = doctype.ownerDocument = doc
14013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        doc.doctype = doctype
14033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        doc.implementation = self
14043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return doc
14053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createDocumentType(self, qualifiedName, publicId, systemId):
14073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        doctype = DocumentType(qualifiedName)
14083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        doctype.publicId = publicId
14093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        doctype.systemId = systemId
14103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return doctype
14113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # DOM Level 3 (WD 9 April 2002)
14133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getInterface(self, feature):
14153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.hasFeature(feature, None):
14163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self
14173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
14183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
14193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # internal
14213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _create_document(self):
14223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return Document()
14233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass ElementInfo(object):
14253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """Object that represents content-model information for an element.
14263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    This implementation is not expected to be used in practice; DOM
14283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    builders should provide implementations which do the right thing
14293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    using information available to it.
14303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """
14323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    __slots__ = 'tagName',
14343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self, name):
14363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.tagName = name
14373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getAttributeType(self, aname):
14393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _no_type
14403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getAttributeTypeNS(self, namespaceURI, localName):
14423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _no_type
14433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def isElementContent(self):
14453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return False
14463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def isEmpty(self):
14483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Returns true iff this element is declared to have an EMPTY
14493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        content model."""
14503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return False
14513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def isId(self, aname):
14533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Returns true iff the named attribute is a DTD-style ID."""
14543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return False
14553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def isIdNS(self, namespaceURI, localName):
14573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Returns true iff the identified attribute is a DTD-style ID."""
14583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return False
14593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __getstate__(self):
14613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.tagName
14623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __setstate__(self, state):
14643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.tagName = state
14653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _clear_id_cache(node):
14673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if node.nodeType == Node.DOCUMENT_NODE:
14683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node._id_cache.clear()
14693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node._id_search_stack = None
14703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    elif _in_document(node):
14713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node.ownerDocument._id_cache.clear()
14723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node.ownerDocument._id_search_stack= None
14733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Document(Node, DocumentLS):
14753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
14763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                         Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
14773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeType = Node.DOCUMENT_NODE
14793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeName = "#document"
14803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    nodeValue = None
14813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    attributes = None
14823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    doctype = None
14833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    parentNode = None
14843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    previousSibling = nextSibling = None
14853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    implementation = DOMImplementation()
14873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # Document attributes from Level 3 (WD 9 April 2002)
14893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    actualEncoding = None
14913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    encoding = None
14923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    standalone = None
14933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    version = None
14943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    strictErrorChecking = False
14953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    errorHandler = None
14963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    documentURI = None
14973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
14983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    _magic_id_count = 0
14993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def __init__(self):
15013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.childNodes = NodeList()
15023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # mapping of (namespaceURI, localName) -> ElementInfo
15033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        #        and tagName -> ElementInfo
15043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._elem_info = {}
15053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._id_cache = {}
15063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._id_search_stack = None
15073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_elem_info(self, element):
15093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if element.namespaceURI:
15103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            key = element.namespaceURI, element.localName
15113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
15123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            key = element.tagName
15133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self._elem_info.get(key)
15143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_actualEncoding(self):
15163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.actualEncoding
15173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_doctype(self):
15193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.doctype
15203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_documentURI(self):
15223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.documentURI
15233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_encoding(self):
15253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.encoding
15263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_errorHandler(self):
15283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.errorHandler
15293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_standalone(self):
15313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.standalone
15323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_strictErrorChecking(self):
15343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.strictErrorChecking
15353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_version(self):
15373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.version
15383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def appendChild(self, node):
15403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.nodeType not in self._child_node_types:
15413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.HierarchyRequestErr(
15423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "%s cannot be child of %s" % (repr(node), repr(self)))
15433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.parentNode is not None:
15443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # This needs to be done before the next test since this
15453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # may *be* the document element, in which case it should
15463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # end up re-ordered to the end.
15473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            node.parentNode.removeChild(node)
15483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.nodeType == Node.ELEMENT_NODE \
15503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel           and self._get_documentElement():
15513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.HierarchyRequestErr(
15523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "two document elements disallowed")
15533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return Node.appendChild(self, node)
15543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def removeChild(self, oldChild):
15563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
15573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.childNodes.remove(oldChild)
15583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except ValueError:
15593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotFoundErr()
15603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        oldChild.nextSibling = oldChild.previousSibling = None
15613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        oldChild.parentNode = None
15623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.documentElement is oldChild:
15633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.documentElement = None
15643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return oldChild
15663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _get_documentElement(self):
15683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for node in self.childNodes:
15693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if node.nodeType == Node.ELEMENT_NODE:
15703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                return node
15713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def unlink(self):
15733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if self.doctype is not None:
15743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.doctype.unlink()
15753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.doctype = None
15763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        Node.unlink(self)
15773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def cloneNode(self, deep):
15793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if not deep:
15803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
15813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone = self.implementation.createDocument(None, None, None)
15823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone.encoding = self.encoding
15833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone.standalone = self.standalone
15843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone.version = self.version
15853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for n in self.childNodes:
15863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            childclone = _clone_node(n, deep, clone)
15873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            assert childclone.ownerDocument.isSameNode(clone)
15883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            clone.childNodes.append(childclone)
15893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if childclone.nodeType == Node.DOCUMENT_NODE:
15903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                assert clone.documentElement is None
15913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
15923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                assert clone.doctype is None
15933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                clone.doctype = childclone
15943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            childclone.parentNode = clone
15953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
15963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                     self, clone)
15973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return clone
15983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
15993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createDocumentFragment(self):
16003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d = DocumentFragment()
16013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d.ownerDocument = self
16023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return d
16033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createElement(self, tagName):
16053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        e = Element(tagName)
16063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        e.ownerDocument = self
16073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return e
16083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createTextNode(self, data):
16103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if not isinstance(data, StringTypes):
16113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise TypeError, "node contents must be a string"
16123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        t = Text()
16133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        t.data = data
16143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        t.ownerDocument = self
16153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return t
16163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createCDATASection(self, data):
16183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if not isinstance(data, StringTypes):
16193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise TypeError, "node contents must be a string"
16203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        c = CDATASection()
16213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        c.data = data
16223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        c.ownerDocument = self
16233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return c
16243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createComment(self, data):
16263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        c = Comment(data)
16273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        c.ownerDocument = self
16283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return c
16293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createProcessingInstruction(self, target, data):
16313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        p = ProcessingInstruction(target, data)
16323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        p.ownerDocument = self
16333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return p
16343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createAttribute(self, qName):
16363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        a = Attr(qName)
16373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        a.ownerDocument = self
16383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        a.value = ""
16393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return a
16403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createElementNS(self, namespaceURI, qualifiedName):
16423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        prefix, localName = _nssplit(qualifiedName)
16433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        e = Element(qualifiedName, namespaceURI, prefix)
16443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        e.ownerDocument = self
16453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return e
16463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def createAttributeNS(self, namespaceURI, qualifiedName):
16483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        prefix, localName = _nssplit(qualifiedName)
16493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        a = Attr(qualifiedName, namespaceURI, localName, prefix)
16503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        a.ownerDocument = self
16513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        a.value = ""
16523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return a
16533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # A couple of implementation-specific helpers to create node types
16553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # not supported by the W3C DOM specs:
16563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _create_entity(self, name, publicId, systemId, notationName):
16583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        e = Entity(name, publicId, systemId, notationName)
16593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        e.ownerDocument = self
16603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return e
16613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def _create_notation(self, name, publicId, systemId):
16633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        n = Notation(name, publicId, systemId)
16643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        n.ownerDocument = self
16653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return n
16663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getElementById(self, id):
16683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if id in self._id_cache:
16693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self._id_cache[id]
16703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if not (self._elem_info or self._magic_id_count):
16713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
16723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        stack = self._id_search_stack
16743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if stack is None:
16753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # we never searched before, or the cache has been cleared
16763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            stack = [self.documentElement]
16773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self._id_search_stack = stack
16783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elif not stack:
16793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # Previous search was completed and cache is still valid;
16803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # no matching node.
16813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
16823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
16833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        result = None
16843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        while stack:
16853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            node = stack.pop()
16863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # add child elements to stack for continued searching
16873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            stack.extend([child for child in node.childNodes
16883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                          if child.nodeType in _nodeTypes_with_children])
16893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # check this node
16903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            info = self._get_elem_info(node)
16913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if info:
16923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                # We have to process all ID attributes before
16933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                # returning in order to get all the attributes set to
16943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                # be IDs using Element.setIdAttribute*().
16953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                for attr in node.attributes.values():
16963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    if attr.namespaceURI:
16973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        if info.isIdNS(attr.namespaceURI, attr.localName):
16983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                            self._id_cache[attr.value] = node
16993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                            if attr.value == id:
17003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                result = node
17013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                            elif not node._magic_id_nodes:
17023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                break
17033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    elif info.isId(attr.name):
17043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        self._id_cache[attr.value] = node
17053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        if attr.value == id:
17063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                            result = node
17073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        elif not node._magic_id_nodes:
17083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                            break
17093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    elif attr._is_id:
17103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        self._id_cache[attr.value] = node
17113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        if attr.value == id:
17123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                            result = node
17133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        elif node._magic_id_nodes == 1:
17143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                            break
17153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            elif node._magic_id_nodes:
17163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                for attr in node.attributes.values():
17173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    if attr._is_id:
17183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        self._id_cache[attr.value] = node
17193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        if attr.value == id:
17203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                            result = node
17213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if result is not None:
17223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                break
17233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return result
17243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
17253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getElementsByTagName(self, name):
17263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _get_elements_by_tagName_helper(self, name, NodeList())
17273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
17283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def getElementsByTagNameNS(self, namespaceURI, localName):
17293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _get_elements_by_tagName_ns_helper(
17303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self, namespaceURI, localName, NodeList())
17313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
17323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def isSupported(self, feature, version):
17333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return self.implementation.hasFeature(feature, version)
17343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
17353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def importNode(self, node, deep):
17363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if node.nodeType == Node.DOCUMENT_NODE:
17373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotSupportedErr("cannot import document nodes")
17383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
17393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotSupportedErr("cannot import document type nodes")
17403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _clone_node(node, deep, self)
17413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
17423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def writexml(self, writer, indent="", addindent="", newl="",
17433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                 encoding = None):
17443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if encoding is None:
17453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write('<?xml version="1.0" ?>'+newl)
17463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
17473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            writer.write('<?xml version="1.0" encoding="%s"?>%s' % (encoding, newl))
17483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for node in self.childNodes:
17493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            node.writexml(writer, indent, addindent, newl)
17503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
17513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # DOM Level 3 (WD 9 April 2002)
17523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
17533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def renameNode(self, n, namespaceURI, name):
17543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if n.ownerDocument is not self:
17553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.WrongDocumentErr(
17563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "cannot rename nodes from other documents;\n"
17573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "expected %s,\nfound %s" % (self, n.ownerDocument))
17583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
17593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise xml.dom.NotSupportedErr(
17603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                "renameNode() only applies to element and attribute nodes")
17613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if namespaceURI != EMPTY_NAMESPACE:
17623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if ':' in name:
17633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                prefix, localName = name.split(':', 1)
17643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if (  prefix == "xmlns"
17653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                      and namespaceURI != xml.dom.XMLNS_NAMESPACE):
17663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    raise xml.dom.NamespaceErr(
17673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        "illegal use of 'xmlns' prefix")
17683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
17693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if (  name == "xmlns"
17703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                      and namespaceURI != xml.dom.XMLNS_NAMESPACE
17713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                      and n.nodeType == Node.ATTRIBUTE_NODE):
17723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    raise xml.dom.NamespaceErr(
17733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                        "illegal use of the 'xmlns' attribute")
17743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                prefix = None
17753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                localName = name
17763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
17773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            prefix = None
17783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            localName = None
17793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if n.nodeType == Node.ATTRIBUTE_NODE:
17803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            element = n.ownerElement
17813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if element is not None:
17823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                is_id = n._is_id
17833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                element.removeAttributeNode(n)
17843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
17853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            element = None
17863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # avoid __setattr__
17873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d = n.__dict__
17883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['prefix'] = prefix
17893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['localName'] = localName
17903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['namespaceURI'] = namespaceURI
17913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        d['nodeName'] = name
17923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if n.nodeType == Node.ELEMENT_NODE:
17933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d['tagName'] = name
17943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
17953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # attribute node
17963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            d['name'] = name
17973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if element is not None:
17983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                element.setAttributeNode(n)
17993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if is_id:
18003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    element.setIdAttributeNode(n)
18013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # It's not clear from a semantic perspective whether we should
18023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # call the user data handlers for the NODE_RENAMED event since
18033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # we're re-using the existing node.  The draft spec has been
18043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # interpreted as meaning "no, don't call the handler unless a
18053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # new node is created."
18063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return n
18073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
18083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefproperty(Document, "documentElement",
18093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            doc="Top-level element of this document.")
18103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
18113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
18123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _clone_node(node, deep, newOwnerDocument):
18133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """
18143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    Clone a node and give it the new owner document.
18153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    Called by Node.cloneNode and Document.importNode
18163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """
18173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if node.ownerDocument.isSameNode(newOwnerDocument):
18183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        operation = xml.dom.UserDataHandler.NODE_CLONED
18193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    else:
18203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        operation = xml.dom.UserDataHandler.NODE_IMPORTED
18213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if node.nodeType == Node.ELEMENT_NODE:
18223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone = newOwnerDocument.createElementNS(node.namespaceURI,
18233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                                 node.nodeName)
18243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for attr in node.attributes.values():
18253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
18263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
18273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            a.specified = attr.specified
18283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
18293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if deep:
18303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            for child in node.childNodes:
18313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                c = _clone_node(child, deep, newOwnerDocument)
18323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                clone.appendChild(c)
18333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
18343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
18353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone = newOwnerDocument.createDocumentFragment()
18363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if deep:
18373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            for child in node.childNodes:
18383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                c = _clone_node(child, deep, newOwnerDocument)
18393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                clone.appendChild(c)
18403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
18413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    elif node.nodeType == Node.TEXT_NODE:
18423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone = newOwnerDocument.createTextNode(node.data)
18433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    elif node.nodeType == Node.CDATA_SECTION_NODE:
18443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone = newOwnerDocument.createCDATASection(node.data)
18453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
18463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone = newOwnerDocument.createProcessingInstruction(node.target,
18473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                                             node.data)
18483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    elif node.nodeType == Node.COMMENT_NODE:
18493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone = newOwnerDocument.createComment(node.data)
18503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    elif node.nodeType == Node.ATTRIBUTE_NODE:
18513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
18523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                                   node.nodeName)
18533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone.specified = True
18543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone.value = node.value
18553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
18563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        assert node.ownerDocument is not newOwnerDocument
18573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        operation = xml.dom.UserDataHandler.NODE_IMPORTED
18583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone = newOwnerDocument.implementation.createDocumentType(
18593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            node.name, node.publicId, node.systemId)
18603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        clone.ownerDocument = newOwnerDocument
18613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if deep:
18623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            clone.entities._seq = []
18633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            clone.notations._seq = []
18643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            for n in node.notations._seq:
18653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                notation = Notation(n.nodeName, n.publicId, n.systemId)
18663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                notation.ownerDocument = newOwnerDocument
18673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                clone.notations._seq.append(notation)
18683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if hasattr(n, '_call_user_data_handler'):
18693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    n._call_user_data_handler(operation, n, notation)
18703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            for e in node.entities._seq:
18713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                entity = Entity(e.nodeName, e.publicId, e.systemId,
18723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                e.notationName)
18733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                entity.actualEncoding = e.actualEncoding
18743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                entity.encoding = e.encoding
18753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                entity.version = e.version
18763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                entity.ownerDocument = newOwnerDocument
18773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                clone.entities._seq.append(entity)
18783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if hasattr(e, '_call_user_data_handler'):
18793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    e._call_user_data_handler(operation, n, entity)
18803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    else:
18813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # Note the cloning of Document and DocumentType nodes is
18823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # implementation specific.  minidom handles those cases
18833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # directly in the cloneNode() methods.
18843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
18853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
18863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # Check for _call_user_data_handler() since this could conceivably
18873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # used with other DOM implementations (one of the FourThought
18883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # DOMs, perhaps?).
18893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if hasattr(node, '_call_user_data_handler'):
18903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        node._call_user_data_handler(operation, node, clone)
18913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    return clone
18923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
18933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
18943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _nssplit(qualifiedName):
18953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    fields = qualifiedName.split(':', 1)
18963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if len(fields) == 2:
18973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return fields
18983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    else:
18993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return (None, fields[0])
19003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
19013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
19023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _get_StringIO():
19033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    # we can't use cStringIO since it doesn't support Unicode strings
19043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    from StringIO import StringIO
19053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    return StringIO()
19063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
19073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _do_pulldom_parse(func, args, kwargs):
19083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    events = func(*args, **kwargs)
19093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    toktype, rootNode = events.getEvent()
19103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    events.expandNode(rootNode)
19113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    events.clear()
19123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    return rootNode
19133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
19143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef parse(file, parser=None, bufsize=None):
19153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """Parse a file into a DOM by filename or file object."""
19163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if parser is None and not bufsize:
19173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        from xml.dom import expatbuilder
19183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return expatbuilder.parse(file)
19193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    else:
19203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        from xml.dom import pulldom
19213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _do_pulldom_parse(pulldom.parse, (file,),
19223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            {'parser': parser, 'bufsize': bufsize})
19233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
19243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef parseString(string, parser=None):
19253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """Parse a file into a DOM from a string."""
19263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if parser is None:
19273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        from xml.dom import expatbuilder
19283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return expatbuilder.parseString(string)
19293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    else:
19303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        from xml.dom import pulldom
19313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return _do_pulldom_parse(pulldom.parseString, (string,),
19323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                                 {'parser': parser})
19333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
19343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef getDOMImplementation(features=None):
19353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if features:
19363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if isinstance(features, StringTypes):
19373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            features = domreg._parse_feature_string(features)
19383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for f, v in features:
19393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if not Document.implementation.hasFeature(f, v):
19403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                return None
19413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    return Document.implementation
1942