17db96d56Sopenharmony_ci"""Simple implementation of the Level 1 DOM.
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciNamespaces and other minor Level 2 features are also supported.
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ciparse("foo.xml")
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ciparseString("<foo><bar/></foo>")
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ciTodo:
107db96d56Sopenharmony_ci=====
117db96d56Sopenharmony_ci * convenience methods for getting elements and text.
127db96d56Sopenharmony_ci * more testing
137db96d56Sopenharmony_ci * bring some of the writer and linearizer code into conformance with this
147db96d56Sopenharmony_ci        interface
157db96d56Sopenharmony_ci * SAX 2 namespaces
167db96d56Sopenharmony_ci"""
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ciimport io
197db96d56Sopenharmony_ciimport xml.dom
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_cifrom xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
227db96d56Sopenharmony_cifrom xml.dom.minicompat import *
237db96d56Sopenharmony_cifrom xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci# This is used by the ID-cache invalidation checks; the list isn't
267db96d56Sopenharmony_ci# actually complete, since the nodes being checked will never be the
277db96d56Sopenharmony_ci# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE.  (The node being checked is
287db96d56Sopenharmony_ci# the node being added or removed, not the node being modified.)
297db96d56Sopenharmony_ci#
307db96d56Sopenharmony_ci_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE,
317db96d56Sopenharmony_ci                            xml.dom.Node.ENTITY_REFERENCE_NODE)
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ciclass Node(xml.dom.Node):
357db96d56Sopenharmony_ci    namespaceURI = None # this is non-null only for elements and attributes
367db96d56Sopenharmony_ci    parentNode = None
377db96d56Sopenharmony_ci    ownerDocument = None
387db96d56Sopenharmony_ci    nextSibling = None
397db96d56Sopenharmony_ci    previousSibling = None
407db96d56Sopenharmony_ci
417db96d56Sopenharmony_ci    prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ci    def __bool__(self):
447db96d56Sopenharmony_ci        return True
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ci    def toxml(self, encoding=None, standalone=None):
477db96d56Sopenharmony_ci        return self.toprettyxml("", "", encoding, standalone)
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci    def toprettyxml(self, indent="\t", newl="\n", encoding=None,
507db96d56Sopenharmony_ci                    standalone=None):
517db96d56Sopenharmony_ci        if encoding is None:
527db96d56Sopenharmony_ci            writer = io.StringIO()
537db96d56Sopenharmony_ci        else:
547db96d56Sopenharmony_ci            writer = io.TextIOWrapper(io.BytesIO(),
557db96d56Sopenharmony_ci                                      encoding=encoding,
567db96d56Sopenharmony_ci                                      errors="xmlcharrefreplace",
577db96d56Sopenharmony_ci                                      newline='\n')
587db96d56Sopenharmony_ci        if self.nodeType == Node.DOCUMENT_NODE:
597db96d56Sopenharmony_ci            # Can pass encoding only to document, to put it into XML header
607db96d56Sopenharmony_ci            self.writexml(writer, "", indent, newl, encoding, standalone)
617db96d56Sopenharmony_ci        else:
627db96d56Sopenharmony_ci            self.writexml(writer, "", indent, newl)
637db96d56Sopenharmony_ci        if encoding is None:
647db96d56Sopenharmony_ci            return writer.getvalue()
657db96d56Sopenharmony_ci        else:
667db96d56Sopenharmony_ci            return writer.detach().getvalue()
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_ci    def hasChildNodes(self):
697db96d56Sopenharmony_ci        return bool(self.childNodes)
707db96d56Sopenharmony_ci
717db96d56Sopenharmony_ci    def _get_childNodes(self):
727db96d56Sopenharmony_ci        return self.childNodes
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ci    def _get_firstChild(self):
757db96d56Sopenharmony_ci        if self.childNodes:
767db96d56Sopenharmony_ci            return self.childNodes[0]
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_ci    def _get_lastChild(self):
797db96d56Sopenharmony_ci        if self.childNodes:
807db96d56Sopenharmony_ci            return self.childNodes[-1]
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ci    def insertBefore(self, newChild, refChild):
837db96d56Sopenharmony_ci        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
847db96d56Sopenharmony_ci            for c in tuple(newChild.childNodes):
857db96d56Sopenharmony_ci                self.insertBefore(c, refChild)
867db96d56Sopenharmony_ci            ### The DOM does not clearly specify what to return in this case
877db96d56Sopenharmony_ci            return newChild
887db96d56Sopenharmony_ci        if newChild.nodeType not in self._child_node_types:
897db96d56Sopenharmony_ci            raise xml.dom.HierarchyRequestErr(
907db96d56Sopenharmony_ci                "%s cannot be child of %s" % (repr(newChild), repr(self)))
917db96d56Sopenharmony_ci        if newChild.parentNode is not None:
927db96d56Sopenharmony_ci            newChild.parentNode.removeChild(newChild)
937db96d56Sopenharmony_ci        if refChild is None:
947db96d56Sopenharmony_ci            self.appendChild(newChild)
957db96d56Sopenharmony_ci        else:
967db96d56Sopenharmony_ci            try:
977db96d56Sopenharmony_ci                index = self.childNodes.index(refChild)
987db96d56Sopenharmony_ci            except ValueError:
997db96d56Sopenharmony_ci                raise xml.dom.NotFoundErr()
1007db96d56Sopenharmony_ci            if newChild.nodeType in _nodeTypes_with_children:
1017db96d56Sopenharmony_ci                _clear_id_cache(self)
1027db96d56Sopenharmony_ci            self.childNodes.insert(index, newChild)
1037db96d56Sopenharmony_ci            newChild.nextSibling = refChild
1047db96d56Sopenharmony_ci            refChild.previousSibling = newChild
1057db96d56Sopenharmony_ci            if index:
1067db96d56Sopenharmony_ci                node = self.childNodes[index-1]
1077db96d56Sopenharmony_ci                node.nextSibling = newChild
1087db96d56Sopenharmony_ci                newChild.previousSibling = node
1097db96d56Sopenharmony_ci            else:
1107db96d56Sopenharmony_ci                newChild.previousSibling = None
1117db96d56Sopenharmony_ci            newChild.parentNode = self
1127db96d56Sopenharmony_ci        return newChild
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ci    def appendChild(self, node):
1157db96d56Sopenharmony_ci        if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
1167db96d56Sopenharmony_ci            for c in tuple(node.childNodes):
1177db96d56Sopenharmony_ci                self.appendChild(c)
1187db96d56Sopenharmony_ci            ### The DOM does not clearly specify what to return in this case
1197db96d56Sopenharmony_ci            return node
1207db96d56Sopenharmony_ci        if node.nodeType not in self._child_node_types:
1217db96d56Sopenharmony_ci            raise xml.dom.HierarchyRequestErr(
1227db96d56Sopenharmony_ci                "%s cannot be child of %s" % (repr(node), repr(self)))
1237db96d56Sopenharmony_ci        elif node.nodeType in _nodeTypes_with_children:
1247db96d56Sopenharmony_ci            _clear_id_cache(self)
1257db96d56Sopenharmony_ci        if node.parentNode is not None:
1267db96d56Sopenharmony_ci            node.parentNode.removeChild(node)
1277db96d56Sopenharmony_ci        _append_child(self, node)
1287db96d56Sopenharmony_ci        node.nextSibling = None
1297db96d56Sopenharmony_ci        return node
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_ci    def replaceChild(self, newChild, oldChild):
1327db96d56Sopenharmony_ci        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
1337db96d56Sopenharmony_ci            refChild = oldChild.nextSibling
1347db96d56Sopenharmony_ci            self.removeChild(oldChild)
1357db96d56Sopenharmony_ci            return self.insertBefore(newChild, refChild)
1367db96d56Sopenharmony_ci        if newChild.nodeType not in self._child_node_types:
1377db96d56Sopenharmony_ci            raise xml.dom.HierarchyRequestErr(
1387db96d56Sopenharmony_ci                "%s cannot be child of %s" % (repr(newChild), repr(self)))
1397db96d56Sopenharmony_ci        if newChild is oldChild:
1407db96d56Sopenharmony_ci            return
1417db96d56Sopenharmony_ci        if newChild.parentNode is not None:
1427db96d56Sopenharmony_ci            newChild.parentNode.removeChild(newChild)
1437db96d56Sopenharmony_ci        try:
1447db96d56Sopenharmony_ci            index = self.childNodes.index(oldChild)
1457db96d56Sopenharmony_ci        except ValueError:
1467db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
1477db96d56Sopenharmony_ci        self.childNodes[index] = newChild
1487db96d56Sopenharmony_ci        newChild.parentNode = self
1497db96d56Sopenharmony_ci        oldChild.parentNode = None
1507db96d56Sopenharmony_ci        if (newChild.nodeType in _nodeTypes_with_children
1517db96d56Sopenharmony_ci            or oldChild.nodeType in _nodeTypes_with_children):
1527db96d56Sopenharmony_ci            _clear_id_cache(self)
1537db96d56Sopenharmony_ci        newChild.nextSibling = oldChild.nextSibling
1547db96d56Sopenharmony_ci        newChild.previousSibling = oldChild.previousSibling
1557db96d56Sopenharmony_ci        oldChild.nextSibling = None
1567db96d56Sopenharmony_ci        oldChild.previousSibling = None
1577db96d56Sopenharmony_ci        if newChild.previousSibling:
1587db96d56Sopenharmony_ci            newChild.previousSibling.nextSibling = newChild
1597db96d56Sopenharmony_ci        if newChild.nextSibling:
1607db96d56Sopenharmony_ci            newChild.nextSibling.previousSibling = newChild
1617db96d56Sopenharmony_ci        return oldChild
1627db96d56Sopenharmony_ci
1637db96d56Sopenharmony_ci    def removeChild(self, oldChild):
1647db96d56Sopenharmony_ci        try:
1657db96d56Sopenharmony_ci            self.childNodes.remove(oldChild)
1667db96d56Sopenharmony_ci        except ValueError:
1677db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
1687db96d56Sopenharmony_ci        if oldChild.nextSibling is not None:
1697db96d56Sopenharmony_ci            oldChild.nextSibling.previousSibling = oldChild.previousSibling
1707db96d56Sopenharmony_ci        if oldChild.previousSibling is not None:
1717db96d56Sopenharmony_ci            oldChild.previousSibling.nextSibling = oldChild.nextSibling
1727db96d56Sopenharmony_ci        oldChild.nextSibling = oldChild.previousSibling = None
1737db96d56Sopenharmony_ci        if oldChild.nodeType in _nodeTypes_with_children:
1747db96d56Sopenharmony_ci            _clear_id_cache(self)
1757db96d56Sopenharmony_ci
1767db96d56Sopenharmony_ci        oldChild.parentNode = None
1777db96d56Sopenharmony_ci        return oldChild
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_ci    def normalize(self):
1807db96d56Sopenharmony_ci        L = []
1817db96d56Sopenharmony_ci        for child in self.childNodes:
1827db96d56Sopenharmony_ci            if child.nodeType == Node.TEXT_NODE:
1837db96d56Sopenharmony_ci                if not child.data:
1847db96d56Sopenharmony_ci                    # empty text node; discard
1857db96d56Sopenharmony_ci                    if L:
1867db96d56Sopenharmony_ci                        L[-1].nextSibling = child.nextSibling
1877db96d56Sopenharmony_ci                    if child.nextSibling:
1887db96d56Sopenharmony_ci                        child.nextSibling.previousSibling = child.previousSibling
1897db96d56Sopenharmony_ci                    child.unlink()
1907db96d56Sopenharmony_ci                elif L and L[-1].nodeType == child.nodeType:
1917db96d56Sopenharmony_ci                    # collapse text node
1927db96d56Sopenharmony_ci                    node = L[-1]
1937db96d56Sopenharmony_ci                    node.data = node.data + child.data
1947db96d56Sopenharmony_ci                    node.nextSibling = child.nextSibling
1957db96d56Sopenharmony_ci                    if child.nextSibling:
1967db96d56Sopenharmony_ci                        child.nextSibling.previousSibling = node
1977db96d56Sopenharmony_ci                    child.unlink()
1987db96d56Sopenharmony_ci                else:
1997db96d56Sopenharmony_ci                    L.append(child)
2007db96d56Sopenharmony_ci            else:
2017db96d56Sopenharmony_ci                L.append(child)
2027db96d56Sopenharmony_ci                if child.nodeType == Node.ELEMENT_NODE:
2037db96d56Sopenharmony_ci                    child.normalize()
2047db96d56Sopenharmony_ci        self.childNodes[:] = L
2057db96d56Sopenharmony_ci
2067db96d56Sopenharmony_ci    def cloneNode(self, deep):
2077db96d56Sopenharmony_ci        return _clone_node(self, deep, self.ownerDocument or self)
2087db96d56Sopenharmony_ci
2097db96d56Sopenharmony_ci    def isSupported(self, feature, version):
2107db96d56Sopenharmony_ci        return self.ownerDocument.implementation.hasFeature(feature, version)
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ci    def _get_localName(self):
2137db96d56Sopenharmony_ci        # Overridden in Element and Attr where localName can be Non-Null
2147db96d56Sopenharmony_ci        return None
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ci    # Node interfaces from Level 3 (WD 9 April 2002)
2177db96d56Sopenharmony_ci
2187db96d56Sopenharmony_ci    def isSameNode(self, other):
2197db96d56Sopenharmony_ci        return self is other
2207db96d56Sopenharmony_ci
2217db96d56Sopenharmony_ci    def getInterface(self, feature):
2227db96d56Sopenharmony_ci        if self.isSupported(feature, None):
2237db96d56Sopenharmony_ci            return self
2247db96d56Sopenharmony_ci        else:
2257db96d56Sopenharmony_ci            return None
2267db96d56Sopenharmony_ci
2277db96d56Sopenharmony_ci    # The "user data" functions use a dictionary that is only present
2287db96d56Sopenharmony_ci    # if some user data has been set, so be careful not to assume it
2297db96d56Sopenharmony_ci    # exists.
2307db96d56Sopenharmony_ci
2317db96d56Sopenharmony_ci    def getUserData(self, key):
2327db96d56Sopenharmony_ci        try:
2337db96d56Sopenharmony_ci            return self._user_data[key][0]
2347db96d56Sopenharmony_ci        except (AttributeError, KeyError):
2357db96d56Sopenharmony_ci            return None
2367db96d56Sopenharmony_ci
2377db96d56Sopenharmony_ci    def setUserData(self, key, data, handler):
2387db96d56Sopenharmony_ci        old = None
2397db96d56Sopenharmony_ci        try:
2407db96d56Sopenharmony_ci            d = self._user_data
2417db96d56Sopenharmony_ci        except AttributeError:
2427db96d56Sopenharmony_ci            d = {}
2437db96d56Sopenharmony_ci            self._user_data = d
2447db96d56Sopenharmony_ci        if key in d:
2457db96d56Sopenharmony_ci            old = d[key][0]
2467db96d56Sopenharmony_ci        if data is None:
2477db96d56Sopenharmony_ci            # ignore handlers passed for None
2487db96d56Sopenharmony_ci            handler = None
2497db96d56Sopenharmony_ci            if old is not None:
2507db96d56Sopenharmony_ci                del d[key]
2517db96d56Sopenharmony_ci        else:
2527db96d56Sopenharmony_ci            d[key] = (data, handler)
2537db96d56Sopenharmony_ci        return old
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci    def _call_user_data_handler(self, operation, src, dst):
2567db96d56Sopenharmony_ci        if hasattr(self, "_user_data"):
2577db96d56Sopenharmony_ci            for key, (data, handler) in list(self._user_data.items()):
2587db96d56Sopenharmony_ci                if handler is not None:
2597db96d56Sopenharmony_ci                    handler.handle(operation, key, data, src, dst)
2607db96d56Sopenharmony_ci
2617db96d56Sopenharmony_ci    # minidom-specific API:
2627db96d56Sopenharmony_ci
2637db96d56Sopenharmony_ci    def unlink(self):
2647db96d56Sopenharmony_ci        self.parentNode = self.ownerDocument = None
2657db96d56Sopenharmony_ci        if self.childNodes:
2667db96d56Sopenharmony_ci            for child in self.childNodes:
2677db96d56Sopenharmony_ci                child.unlink()
2687db96d56Sopenharmony_ci            self.childNodes = NodeList()
2697db96d56Sopenharmony_ci        self.previousSibling = None
2707db96d56Sopenharmony_ci        self.nextSibling = None
2717db96d56Sopenharmony_ci
2727db96d56Sopenharmony_ci    # A Node is its own context manager, to ensure that an unlink() call occurs.
2737db96d56Sopenharmony_ci    # This is similar to how a file object works.
2747db96d56Sopenharmony_ci    def __enter__(self):
2757db96d56Sopenharmony_ci        return self
2767db96d56Sopenharmony_ci
2777db96d56Sopenharmony_ci    def __exit__(self, et, ev, tb):
2787db96d56Sopenharmony_ci        self.unlink()
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_cidefproperty(Node, "firstChild", doc="First child node, or None.")
2817db96d56Sopenharmony_cidefproperty(Node, "lastChild",  doc="Last child node, or None.")
2827db96d56Sopenharmony_cidefproperty(Node, "localName",  doc="Namespace-local name of this node.")
2837db96d56Sopenharmony_ci
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_cidef _append_child(self, node):
2867db96d56Sopenharmony_ci    # fast path with less checks; usable by DOM builders if careful
2877db96d56Sopenharmony_ci    childNodes = self.childNodes
2887db96d56Sopenharmony_ci    if childNodes:
2897db96d56Sopenharmony_ci        last = childNodes[-1]
2907db96d56Sopenharmony_ci        node.previousSibling = last
2917db96d56Sopenharmony_ci        last.nextSibling = node
2927db96d56Sopenharmony_ci    childNodes.append(node)
2937db96d56Sopenharmony_ci    node.parentNode = self
2947db96d56Sopenharmony_ci
2957db96d56Sopenharmony_cidef _in_document(node):
2967db96d56Sopenharmony_ci    # return True iff node is part of a document tree
2977db96d56Sopenharmony_ci    while node is not None:
2987db96d56Sopenharmony_ci        if node.nodeType == Node.DOCUMENT_NODE:
2997db96d56Sopenharmony_ci            return True
3007db96d56Sopenharmony_ci        node = node.parentNode
3017db96d56Sopenharmony_ci    return False
3027db96d56Sopenharmony_ci
3037db96d56Sopenharmony_cidef _write_data(writer, data):
3047db96d56Sopenharmony_ci    "Writes datachars to writer."
3057db96d56Sopenharmony_ci    if data:
3067db96d56Sopenharmony_ci        data = data.replace("&", "&amp;").replace("<", "&lt;"). \
3077db96d56Sopenharmony_ci                    replace("\"", "&quot;").replace(">", "&gt;")
3087db96d56Sopenharmony_ci        writer.write(data)
3097db96d56Sopenharmony_ci
3107db96d56Sopenharmony_cidef _get_elements_by_tagName_helper(parent, name, rc):
3117db96d56Sopenharmony_ci    for node in parent.childNodes:
3127db96d56Sopenharmony_ci        if node.nodeType == Node.ELEMENT_NODE and \
3137db96d56Sopenharmony_ci            (name == "*" or node.tagName == name):
3147db96d56Sopenharmony_ci            rc.append(node)
3157db96d56Sopenharmony_ci        _get_elements_by_tagName_helper(node, name, rc)
3167db96d56Sopenharmony_ci    return rc
3177db96d56Sopenharmony_ci
3187db96d56Sopenharmony_cidef _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
3197db96d56Sopenharmony_ci    for node in parent.childNodes:
3207db96d56Sopenharmony_ci        if node.nodeType == Node.ELEMENT_NODE:
3217db96d56Sopenharmony_ci            if ((localName == "*" or node.localName == localName) and
3227db96d56Sopenharmony_ci                (nsURI == "*" or node.namespaceURI == nsURI)):
3237db96d56Sopenharmony_ci                rc.append(node)
3247db96d56Sopenharmony_ci            _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
3257db96d56Sopenharmony_ci    return rc
3267db96d56Sopenharmony_ci
3277db96d56Sopenharmony_ciclass DocumentFragment(Node):
3287db96d56Sopenharmony_ci    nodeType = Node.DOCUMENT_FRAGMENT_NODE
3297db96d56Sopenharmony_ci    nodeName = "#document-fragment"
3307db96d56Sopenharmony_ci    nodeValue = None
3317db96d56Sopenharmony_ci    attributes = None
3327db96d56Sopenharmony_ci    parentNode = None
3337db96d56Sopenharmony_ci    _child_node_types = (Node.ELEMENT_NODE,
3347db96d56Sopenharmony_ci                         Node.TEXT_NODE,
3357db96d56Sopenharmony_ci                         Node.CDATA_SECTION_NODE,
3367db96d56Sopenharmony_ci                         Node.ENTITY_REFERENCE_NODE,
3377db96d56Sopenharmony_ci                         Node.PROCESSING_INSTRUCTION_NODE,
3387db96d56Sopenharmony_ci                         Node.COMMENT_NODE,
3397db96d56Sopenharmony_ci                         Node.NOTATION_NODE)
3407db96d56Sopenharmony_ci
3417db96d56Sopenharmony_ci    def __init__(self):
3427db96d56Sopenharmony_ci        self.childNodes = NodeList()
3437db96d56Sopenharmony_ci
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_ciclass Attr(Node):
3467db96d56Sopenharmony_ci    __slots__=('_name', '_value', 'namespaceURI',
3477db96d56Sopenharmony_ci               '_prefix', 'childNodes', '_localName', 'ownerDocument', 'ownerElement')
3487db96d56Sopenharmony_ci    nodeType = Node.ATTRIBUTE_NODE
3497db96d56Sopenharmony_ci    attributes = None
3507db96d56Sopenharmony_ci    specified = False
3517db96d56Sopenharmony_ci    _is_id = False
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci    _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
3547db96d56Sopenharmony_ci
3557db96d56Sopenharmony_ci    def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
3567db96d56Sopenharmony_ci                 prefix=None):
3577db96d56Sopenharmony_ci        self.ownerElement = None
3587db96d56Sopenharmony_ci        self._name = qName
3597db96d56Sopenharmony_ci        self.namespaceURI = namespaceURI
3607db96d56Sopenharmony_ci        self._prefix = prefix
3617db96d56Sopenharmony_ci        if localName is not None:
3627db96d56Sopenharmony_ci            self._localName = localName
3637db96d56Sopenharmony_ci        self.childNodes = NodeList()
3647db96d56Sopenharmony_ci
3657db96d56Sopenharmony_ci        # Add the single child node that represents the value of the attr
3667db96d56Sopenharmony_ci        self.childNodes.append(Text())
3677db96d56Sopenharmony_ci
3687db96d56Sopenharmony_ci        # nodeValue and value are set elsewhere
3697db96d56Sopenharmony_ci
3707db96d56Sopenharmony_ci    def _get_localName(self):
3717db96d56Sopenharmony_ci        try:
3727db96d56Sopenharmony_ci            return self._localName
3737db96d56Sopenharmony_ci        except AttributeError:
3747db96d56Sopenharmony_ci            return self.nodeName.split(":", 1)[-1]
3757db96d56Sopenharmony_ci
3767db96d56Sopenharmony_ci    def _get_specified(self):
3777db96d56Sopenharmony_ci        return self.specified
3787db96d56Sopenharmony_ci
3797db96d56Sopenharmony_ci    def _get_name(self):
3807db96d56Sopenharmony_ci        return self._name
3817db96d56Sopenharmony_ci
3827db96d56Sopenharmony_ci    def _set_name(self, value):
3837db96d56Sopenharmony_ci        self._name = value
3847db96d56Sopenharmony_ci        if self.ownerElement is not None:
3857db96d56Sopenharmony_ci            _clear_id_cache(self.ownerElement)
3867db96d56Sopenharmony_ci
3877db96d56Sopenharmony_ci    nodeName = name = property(_get_name, _set_name)
3887db96d56Sopenharmony_ci
3897db96d56Sopenharmony_ci    def _get_value(self):
3907db96d56Sopenharmony_ci        return self._value
3917db96d56Sopenharmony_ci
3927db96d56Sopenharmony_ci    def _set_value(self, value):
3937db96d56Sopenharmony_ci        self._value = value
3947db96d56Sopenharmony_ci        self.childNodes[0].data = value
3957db96d56Sopenharmony_ci        if self.ownerElement is not None:
3967db96d56Sopenharmony_ci            _clear_id_cache(self.ownerElement)
3977db96d56Sopenharmony_ci        self.childNodes[0].data = value
3987db96d56Sopenharmony_ci
3997db96d56Sopenharmony_ci    nodeValue = value = property(_get_value, _set_value)
4007db96d56Sopenharmony_ci
4017db96d56Sopenharmony_ci    def _get_prefix(self):
4027db96d56Sopenharmony_ci        return self._prefix
4037db96d56Sopenharmony_ci
4047db96d56Sopenharmony_ci    def _set_prefix(self, prefix):
4057db96d56Sopenharmony_ci        nsuri = self.namespaceURI
4067db96d56Sopenharmony_ci        if prefix == "xmlns":
4077db96d56Sopenharmony_ci            if nsuri and nsuri != XMLNS_NAMESPACE:
4087db96d56Sopenharmony_ci                raise xml.dom.NamespaceErr(
4097db96d56Sopenharmony_ci                    "illegal use of 'xmlns' prefix for the wrong namespace")
4107db96d56Sopenharmony_ci        self._prefix = prefix
4117db96d56Sopenharmony_ci        if prefix is None:
4127db96d56Sopenharmony_ci            newName = self.localName
4137db96d56Sopenharmony_ci        else:
4147db96d56Sopenharmony_ci            newName = "%s:%s" % (prefix, self.localName)
4157db96d56Sopenharmony_ci        if self.ownerElement:
4167db96d56Sopenharmony_ci            _clear_id_cache(self.ownerElement)
4177db96d56Sopenharmony_ci        self.name = newName
4187db96d56Sopenharmony_ci
4197db96d56Sopenharmony_ci    prefix = property(_get_prefix, _set_prefix)
4207db96d56Sopenharmony_ci
4217db96d56Sopenharmony_ci    def unlink(self):
4227db96d56Sopenharmony_ci        # This implementation does not call the base implementation
4237db96d56Sopenharmony_ci        # since most of that is not needed, and the expense of the
4247db96d56Sopenharmony_ci        # method call is not warranted.  We duplicate the removal of
4257db96d56Sopenharmony_ci        # children, but that's all we needed from the base class.
4267db96d56Sopenharmony_ci        elem = self.ownerElement
4277db96d56Sopenharmony_ci        if elem is not None:
4287db96d56Sopenharmony_ci            del elem._attrs[self.nodeName]
4297db96d56Sopenharmony_ci            del elem._attrsNS[(self.namespaceURI, self.localName)]
4307db96d56Sopenharmony_ci            if self._is_id:
4317db96d56Sopenharmony_ci                self._is_id = False
4327db96d56Sopenharmony_ci                elem._magic_id_nodes -= 1
4337db96d56Sopenharmony_ci                self.ownerDocument._magic_id_count -= 1
4347db96d56Sopenharmony_ci        for child in self.childNodes:
4357db96d56Sopenharmony_ci            child.unlink()
4367db96d56Sopenharmony_ci        del self.childNodes[:]
4377db96d56Sopenharmony_ci
4387db96d56Sopenharmony_ci    def _get_isId(self):
4397db96d56Sopenharmony_ci        if self._is_id:
4407db96d56Sopenharmony_ci            return True
4417db96d56Sopenharmony_ci        doc = self.ownerDocument
4427db96d56Sopenharmony_ci        elem = self.ownerElement
4437db96d56Sopenharmony_ci        if doc is None or elem is None:
4447db96d56Sopenharmony_ci            return False
4457db96d56Sopenharmony_ci
4467db96d56Sopenharmony_ci        info = doc._get_elem_info(elem)
4477db96d56Sopenharmony_ci        if info is None:
4487db96d56Sopenharmony_ci            return False
4497db96d56Sopenharmony_ci        if self.namespaceURI:
4507db96d56Sopenharmony_ci            return info.isIdNS(self.namespaceURI, self.localName)
4517db96d56Sopenharmony_ci        else:
4527db96d56Sopenharmony_ci            return info.isId(self.nodeName)
4537db96d56Sopenharmony_ci
4547db96d56Sopenharmony_ci    def _get_schemaType(self):
4557db96d56Sopenharmony_ci        doc = self.ownerDocument
4567db96d56Sopenharmony_ci        elem = self.ownerElement
4577db96d56Sopenharmony_ci        if doc is None or elem is None:
4587db96d56Sopenharmony_ci            return _no_type
4597db96d56Sopenharmony_ci
4607db96d56Sopenharmony_ci        info = doc._get_elem_info(elem)
4617db96d56Sopenharmony_ci        if info is None:
4627db96d56Sopenharmony_ci            return _no_type
4637db96d56Sopenharmony_ci        if self.namespaceURI:
4647db96d56Sopenharmony_ci            return info.getAttributeTypeNS(self.namespaceURI, self.localName)
4657db96d56Sopenharmony_ci        else:
4667db96d56Sopenharmony_ci            return info.getAttributeType(self.nodeName)
4677db96d56Sopenharmony_ci
4687db96d56Sopenharmony_cidefproperty(Attr, "isId",       doc="True if this attribute is an ID.")
4697db96d56Sopenharmony_cidefproperty(Attr, "localName",  doc="Namespace-local name of this attribute.")
4707db96d56Sopenharmony_cidefproperty(Attr, "schemaType", doc="Schema type for this attribute.")
4717db96d56Sopenharmony_ci
4727db96d56Sopenharmony_ci
4737db96d56Sopenharmony_ciclass NamedNodeMap(object):
4747db96d56Sopenharmony_ci    """The attribute list is a transient interface to the underlying
4757db96d56Sopenharmony_ci    dictionaries.  Mutations here will change the underlying element's
4767db96d56Sopenharmony_ci    dictionary.
4777db96d56Sopenharmony_ci
4787db96d56Sopenharmony_ci    Ordering is imposed artificially and does not reflect the order of
4797db96d56Sopenharmony_ci    attributes as found in an input document.
4807db96d56Sopenharmony_ci    """
4817db96d56Sopenharmony_ci
4827db96d56Sopenharmony_ci    __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
4837db96d56Sopenharmony_ci
4847db96d56Sopenharmony_ci    def __init__(self, attrs, attrsNS, ownerElement):
4857db96d56Sopenharmony_ci        self._attrs = attrs
4867db96d56Sopenharmony_ci        self._attrsNS = attrsNS
4877db96d56Sopenharmony_ci        self._ownerElement = ownerElement
4887db96d56Sopenharmony_ci
4897db96d56Sopenharmony_ci    def _get_length(self):
4907db96d56Sopenharmony_ci        return len(self._attrs)
4917db96d56Sopenharmony_ci
4927db96d56Sopenharmony_ci    def item(self, index):
4937db96d56Sopenharmony_ci        try:
4947db96d56Sopenharmony_ci            return self[list(self._attrs.keys())[index]]
4957db96d56Sopenharmony_ci        except IndexError:
4967db96d56Sopenharmony_ci            return None
4977db96d56Sopenharmony_ci
4987db96d56Sopenharmony_ci    def items(self):
4997db96d56Sopenharmony_ci        L = []
5007db96d56Sopenharmony_ci        for node in self._attrs.values():
5017db96d56Sopenharmony_ci            L.append((node.nodeName, node.value))
5027db96d56Sopenharmony_ci        return L
5037db96d56Sopenharmony_ci
5047db96d56Sopenharmony_ci    def itemsNS(self):
5057db96d56Sopenharmony_ci        L = []
5067db96d56Sopenharmony_ci        for node in self._attrs.values():
5077db96d56Sopenharmony_ci            L.append(((node.namespaceURI, node.localName), node.value))
5087db96d56Sopenharmony_ci        return L
5097db96d56Sopenharmony_ci
5107db96d56Sopenharmony_ci    def __contains__(self, key):
5117db96d56Sopenharmony_ci        if isinstance(key, str):
5127db96d56Sopenharmony_ci            return key in self._attrs
5137db96d56Sopenharmony_ci        else:
5147db96d56Sopenharmony_ci            return key in self._attrsNS
5157db96d56Sopenharmony_ci
5167db96d56Sopenharmony_ci    def keys(self):
5177db96d56Sopenharmony_ci        return self._attrs.keys()
5187db96d56Sopenharmony_ci
5197db96d56Sopenharmony_ci    def keysNS(self):
5207db96d56Sopenharmony_ci        return self._attrsNS.keys()
5217db96d56Sopenharmony_ci
5227db96d56Sopenharmony_ci    def values(self):
5237db96d56Sopenharmony_ci        return self._attrs.values()
5247db96d56Sopenharmony_ci
5257db96d56Sopenharmony_ci    def get(self, name, value=None):
5267db96d56Sopenharmony_ci        return self._attrs.get(name, value)
5277db96d56Sopenharmony_ci
5287db96d56Sopenharmony_ci    __len__ = _get_length
5297db96d56Sopenharmony_ci
5307db96d56Sopenharmony_ci    def _cmp(self, other):
5317db96d56Sopenharmony_ci        if self._attrs is getattr(other, "_attrs", None):
5327db96d56Sopenharmony_ci            return 0
5337db96d56Sopenharmony_ci        else:
5347db96d56Sopenharmony_ci            return (id(self) > id(other)) - (id(self) < id(other))
5357db96d56Sopenharmony_ci
5367db96d56Sopenharmony_ci    def __eq__(self, other):
5377db96d56Sopenharmony_ci        return self._cmp(other) == 0
5387db96d56Sopenharmony_ci
5397db96d56Sopenharmony_ci    def __ge__(self, other):
5407db96d56Sopenharmony_ci        return self._cmp(other) >= 0
5417db96d56Sopenharmony_ci
5427db96d56Sopenharmony_ci    def __gt__(self, other):
5437db96d56Sopenharmony_ci        return self._cmp(other) > 0
5447db96d56Sopenharmony_ci
5457db96d56Sopenharmony_ci    def __le__(self, other):
5467db96d56Sopenharmony_ci        return self._cmp(other) <= 0
5477db96d56Sopenharmony_ci
5487db96d56Sopenharmony_ci    def __lt__(self, other):
5497db96d56Sopenharmony_ci        return self._cmp(other) < 0
5507db96d56Sopenharmony_ci
5517db96d56Sopenharmony_ci    def __getitem__(self, attname_or_tuple):
5527db96d56Sopenharmony_ci        if isinstance(attname_or_tuple, tuple):
5537db96d56Sopenharmony_ci            return self._attrsNS[attname_or_tuple]
5547db96d56Sopenharmony_ci        else:
5557db96d56Sopenharmony_ci            return self._attrs[attname_or_tuple]
5567db96d56Sopenharmony_ci
5577db96d56Sopenharmony_ci    # same as set
5587db96d56Sopenharmony_ci    def __setitem__(self, attname, value):
5597db96d56Sopenharmony_ci        if isinstance(value, str):
5607db96d56Sopenharmony_ci            try:
5617db96d56Sopenharmony_ci                node = self._attrs[attname]
5627db96d56Sopenharmony_ci            except KeyError:
5637db96d56Sopenharmony_ci                node = Attr(attname)
5647db96d56Sopenharmony_ci                node.ownerDocument = self._ownerElement.ownerDocument
5657db96d56Sopenharmony_ci                self.setNamedItem(node)
5667db96d56Sopenharmony_ci            node.value = value
5677db96d56Sopenharmony_ci        else:
5687db96d56Sopenharmony_ci            if not isinstance(value, Attr):
5697db96d56Sopenharmony_ci                raise TypeError("value must be a string or Attr object")
5707db96d56Sopenharmony_ci            node = value
5717db96d56Sopenharmony_ci            self.setNamedItem(node)
5727db96d56Sopenharmony_ci
5737db96d56Sopenharmony_ci    def getNamedItem(self, name):
5747db96d56Sopenharmony_ci        try:
5757db96d56Sopenharmony_ci            return self._attrs[name]
5767db96d56Sopenharmony_ci        except KeyError:
5777db96d56Sopenharmony_ci            return None
5787db96d56Sopenharmony_ci
5797db96d56Sopenharmony_ci    def getNamedItemNS(self, namespaceURI, localName):
5807db96d56Sopenharmony_ci        try:
5817db96d56Sopenharmony_ci            return self._attrsNS[(namespaceURI, localName)]
5827db96d56Sopenharmony_ci        except KeyError:
5837db96d56Sopenharmony_ci            return None
5847db96d56Sopenharmony_ci
5857db96d56Sopenharmony_ci    def removeNamedItem(self, name):
5867db96d56Sopenharmony_ci        n = self.getNamedItem(name)
5877db96d56Sopenharmony_ci        if n is not None:
5887db96d56Sopenharmony_ci            _clear_id_cache(self._ownerElement)
5897db96d56Sopenharmony_ci            del self._attrs[n.nodeName]
5907db96d56Sopenharmony_ci            del self._attrsNS[(n.namespaceURI, n.localName)]
5917db96d56Sopenharmony_ci            if hasattr(n, 'ownerElement'):
5927db96d56Sopenharmony_ci                n.ownerElement = None
5937db96d56Sopenharmony_ci            return n
5947db96d56Sopenharmony_ci        else:
5957db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
5967db96d56Sopenharmony_ci
5977db96d56Sopenharmony_ci    def removeNamedItemNS(self, namespaceURI, localName):
5987db96d56Sopenharmony_ci        n = self.getNamedItemNS(namespaceURI, localName)
5997db96d56Sopenharmony_ci        if n is not None:
6007db96d56Sopenharmony_ci            _clear_id_cache(self._ownerElement)
6017db96d56Sopenharmony_ci            del self._attrsNS[(n.namespaceURI, n.localName)]
6027db96d56Sopenharmony_ci            del self._attrs[n.nodeName]
6037db96d56Sopenharmony_ci            if hasattr(n, 'ownerElement'):
6047db96d56Sopenharmony_ci                n.ownerElement = None
6057db96d56Sopenharmony_ci            return n
6067db96d56Sopenharmony_ci        else:
6077db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
6087db96d56Sopenharmony_ci
6097db96d56Sopenharmony_ci    def setNamedItem(self, node):
6107db96d56Sopenharmony_ci        if not isinstance(node, Attr):
6117db96d56Sopenharmony_ci            raise xml.dom.HierarchyRequestErr(
6127db96d56Sopenharmony_ci                "%s cannot be child of %s" % (repr(node), repr(self)))
6137db96d56Sopenharmony_ci        old = self._attrs.get(node.name)
6147db96d56Sopenharmony_ci        if old:
6157db96d56Sopenharmony_ci            old.unlink()
6167db96d56Sopenharmony_ci        self._attrs[node.name] = node
6177db96d56Sopenharmony_ci        self._attrsNS[(node.namespaceURI, node.localName)] = node
6187db96d56Sopenharmony_ci        node.ownerElement = self._ownerElement
6197db96d56Sopenharmony_ci        _clear_id_cache(node.ownerElement)
6207db96d56Sopenharmony_ci        return old
6217db96d56Sopenharmony_ci
6227db96d56Sopenharmony_ci    def setNamedItemNS(self, node):
6237db96d56Sopenharmony_ci        return self.setNamedItem(node)
6247db96d56Sopenharmony_ci
6257db96d56Sopenharmony_ci    def __delitem__(self, attname_or_tuple):
6267db96d56Sopenharmony_ci        node = self[attname_or_tuple]
6277db96d56Sopenharmony_ci        _clear_id_cache(node.ownerElement)
6287db96d56Sopenharmony_ci        node.unlink()
6297db96d56Sopenharmony_ci
6307db96d56Sopenharmony_ci    def __getstate__(self):
6317db96d56Sopenharmony_ci        return self._attrs, self._attrsNS, self._ownerElement
6327db96d56Sopenharmony_ci
6337db96d56Sopenharmony_ci    def __setstate__(self, state):
6347db96d56Sopenharmony_ci        self._attrs, self._attrsNS, self._ownerElement = state
6357db96d56Sopenharmony_ci
6367db96d56Sopenharmony_cidefproperty(NamedNodeMap, "length",
6377db96d56Sopenharmony_ci            doc="Number of nodes in the NamedNodeMap.")
6387db96d56Sopenharmony_ci
6397db96d56Sopenharmony_ciAttributeList = NamedNodeMap
6407db96d56Sopenharmony_ci
6417db96d56Sopenharmony_ci
6427db96d56Sopenharmony_ciclass TypeInfo(object):
6437db96d56Sopenharmony_ci    __slots__ = 'namespace', 'name'
6447db96d56Sopenharmony_ci
6457db96d56Sopenharmony_ci    def __init__(self, namespace, name):
6467db96d56Sopenharmony_ci        self.namespace = namespace
6477db96d56Sopenharmony_ci        self.name = name
6487db96d56Sopenharmony_ci
6497db96d56Sopenharmony_ci    def __repr__(self):
6507db96d56Sopenharmony_ci        if self.namespace:
6517db96d56Sopenharmony_ci            return "<%s %r (from %r)>" % (self.__class__.__name__, self.name,
6527db96d56Sopenharmony_ci                                          self.namespace)
6537db96d56Sopenharmony_ci        else:
6547db96d56Sopenharmony_ci            return "<%s %r>" % (self.__class__.__name__, self.name)
6557db96d56Sopenharmony_ci
6567db96d56Sopenharmony_ci    def _get_name(self):
6577db96d56Sopenharmony_ci        return self.name
6587db96d56Sopenharmony_ci
6597db96d56Sopenharmony_ci    def _get_namespace(self):
6607db96d56Sopenharmony_ci        return self.namespace
6617db96d56Sopenharmony_ci
6627db96d56Sopenharmony_ci_no_type = TypeInfo(None, None)
6637db96d56Sopenharmony_ci
6647db96d56Sopenharmony_ciclass Element(Node):
6657db96d56Sopenharmony_ci    __slots__=('ownerDocument', 'parentNode', 'tagName', 'nodeName', 'prefix',
6667db96d56Sopenharmony_ci               'namespaceURI', '_localName', 'childNodes', '_attrs', '_attrsNS',
6677db96d56Sopenharmony_ci               'nextSibling', 'previousSibling')
6687db96d56Sopenharmony_ci    nodeType = Node.ELEMENT_NODE
6697db96d56Sopenharmony_ci    nodeValue = None
6707db96d56Sopenharmony_ci    schemaType = _no_type
6717db96d56Sopenharmony_ci
6727db96d56Sopenharmony_ci    _magic_id_nodes = 0
6737db96d56Sopenharmony_ci
6747db96d56Sopenharmony_ci    _child_node_types = (Node.ELEMENT_NODE,
6757db96d56Sopenharmony_ci                         Node.PROCESSING_INSTRUCTION_NODE,
6767db96d56Sopenharmony_ci                         Node.COMMENT_NODE,
6777db96d56Sopenharmony_ci                         Node.TEXT_NODE,
6787db96d56Sopenharmony_ci                         Node.CDATA_SECTION_NODE,
6797db96d56Sopenharmony_ci                         Node.ENTITY_REFERENCE_NODE)
6807db96d56Sopenharmony_ci
6817db96d56Sopenharmony_ci    def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
6827db96d56Sopenharmony_ci                 localName=None):
6837db96d56Sopenharmony_ci        self.parentNode = None
6847db96d56Sopenharmony_ci        self.tagName = self.nodeName = tagName
6857db96d56Sopenharmony_ci        self.prefix = prefix
6867db96d56Sopenharmony_ci        self.namespaceURI = namespaceURI
6877db96d56Sopenharmony_ci        self.childNodes = NodeList()
6887db96d56Sopenharmony_ci        self.nextSibling = self.previousSibling = None
6897db96d56Sopenharmony_ci
6907db96d56Sopenharmony_ci        # Attribute dictionaries are lazily created
6917db96d56Sopenharmony_ci        # attributes are double-indexed:
6927db96d56Sopenharmony_ci        #    tagName -> Attribute
6937db96d56Sopenharmony_ci        #    URI,localName -> Attribute
6947db96d56Sopenharmony_ci        # in the future: consider lazy generation
6957db96d56Sopenharmony_ci        # of attribute objects this is too tricky
6967db96d56Sopenharmony_ci        # for now because of headaches with
6977db96d56Sopenharmony_ci        # namespaces.
6987db96d56Sopenharmony_ci        self._attrs = None
6997db96d56Sopenharmony_ci        self._attrsNS = None
7007db96d56Sopenharmony_ci
7017db96d56Sopenharmony_ci    def _ensure_attributes(self):
7027db96d56Sopenharmony_ci        if self._attrs is None:
7037db96d56Sopenharmony_ci            self._attrs = {}
7047db96d56Sopenharmony_ci            self._attrsNS = {}
7057db96d56Sopenharmony_ci
7067db96d56Sopenharmony_ci    def _get_localName(self):
7077db96d56Sopenharmony_ci        try:
7087db96d56Sopenharmony_ci            return self._localName
7097db96d56Sopenharmony_ci        except AttributeError:
7107db96d56Sopenharmony_ci            return self.tagName.split(":", 1)[-1]
7117db96d56Sopenharmony_ci
7127db96d56Sopenharmony_ci    def _get_tagName(self):
7137db96d56Sopenharmony_ci        return self.tagName
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_ci    def unlink(self):
7167db96d56Sopenharmony_ci        if self._attrs is not None:
7177db96d56Sopenharmony_ci            for attr in list(self._attrs.values()):
7187db96d56Sopenharmony_ci                attr.unlink()
7197db96d56Sopenharmony_ci        self._attrs = None
7207db96d56Sopenharmony_ci        self._attrsNS = None
7217db96d56Sopenharmony_ci        Node.unlink(self)
7227db96d56Sopenharmony_ci
7237db96d56Sopenharmony_ci    def getAttribute(self, attname):
7247db96d56Sopenharmony_ci        """Returns the value of the specified attribute.
7257db96d56Sopenharmony_ci
7267db96d56Sopenharmony_ci        Returns the value of the element's attribute named attname as
7277db96d56Sopenharmony_ci        a string. An empty string is returned if the element does not
7287db96d56Sopenharmony_ci        have such an attribute. Note that an empty string may also be
7297db96d56Sopenharmony_ci        returned as an explicitly given attribute value, use the
7307db96d56Sopenharmony_ci        hasAttribute method to distinguish these two cases.
7317db96d56Sopenharmony_ci        """
7327db96d56Sopenharmony_ci        if self._attrs is None:
7337db96d56Sopenharmony_ci            return ""
7347db96d56Sopenharmony_ci        try:
7357db96d56Sopenharmony_ci            return self._attrs[attname].value
7367db96d56Sopenharmony_ci        except KeyError:
7377db96d56Sopenharmony_ci            return ""
7387db96d56Sopenharmony_ci
7397db96d56Sopenharmony_ci    def getAttributeNS(self, namespaceURI, localName):
7407db96d56Sopenharmony_ci        if self._attrsNS is None:
7417db96d56Sopenharmony_ci            return ""
7427db96d56Sopenharmony_ci        try:
7437db96d56Sopenharmony_ci            return self._attrsNS[(namespaceURI, localName)].value
7447db96d56Sopenharmony_ci        except KeyError:
7457db96d56Sopenharmony_ci            return ""
7467db96d56Sopenharmony_ci
7477db96d56Sopenharmony_ci    def setAttribute(self, attname, value):
7487db96d56Sopenharmony_ci        attr = self.getAttributeNode(attname)
7497db96d56Sopenharmony_ci        if attr is None:
7507db96d56Sopenharmony_ci            attr = Attr(attname)
7517db96d56Sopenharmony_ci            attr.value = value # also sets nodeValue
7527db96d56Sopenharmony_ci            attr.ownerDocument = self.ownerDocument
7537db96d56Sopenharmony_ci            self.setAttributeNode(attr)
7547db96d56Sopenharmony_ci        elif value != attr.value:
7557db96d56Sopenharmony_ci            attr.value = value
7567db96d56Sopenharmony_ci            if attr.isId:
7577db96d56Sopenharmony_ci                _clear_id_cache(self)
7587db96d56Sopenharmony_ci
7597db96d56Sopenharmony_ci    def setAttributeNS(self, namespaceURI, qualifiedName, value):
7607db96d56Sopenharmony_ci        prefix, localname = _nssplit(qualifiedName)
7617db96d56Sopenharmony_ci        attr = self.getAttributeNodeNS(namespaceURI, localname)
7627db96d56Sopenharmony_ci        if attr is None:
7637db96d56Sopenharmony_ci            attr = Attr(qualifiedName, namespaceURI, localname, prefix)
7647db96d56Sopenharmony_ci            attr.value = value
7657db96d56Sopenharmony_ci            attr.ownerDocument = self.ownerDocument
7667db96d56Sopenharmony_ci            self.setAttributeNode(attr)
7677db96d56Sopenharmony_ci        else:
7687db96d56Sopenharmony_ci            if value != attr.value:
7697db96d56Sopenharmony_ci                attr.value = value
7707db96d56Sopenharmony_ci                if attr.isId:
7717db96d56Sopenharmony_ci                    _clear_id_cache(self)
7727db96d56Sopenharmony_ci            if attr.prefix != prefix:
7737db96d56Sopenharmony_ci                attr.prefix = prefix
7747db96d56Sopenharmony_ci                attr.nodeName = qualifiedName
7757db96d56Sopenharmony_ci
7767db96d56Sopenharmony_ci    def getAttributeNode(self, attrname):
7777db96d56Sopenharmony_ci        if self._attrs is None:
7787db96d56Sopenharmony_ci            return None
7797db96d56Sopenharmony_ci        return self._attrs.get(attrname)
7807db96d56Sopenharmony_ci
7817db96d56Sopenharmony_ci    def getAttributeNodeNS(self, namespaceURI, localName):
7827db96d56Sopenharmony_ci        if self._attrsNS is None:
7837db96d56Sopenharmony_ci            return None
7847db96d56Sopenharmony_ci        return self._attrsNS.get((namespaceURI, localName))
7857db96d56Sopenharmony_ci
7867db96d56Sopenharmony_ci    def setAttributeNode(self, attr):
7877db96d56Sopenharmony_ci        if attr.ownerElement not in (None, self):
7887db96d56Sopenharmony_ci            raise xml.dom.InuseAttributeErr("attribute node already owned")
7897db96d56Sopenharmony_ci        self._ensure_attributes()
7907db96d56Sopenharmony_ci        old1 = self._attrs.get(attr.name, None)
7917db96d56Sopenharmony_ci        if old1 is not None:
7927db96d56Sopenharmony_ci            self.removeAttributeNode(old1)
7937db96d56Sopenharmony_ci        old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
7947db96d56Sopenharmony_ci        if old2 is not None and old2 is not old1:
7957db96d56Sopenharmony_ci            self.removeAttributeNode(old2)
7967db96d56Sopenharmony_ci        _set_attribute_node(self, attr)
7977db96d56Sopenharmony_ci
7987db96d56Sopenharmony_ci        if old1 is not attr:
7997db96d56Sopenharmony_ci            # It might have already been part of this node, in which case
8007db96d56Sopenharmony_ci            # it doesn't represent a change, and should not be returned.
8017db96d56Sopenharmony_ci            return old1
8027db96d56Sopenharmony_ci        if old2 is not attr:
8037db96d56Sopenharmony_ci            return old2
8047db96d56Sopenharmony_ci
8057db96d56Sopenharmony_ci    setAttributeNodeNS = setAttributeNode
8067db96d56Sopenharmony_ci
8077db96d56Sopenharmony_ci    def removeAttribute(self, name):
8087db96d56Sopenharmony_ci        if self._attrsNS is None:
8097db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
8107db96d56Sopenharmony_ci        try:
8117db96d56Sopenharmony_ci            attr = self._attrs[name]
8127db96d56Sopenharmony_ci        except KeyError:
8137db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
8147db96d56Sopenharmony_ci        self.removeAttributeNode(attr)
8157db96d56Sopenharmony_ci
8167db96d56Sopenharmony_ci    def removeAttributeNS(self, namespaceURI, localName):
8177db96d56Sopenharmony_ci        if self._attrsNS is None:
8187db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
8197db96d56Sopenharmony_ci        try:
8207db96d56Sopenharmony_ci            attr = self._attrsNS[(namespaceURI, localName)]
8217db96d56Sopenharmony_ci        except KeyError:
8227db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
8237db96d56Sopenharmony_ci        self.removeAttributeNode(attr)
8247db96d56Sopenharmony_ci
8257db96d56Sopenharmony_ci    def removeAttributeNode(self, node):
8267db96d56Sopenharmony_ci        if node is None:
8277db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
8287db96d56Sopenharmony_ci        try:
8297db96d56Sopenharmony_ci            self._attrs[node.name]
8307db96d56Sopenharmony_ci        except KeyError:
8317db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
8327db96d56Sopenharmony_ci        _clear_id_cache(self)
8337db96d56Sopenharmony_ci        node.unlink()
8347db96d56Sopenharmony_ci        # Restore this since the node is still useful and otherwise
8357db96d56Sopenharmony_ci        # unlinked
8367db96d56Sopenharmony_ci        node.ownerDocument = self.ownerDocument
8377db96d56Sopenharmony_ci        return node
8387db96d56Sopenharmony_ci
8397db96d56Sopenharmony_ci    removeAttributeNodeNS = removeAttributeNode
8407db96d56Sopenharmony_ci
8417db96d56Sopenharmony_ci    def hasAttribute(self, name):
8427db96d56Sopenharmony_ci        """Checks whether the element has an attribute with the specified name.
8437db96d56Sopenharmony_ci
8447db96d56Sopenharmony_ci        Returns True if the element has an attribute with the specified name.
8457db96d56Sopenharmony_ci        Otherwise, returns False.
8467db96d56Sopenharmony_ci        """
8477db96d56Sopenharmony_ci        if self._attrs is None:
8487db96d56Sopenharmony_ci            return False
8497db96d56Sopenharmony_ci        return name in self._attrs
8507db96d56Sopenharmony_ci
8517db96d56Sopenharmony_ci    def hasAttributeNS(self, namespaceURI, localName):
8527db96d56Sopenharmony_ci        if self._attrsNS is None:
8537db96d56Sopenharmony_ci            return False
8547db96d56Sopenharmony_ci        return (namespaceURI, localName) in self._attrsNS
8557db96d56Sopenharmony_ci
8567db96d56Sopenharmony_ci    def getElementsByTagName(self, name):
8577db96d56Sopenharmony_ci        """Returns all descendant elements with the given tag name.
8587db96d56Sopenharmony_ci
8597db96d56Sopenharmony_ci        Returns the list of all descendant elements (not direct children
8607db96d56Sopenharmony_ci        only) with the specified tag name.
8617db96d56Sopenharmony_ci        """
8627db96d56Sopenharmony_ci        return _get_elements_by_tagName_helper(self, name, NodeList())
8637db96d56Sopenharmony_ci
8647db96d56Sopenharmony_ci    def getElementsByTagNameNS(self, namespaceURI, localName):
8657db96d56Sopenharmony_ci        return _get_elements_by_tagName_ns_helper(
8667db96d56Sopenharmony_ci            self, namespaceURI, localName, NodeList())
8677db96d56Sopenharmony_ci
8687db96d56Sopenharmony_ci    def __repr__(self):
8697db96d56Sopenharmony_ci        return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
8707db96d56Sopenharmony_ci
8717db96d56Sopenharmony_ci    def writexml(self, writer, indent="", addindent="", newl=""):
8727db96d56Sopenharmony_ci        """Write an XML element to a file-like object
8737db96d56Sopenharmony_ci
8747db96d56Sopenharmony_ci        Write the element to the writer object that must provide
8757db96d56Sopenharmony_ci        a write method (e.g. a file or StringIO object).
8767db96d56Sopenharmony_ci        """
8777db96d56Sopenharmony_ci        # indent = current indentation
8787db96d56Sopenharmony_ci        # addindent = indentation to add to higher levels
8797db96d56Sopenharmony_ci        # newl = newline string
8807db96d56Sopenharmony_ci        writer.write(indent+"<" + self.tagName)
8817db96d56Sopenharmony_ci
8827db96d56Sopenharmony_ci        attrs = self._get_attributes()
8837db96d56Sopenharmony_ci
8847db96d56Sopenharmony_ci        for a_name in attrs.keys():
8857db96d56Sopenharmony_ci            writer.write(" %s=\"" % a_name)
8867db96d56Sopenharmony_ci            _write_data(writer, attrs[a_name].value)
8877db96d56Sopenharmony_ci            writer.write("\"")
8887db96d56Sopenharmony_ci        if self.childNodes:
8897db96d56Sopenharmony_ci            writer.write(">")
8907db96d56Sopenharmony_ci            if (len(self.childNodes) == 1 and
8917db96d56Sopenharmony_ci                self.childNodes[0].nodeType in (
8927db96d56Sopenharmony_ci                        Node.TEXT_NODE, Node.CDATA_SECTION_NODE)):
8937db96d56Sopenharmony_ci                self.childNodes[0].writexml(writer, '', '', '')
8947db96d56Sopenharmony_ci            else:
8957db96d56Sopenharmony_ci                writer.write(newl)
8967db96d56Sopenharmony_ci                for node in self.childNodes:
8977db96d56Sopenharmony_ci                    node.writexml(writer, indent+addindent, addindent, newl)
8987db96d56Sopenharmony_ci                writer.write(indent)
8997db96d56Sopenharmony_ci            writer.write("</%s>%s" % (self.tagName, newl))
9007db96d56Sopenharmony_ci        else:
9017db96d56Sopenharmony_ci            writer.write("/>%s"%(newl))
9027db96d56Sopenharmony_ci
9037db96d56Sopenharmony_ci    def _get_attributes(self):
9047db96d56Sopenharmony_ci        self._ensure_attributes()
9057db96d56Sopenharmony_ci        return NamedNodeMap(self._attrs, self._attrsNS, self)
9067db96d56Sopenharmony_ci
9077db96d56Sopenharmony_ci    def hasAttributes(self):
9087db96d56Sopenharmony_ci        if self._attrs:
9097db96d56Sopenharmony_ci            return True
9107db96d56Sopenharmony_ci        else:
9117db96d56Sopenharmony_ci            return False
9127db96d56Sopenharmony_ci
9137db96d56Sopenharmony_ci    # DOM Level 3 attributes, based on the 22 Oct 2002 draft
9147db96d56Sopenharmony_ci
9157db96d56Sopenharmony_ci    def setIdAttribute(self, name):
9167db96d56Sopenharmony_ci        idAttr = self.getAttributeNode(name)
9177db96d56Sopenharmony_ci        self.setIdAttributeNode(idAttr)
9187db96d56Sopenharmony_ci
9197db96d56Sopenharmony_ci    def setIdAttributeNS(self, namespaceURI, localName):
9207db96d56Sopenharmony_ci        idAttr = self.getAttributeNodeNS(namespaceURI, localName)
9217db96d56Sopenharmony_ci        self.setIdAttributeNode(idAttr)
9227db96d56Sopenharmony_ci
9237db96d56Sopenharmony_ci    def setIdAttributeNode(self, idAttr):
9247db96d56Sopenharmony_ci        if idAttr is None or not self.isSameNode(idAttr.ownerElement):
9257db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
9267db96d56Sopenharmony_ci        if _get_containing_entref(self) is not None:
9277db96d56Sopenharmony_ci            raise xml.dom.NoModificationAllowedErr()
9287db96d56Sopenharmony_ci        if not idAttr._is_id:
9297db96d56Sopenharmony_ci            idAttr._is_id = True
9307db96d56Sopenharmony_ci            self._magic_id_nodes += 1
9317db96d56Sopenharmony_ci            self.ownerDocument._magic_id_count += 1
9327db96d56Sopenharmony_ci            _clear_id_cache(self)
9337db96d56Sopenharmony_ci
9347db96d56Sopenharmony_cidefproperty(Element, "attributes",
9357db96d56Sopenharmony_ci            doc="NamedNodeMap of attributes on the element.")
9367db96d56Sopenharmony_cidefproperty(Element, "localName",
9377db96d56Sopenharmony_ci            doc="Namespace-local name of this element.")
9387db96d56Sopenharmony_ci
9397db96d56Sopenharmony_ci
9407db96d56Sopenharmony_cidef _set_attribute_node(element, attr):
9417db96d56Sopenharmony_ci    _clear_id_cache(element)
9427db96d56Sopenharmony_ci    element._ensure_attributes()
9437db96d56Sopenharmony_ci    element._attrs[attr.name] = attr
9447db96d56Sopenharmony_ci    element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
9457db96d56Sopenharmony_ci
9467db96d56Sopenharmony_ci    # This creates a circular reference, but Element.unlink()
9477db96d56Sopenharmony_ci    # breaks the cycle since the references to the attribute
9487db96d56Sopenharmony_ci    # dictionaries are tossed.
9497db96d56Sopenharmony_ci    attr.ownerElement = element
9507db96d56Sopenharmony_ci
9517db96d56Sopenharmony_ciclass Childless:
9527db96d56Sopenharmony_ci    """Mixin that makes childless-ness easy to implement and avoids
9537db96d56Sopenharmony_ci    the complexity of the Node methods that deal with children.
9547db96d56Sopenharmony_ci    """
9557db96d56Sopenharmony_ci    __slots__ = ()
9567db96d56Sopenharmony_ci
9577db96d56Sopenharmony_ci    attributes = None
9587db96d56Sopenharmony_ci    childNodes = EmptyNodeList()
9597db96d56Sopenharmony_ci    firstChild = None
9607db96d56Sopenharmony_ci    lastChild = None
9617db96d56Sopenharmony_ci
9627db96d56Sopenharmony_ci    def _get_firstChild(self):
9637db96d56Sopenharmony_ci        return None
9647db96d56Sopenharmony_ci
9657db96d56Sopenharmony_ci    def _get_lastChild(self):
9667db96d56Sopenharmony_ci        return None
9677db96d56Sopenharmony_ci
9687db96d56Sopenharmony_ci    def appendChild(self, node):
9697db96d56Sopenharmony_ci        raise xml.dom.HierarchyRequestErr(
9707db96d56Sopenharmony_ci            self.nodeName + " nodes cannot have children")
9717db96d56Sopenharmony_ci
9727db96d56Sopenharmony_ci    def hasChildNodes(self):
9737db96d56Sopenharmony_ci        return False
9747db96d56Sopenharmony_ci
9757db96d56Sopenharmony_ci    def insertBefore(self, newChild, refChild):
9767db96d56Sopenharmony_ci        raise xml.dom.HierarchyRequestErr(
9777db96d56Sopenharmony_ci            self.nodeName + " nodes do not have children")
9787db96d56Sopenharmony_ci
9797db96d56Sopenharmony_ci    def removeChild(self, oldChild):
9807db96d56Sopenharmony_ci        raise xml.dom.NotFoundErr(
9817db96d56Sopenharmony_ci            self.nodeName + " nodes do not have children")
9827db96d56Sopenharmony_ci
9837db96d56Sopenharmony_ci    def normalize(self):
9847db96d56Sopenharmony_ci        # For childless nodes, normalize() has nothing to do.
9857db96d56Sopenharmony_ci        pass
9867db96d56Sopenharmony_ci
9877db96d56Sopenharmony_ci    def replaceChild(self, newChild, oldChild):
9887db96d56Sopenharmony_ci        raise xml.dom.HierarchyRequestErr(
9897db96d56Sopenharmony_ci            self.nodeName + " nodes do not have children")
9907db96d56Sopenharmony_ci
9917db96d56Sopenharmony_ci
9927db96d56Sopenharmony_ciclass ProcessingInstruction(Childless, Node):
9937db96d56Sopenharmony_ci    nodeType = Node.PROCESSING_INSTRUCTION_NODE
9947db96d56Sopenharmony_ci    __slots__ = ('target', 'data')
9957db96d56Sopenharmony_ci
9967db96d56Sopenharmony_ci    def __init__(self, target, data):
9977db96d56Sopenharmony_ci        self.target = target
9987db96d56Sopenharmony_ci        self.data = data
9997db96d56Sopenharmony_ci
10007db96d56Sopenharmony_ci    # nodeValue is an alias for data
10017db96d56Sopenharmony_ci    def _get_nodeValue(self):
10027db96d56Sopenharmony_ci        return self.data
10037db96d56Sopenharmony_ci    def _set_nodeValue(self, value):
10047db96d56Sopenharmony_ci        self.data = value
10057db96d56Sopenharmony_ci    nodeValue = property(_get_nodeValue, _set_nodeValue)
10067db96d56Sopenharmony_ci
10077db96d56Sopenharmony_ci    # nodeName is an alias for target
10087db96d56Sopenharmony_ci    def _get_nodeName(self):
10097db96d56Sopenharmony_ci        return self.target
10107db96d56Sopenharmony_ci    def _set_nodeName(self, value):
10117db96d56Sopenharmony_ci        self.target = value
10127db96d56Sopenharmony_ci    nodeName = property(_get_nodeName, _set_nodeName)
10137db96d56Sopenharmony_ci
10147db96d56Sopenharmony_ci    def writexml(self, writer, indent="", addindent="", newl=""):
10157db96d56Sopenharmony_ci        writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
10167db96d56Sopenharmony_ci
10177db96d56Sopenharmony_ci
10187db96d56Sopenharmony_ciclass CharacterData(Childless, Node):
10197db96d56Sopenharmony_ci    __slots__=('_data', 'ownerDocument','parentNode', 'previousSibling', 'nextSibling')
10207db96d56Sopenharmony_ci
10217db96d56Sopenharmony_ci    def __init__(self):
10227db96d56Sopenharmony_ci        self.ownerDocument = self.parentNode = None
10237db96d56Sopenharmony_ci        self.previousSibling = self.nextSibling = None
10247db96d56Sopenharmony_ci        self._data = ''
10257db96d56Sopenharmony_ci        Node.__init__(self)
10267db96d56Sopenharmony_ci
10277db96d56Sopenharmony_ci    def _get_length(self):
10287db96d56Sopenharmony_ci        return len(self.data)
10297db96d56Sopenharmony_ci    __len__ = _get_length
10307db96d56Sopenharmony_ci
10317db96d56Sopenharmony_ci    def _get_data(self):
10327db96d56Sopenharmony_ci        return self._data
10337db96d56Sopenharmony_ci    def _set_data(self, data):
10347db96d56Sopenharmony_ci        self._data = data
10357db96d56Sopenharmony_ci
10367db96d56Sopenharmony_ci    data = nodeValue = property(_get_data, _set_data)
10377db96d56Sopenharmony_ci
10387db96d56Sopenharmony_ci    def __repr__(self):
10397db96d56Sopenharmony_ci        data = self.data
10407db96d56Sopenharmony_ci        if len(data) > 10:
10417db96d56Sopenharmony_ci            dotdotdot = "..."
10427db96d56Sopenharmony_ci        else:
10437db96d56Sopenharmony_ci            dotdotdot = ""
10447db96d56Sopenharmony_ci        return '<DOM %s node "%r%s">' % (
10457db96d56Sopenharmony_ci            self.__class__.__name__, data[0:10], dotdotdot)
10467db96d56Sopenharmony_ci
10477db96d56Sopenharmony_ci    def substringData(self, offset, count):
10487db96d56Sopenharmony_ci        if offset < 0:
10497db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("offset cannot be negative")
10507db96d56Sopenharmony_ci        if offset >= len(self.data):
10517db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
10527db96d56Sopenharmony_ci        if count < 0:
10537db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("count cannot be negative")
10547db96d56Sopenharmony_ci        return self.data[offset:offset+count]
10557db96d56Sopenharmony_ci
10567db96d56Sopenharmony_ci    def appendData(self, arg):
10577db96d56Sopenharmony_ci        self.data = self.data + arg
10587db96d56Sopenharmony_ci
10597db96d56Sopenharmony_ci    def insertData(self, offset, arg):
10607db96d56Sopenharmony_ci        if offset < 0:
10617db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("offset cannot be negative")
10627db96d56Sopenharmony_ci        if offset >= len(self.data):
10637db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
10647db96d56Sopenharmony_ci        if arg:
10657db96d56Sopenharmony_ci            self.data = "%s%s%s" % (
10667db96d56Sopenharmony_ci                self.data[:offset], arg, self.data[offset:])
10677db96d56Sopenharmony_ci
10687db96d56Sopenharmony_ci    def deleteData(self, offset, count):
10697db96d56Sopenharmony_ci        if offset < 0:
10707db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("offset cannot be negative")
10717db96d56Sopenharmony_ci        if offset >= len(self.data):
10727db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
10737db96d56Sopenharmony_ci        if count < 0:
10747db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("count cannot be negative")
10757db96d56Sopenharmony_ci        if count:
10767db96d56Sopenharmony_ci            self.data = self.data[:offset] + self.data[offset+count:]
10777db96d56Sopenharmony_ci
10787db96d56Sopenharmony_ci    def replaceData(self, offset, count, arg):
10797db96d56Sopenharmony_ci        if offset < 0:
10807db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("offset cannot be negative")
10817db96d56Sopenharmony_ci        if offset >= len(self.data):
10827db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
10837db96d56Sopenharmony_ci        if count < 0:
10847db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("count cannot be negative")
10857db96d56Sopenharmony_ci        if count:
10867db96d56Sopenharmony_ci            self.data = "%s%s%s" % (
10877db96d56Sopenharmony_ci                self.data[:offset], arg, self.data[offset+count:])
10887db96d56Sopenharmony_ci
10897db96d56Sopenharmony_cidefproperty(CharacterData, "length", doc="Length of the string data.")
10907db96d56Sopenharmony_ci
10917db96d56Sopenharmony_ci
10927db96d56Sopenharmony_ciclass Text(CharacterData):
10937db96d56Sopenharmony_ci    __slots__ = ()
10947db96d56Sopenharmony_ci
10957db96d56Sopenharmony_ci    nodeType = Node.TEXT_NODE
10967db96d56Sopenharmony_ci    nodeName = "#text"
10977db96d56Sopenharmony_ci    attributes = None
10987db96d56Sopenharmony_ci
10997db96d56Sopenharmony_ci    def splitText(self, offset):
11007db96d56Sopenharmony_ci        if offset < 0 or offset > len(self.data):
11017db96d56Sopenharmony_ci            raise xml.dom.IndexSizeErr("illegal offset value")
11027db96d56Sopenharmony_ci        newText = self.__class__()
11037db96d56Sopenharmony_ci        newText.data = self.data[offset:]
11047db96d56Sopenharmony_ci        newText.ownerDocument = self.ownerDocument
11057db96d56Sopenharmony_ci        next = self.nextSibling
11067db96d56Sopenharmony_ci        if self.parentNode and self in self.parentNode.childNodes:
11077db96d56Sopenharmony_ci            if next is None:
11087db96d56Sopenharmony_ci                self.parentNode.appendChild(newText)
11097db96d56Sopenharmony_ci            else:
11107db96d56Sopenharmony_ci                self.parentNode.insertBefore(newText, next)
11117db96d56Sopenharmony_ci        self.data = self.data[:offset]
11127db96d56Sopenharmony_ci        return newText
11137db96d56Sopenharmony_ci
11147db96d56Sopenharmony_ci    def writexml(self, writer, indent="", addindent="", newl=""):
11157db96d56Sopenharmony_ci        _write_data(writer, "%s%s%s" % (indent, self.data, newl))
11167db96d56Sopenharmony_ci
11177db96d56Sopenharmony_ci    # DOM Level 3 (WD 9 April 2002)
11187db96d56Sopenharmony_ci
11197db96d56Sopenharmony_ci    def _get_wholeText(self):
11207db96d56Sopenharmony_ci        L = [self.data]
11217db96d56Sopenharmony_ci        n = self.previousSibling
11227db96d56Sopenharmony_ci        while n is not None:
11237db96d56Sopenharmony_ci            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
11247db96d56Sopenharmony_ci                L.insert(0, n.data)
11257db96d56Sopenharmony_ci                n = n.previousSibling
11267db96d56Sopenharmony_ci            else:
11277db96d56Sopenharmony_ci                break
11287db96d56Sopenharmony_ci        n = self.nextSibling
11297db96d56Sopenharmony_ci        while n is not None:
11307db96d56Sopenharmony_ci            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
11317db96d56Sopenharmony_ci                L.append(n.data)
11327db96d56Sopenharmony_ci                n = n.nextSibling
11337db96d56Sopenharmony_ci            else:
11347db96d56Sopenharmony_ci                break
11357db96d56Sopenharmony_ci        return ''.join(L)
11367db96d56Sopenharmony_ci
11377db96d56Sopenharmony_ci    def replaceWholeText(self, content):
11387db96d56Sopenharmony_ci        # XXX This needs to be seriously changed if minidom ever
11397db96d56Sopenharmony_ci        # supports EntityReference nodes.
11407db96d56Sopenharmony_ci        parent = self.parentNode
11417db96d56Sopenharmony_ci        n = self.previousSibling
11427db96d56Sopenharmony_ci        while n is not None:
11437db96d56Sopenharmony_ci            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
11447db96d56Sopenharmony_ci                next = n.previousSibling
11457db96d56Sopenharmony_ci                parent.removeChild(n)
11467db96d56Sopenharmony_ci                n = next
11477db96d56Sopenharmony_ci            else:
11487db96d56Sopenharmony_ci                break
11497db96d56Sopenharmony_ci        n = self.nextSibling
11507db96d56Sopenharmony_ci        if not content:
11517db96d56Sopenharmony_ci            parent.removeChild(self)
11527db96d56Sopenharmony_ci        while n is not None:
11537db96d56Sopenharmony_ci            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
11547db96d56Sopenharmony_ci                next = n.nextSibling
11557db96d56Sopenharmony_ci                parent.removeChild(n)
11567db96d56Sopenharmony_ci                n = next
11577db96d56Sopenharmony_ci            else:
11587db96d56Sopenharmony_ci                break
11597db96d56Sopenharmony_ci        if content:
11607db96d56Sopenharmony_ci            self.data = content
11617db96d56Sopenharmony_ci            return self
11627db96d56Sopenharmony_ci        else:
11637db96d56Sopenharmony_ci            return None
11647db96d56Sopenharmony_ci
11657db96d56Sopenharmony_ci    def _get_isWhitespaceInElementContent(self):
11667db96d56Sopenharmony_ci        if self.data.strip():
11677db96d56Sopenharmony_ci            return False
11687db96d56Sopenharmony_ci        elem = _get_containing_element(self)
11697db96d56Sopenharmony_ci        if elem is None:
11707db96d56Sopenharmony_ci            return False
11717db96d56Sopenharmony_ci        info = self.ownerDocument._get_elem_info(elem)
11727db96d56Sopenharmony_ci        if info is None:
11737db96d56Sopenharmony_ci            return False
11747db96d56Sopenharmony_ci        else:
11757db96d56Sopenharmony_ci            return info.isElementContent()
11767db96d56Sopenharmony_ci
11777db96d56Sopenharmony_cidefproperty(Text, "isWhitespaceInElementContent",
11787db96d56Sopenharmony_ci            doc="True iff this text node contains only whitespace"
11797db96d56Sopenharmony_ci                " and is in element content.")
11807db96d56Sopenharmony_cidefproperty(Text, "wholeText",
11817db96d56Sopenharmony_ci            doc="The text of all logically-adjacent text nodes.")
11827db96d56Sopenharmony_ci
11837db96d56Sopenharmony_ci
11847db96d56Sopenharmony_cidef _get_containing_element(node):
11857db96d56Sopenharmony_ci    c = node.parentNode
11867db96d56Sopenharmony_ci    while c is not None:
11877db96d56Sopenharmony_ci        if c.nodeType == Node.ELEMENT_NODE:
11887db96d56Sopenharmony_ci            return c
11897db96d56Sopenharmony_ci        c = c.parentNode
11907db96d56Sopenharmony_ci    return None
11917db96d56Sopenharmony_ci
11927db96d56Sopenharmony_cidef _get_containing_entref(node):
11937db96d56Sopenharmony_ci    c = node.parentNode
11947db96d56Sopenharmony_ci    while c is not None:
11957db96d56Sopenharmony_ci        if c.nodeType == Node.ENTITY_REFERENCE_NODE:
11967db96d56Sopenharmony_ci            return c
11977db96d56Sopenharmony_ci        c = c.parentNode
11987db96d56Sopenharmony_ci    return None
11997db96d56Sopenharmony_ci
12007db96d56Sopenharmony_ci
12017db96d56Sopenharmony_ciclass Comment(CharacterData):
12027db96d56Sopenharmony_ci    nodeType = Node.COMMENT_NODE
12037db96d56Sopenharmony_ci    nodeName = "#comment"
12047db96d56Sopenharmony_ci
12057db96d56Sopenharmony_ci    def __init__(self, data):
12067db96d56Sopenharmony_ci        CharacterData.__init__(self)
12077db96d56Sopenharmony_ci        self._data = data
12087db96d56Sopenharmony_ci
12097db96d56Sopenharmony_ci    def writexml(self, writer, indent="", addindent="", newl=""):
12107db96d56Sopenharmony_ci        if "--" in self.data:
12117db96d56Sopenharmony_ci            raise ValueError("'--' is not allowed in a comment node")
12127db96d56Sopenharmony_ci        writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
12137db96d56Sopenharmony_ci
12147db96d56Sopenharmony_ci
12157db96d56Sopenharmony_ciclass CDATASection(Text):
12167db96d56Sopenharmony_ci    __slots__ = ()
12177db96d56Sopenharmony_ci
12187db96d56Sopenharmony_ci    nodeType = Node.CDATA_SECTION_NODE
12197db96d56Sopenharmony_ci    nodeName = "#cdata-section"
12207db96d56Sopenharmony_ci
12217db96d56Sopenharmony_ci    def writexml(self, writer, indent="", addindent="", newl=""):
12227db96d56Sopenharmony_ci        if self.data.find("]]>") >= 0:
12237db96d56Sopenharmony_ci            raise ValueError("']]>' not allowed in a CDATA section")
12247db96d56Sopenharmony_ci        writer.write("<![CDATA[%s]]>" % self.data)
12257db96d56Sopenharmony_ci
12267db96d56Sopenharmony_ci
12277db96d56Sopenharmony_ciclass ReadOnlySequentialNamedNodeMap(object):
12287db96d56Sopenharmony_ci    __slots__ = '_seq',
12297db96d56Sopenharmony_ci
12307db96d56Sopenharmony_ci    def __init__(self, seq=()):
12317db96d56Sopenharmony_ci        # seq should be a list or tuple
12327db96d56Sopenharmony_ci        self._seq = seq
12337db96d56Sopenharmony_ci
12347db96d56Sopenharmony_ci    def __len__(self):
12357db96d56Sopenharmony_ci        return len(self._seq)
12367db96d56Sopenharmony_ci
12377db96d56Sopenharmony_ci    def _get_length(self):
12387db96d56Sopenharmony_ci        return len(self._seq)
12397db96d56Sopenharmony_ci
12407db96d56Sopenharmony_ci    def getNamedItem(self, name):
12417db96d56Sopenharmony_ci        for n in self._seq:
12427db96d56Sopenharmony_ci            if n.nodeName == name:
12437db96d56Sopenharmony_ci                return n
12447db96d56Sopenharmony_ci
12457db96d56Sopenharmony_ci    def getNamedItemNS(self, namespaceURI, localName):
12467db96d56Sopenharmony_ci        for n in self._seq:
12477db96d56Sopenharmony_ci            if n.namespaceURI == namespaceURI and n.localName == localName:
12487db96d56Sopenharmony_ci                return n
12497db96d56Sopenharmony_ci
12507db96d56Sopenharmony_ci    def __getitem__(self, name_or_tuple):
12517db96d56Sopenharmony_ci        if isinstance(name_or_tuple, tuple):
12527db96d56Sopenharmony_ci            node = self.getNamedItemNS(*name_or_tuple)
12537db96d56Sopenharmony_ci        else:
12547db96d56Sopenharmony_ci            node = self.getNamedItem(name_or_tuple)
12557db96d56Sopenharmony_ci        if node is None:
12567db96d56Sopenharmony_ci            raise KeyError(name_or_tuple)
12577db96d56Sopenharmony_ci        return node
12587db96d56Sopenharmony_ci
12597db96d56Sopenharmony_ci    def item(self, index):
12607db96d56Sopenharmony_ci        if index < 0:
12617db96d56Sopenharmony_ci            return None
12627db96d56Sopenharmony_ci        try:
12637db96d56Sopenharmony_ci            return self._seq[index]
12647db96d56Sopenharmony_ci        except IndexError:
12657db96d56Sopenharmony_ci            return None
12667db96d56Sopenharmony_ci
12677db96d56Sopenharmony_ci    def removeNamedItem(self, name):
12687db96d56Sopenharmony_ci        raise xml.dom.NoModificationAllowedErr(
12697db96d56Sopenharmony_ci            "NamedNodeMap instance is read-only")
12707db96d56Sopenharmony_ci
12717db96d56Sopenharmony_ci    def removeNamedItemNS(self, namespaceURI, localName):
12727db96d56Sopenharmony_ci        raise xml.dom.NoModificationAllowedErr(
12737db96d56Sopenharmony_ci            "NamedNodeMap instance is read-only")
12747db96d56Sopenharmony_ci
12757db96d56Sopenharmony_ci    def setNamedItem(self, node):
12767db96d56Sopenharmony_ci        raise xml.dom.NoModificationAllowedErr(
12777db96d56Sopenharmony_ci            "NamedNodeMap instance is read-only")
12787db96d56Sopenharmony_ci
12797db96d56Sopenharmony_ci    def setNamedItemNS(self, node):
12807db96d56Sopenharmony_ci        raise xml.dom.NoModificationAllowedErr(
12817db96d56Sopenharmony_ci            "NamedNodeMap instance is read-only")
12827db96d56Sopenharmony_ci
12837db96d56Sopenharmony_ci    def __getstate__(self):
12847db96d56Sopenharmony_ci        return [self._seq]
12857db96d56Sopenharmony_ci
12867db96d56Sopenharmony_ci    def __setstate__(self, state):
12877db96d56Sopenharmony_ci        self._seq = state[0]
12887db96d56Sopenharmony_ci
12897db96d56Sopenharmony_cidefproperty(ReadOnlySequentialNamedNodeMap, "length",
12907db96d56Sopenharmony_ci            doc="Number of entries in the NamedNodeMap.")
12917db96d56Sopenharmony_ci
12927db96d56Sopenharmony_ci
12937db96d56Sopenharmony_ciclass Identified:
12947db96d56Sopenharmony_ci    """Mix-in class that supports the publicId and systemId attributes."""
12957db96d56Sopenharmony_ci
12967db96d56Sopenharmony_ci    __slots__ = 'publicId', 'systemId'
12977db96d56Sopenharmony_ci
12987db96d56Sopenharmony_ci    def _identified_mixin_init(self, publicId, systemId):
12997db96d56Sopenharmony_ci        self.publicId = publicId
13007db96d56Sopenharmony_ci        self.systemId = systemId
13017db96d56Sopenharmony_ci
13027db96d56Sopenharmony_ci    def _get_publicId(self):
13037db96d56Sopenharmony_ci        return self.publicId
13047db96d56Sopenharmony_ci
13057db96d56Sopenharmony_ci    def _get_systemId(self):
13067db96d56Sopenharmony_ci        return self.systemId
13077db96d56Sopenharmony_ci
13087db96d56Sopenharmony_ciclass DocumentType(Identified, Childless, Node):
13097db96d56Sopenharmony_ci    nodeType = Node.DOCUMENT_TYPE_NODE
13107db96d56Sopenharmony_ci    nodeValue = None
13117db96d56Sopenharmony_ci    name = None
13127db96d56Sopenharmony_ci    publicId = None
13137db96d56Sopenharmony_ci    systemId = None
13147db96d56Sopenharmony_ci    internalSubset = None
13157db96d56Sopenharmony_ci
13167db96d56Sopenharmony_ci    def __init__(self, qualifiedName):
13177db96d56Sopenharmony_ci        self.entities = ReadOnlySequentialNamedNodeMap()
13187db96d56Sopenharmony_ci        self.notations = ReadOnlySequentialNamedNodeMap()
13197db96d56Sopenharmony_ci        if qualifiedName:
13207db96d56Sopenharmony_ci            prefix, localname = _nssplit(qualifiedName)
13217db96d56Sopenharmony_ci            self.name = localname
13227db96d56Sopenharmony_ci        self.nodeName = self.name
13237db96d56Sopenharmony_ci
13247db96d56Sopenharmony_ci    def _get_internalSubset(self):
13257db96d56Sopenharmony_ci        return self.internalSubset
13267db96d56Sopenharmony_ci
13277db96d56Sopenharmony_ci    def cloneNode(self, deep):
13287db96d56Sopenharmony_ci        if self.ownerDocument is None:
13297db96d56Sopenharmony_ci            # it's ok
13307db96d56Sopenharmony_ci            clone = DocumentType(None)
13317db96d56Sopenharmony_ci            clone.name = self.name
13327db96d56Sopenharmony_ci            clone.nodeName = self.name
13337db96d56Sopenharmony_ci            operation = xml.dom.UserDataHandler.NODE_CLONED
13347db96d56Sopenharmony_ci            if deep:
13357db96d56Sopenharmony_ci                clone.entities._seq = []
13367db96d56Sopenharmony_ci                clone.notations._seq = []
13377db96d56Sopenharmony_ci                for n in self.notations._seq:
13387db96d56Sopenharmony_ci                    notation = Notation(n.nodeName, n.publicId, n.systemId)
13397db96d56Sopenharmony_ci                    clone.notations._seq.append(notation)
13407db96d56Sopenharmony_ci                    n._call_user_data_handler(operation, n, notation)
13417db96d56Sopenharmony_ci                for e in self.entities._seq:
13427db96d56Sopenharmony_ci                    entity = Entity(e.nodeName, e.publicId, e.systemId,
13437db96d56Sopenharmony_ci                                    e.notationName)
13447db96d56Sopenharmony_ci                    entity.actualEncoding = e.actualEncoding
13457db96d56Sopenharmony_ci                    entity.encoding = e.encoding
13467db96d56Sopenharmony_ci                    entity.version = e.version
13477db96d56Sopenharmony_ci                    clone.entities._seq.append(entity)
13487db96d56Sopenharmony_ci                    e._call_user_data_handler(operation, e, entity)
13497db96d56Sopenharmony_ci            self._call_user_data_handler(operation, self, clone)
13507db96d56Sopenharmony_ci            return clone
13517db96d56Sopenharmony_ci        else:
13527db96d56Sopenharmony_ci            return None
13537db96d56Sopenharmony_ci
13547db96d56Sopenharmony_ci    def writexml(self, writer, indent="", addindent="", newl=""):
13557db96d56Sopenharmony_ci        writer.write("<!DOCTYPE ")
13567db96d56Sopenharmony_ci        writer.write(self.name)
13577db96d56Sopenharmony_ci        if self.publicId:
13587db96d56Sopenharmony_ci            writer.write("%s  PUBLIC '%s'%s  '%s'"
13597db96d56Sopenharmony_ci                         % (newl, self.publicId, newl, self.systemId))
13607db96d56Sopenharmony_ci        elif self.systemId:
13617db96d56Sopenharmony_ci            writer.write("%s  SYSTEM '%s'" % (newl, self.systemId))
13627db96d56Sopenharmony_ci        if self.internalSubset is not None:
13637db96d56Sopenharmony_ci            writer.write(" [")
13647db96d56Sopenharmony_ci            writer.write(self.internalSubset)
13657db96d56Sopenharmony_ci            writer.write("]")
13667db96d56Sopenharmony_ci        writer.write(">"+newl)
13677db96d56Sopenharmony_ci
13687db96d56Sopenharmony_ciclass Entity(Identified, Node):
13697db96d56Sopenharmony_ci    attributes = None
13707db96d56Sopenharmony_ci    nodeType = Node.ENTITY_NODE
13717db96d56Sopenharmony_ci    nodeValue = None
13727db96d56Sopenharmony_ci
13737db96d56Sopenharmony_ci    actualEncoding = None
13747db96d56Sopenharmony_ci    encoding = None
13757db96d56Sopenharmony_ci    version = None
13767db96d56Sopenharmony_ci
13777db96d56Sopenharmony_ci    def __init__(self, name, publicId, systemId, notation):
13787db96d56Sopenharmony_ci        self.nodeName = name
13797db96d56Sopenharmony_ci        self.notationName = notation
13807db96d56Sopenharmony_ci        self.childNodes = NodeList()
13817db96d56Sopenharmony_ci        self._identified_mixin_init(publicId, systemId)
13827db96d56Sopenharmony_ci
13837db96d56Sopenharmony_ci    def _get_actualEncoding(self):
13847db96d56Sopenharmony_ci        return self.actualEncoding
13857db96d56Sopenharmony_ci
13867db96d56Sopenharmony_ci    def _get_encoding(self):
13877db96d56Sopenharmony_ci        return self.encoding
13887db96d56Sopenharmony_ci
13897db96d56Sopenharmony_ci    def _get_version(self):
13907db96d56Sopenharmony_ci        return self.version
13917db96d56Sopenharmony_ci
13927db96d56Sopenharmony_ci    def appendChild(self, newChild):
13937db96d56Sopenharmony_ci        raise xml.dom.HierarchyRequestErr(
13947db96d56Sopenharmony_ci            "cannot append children to an entity node")
13957db96d56Sopenharmony_ci
13967db96d56Sopenharmony_ci    def insertBefore(self, newChild, refChild):
13977db96d56Sopenharmony_ci        raise xml.dom.HierarchyRequestErr(
13987db96d56Sopenharmony_ci            "cannot insert children below an entity node")
13997db96d56Sopenharmony_ci
14007db96d56Sopenharmony_ci    def removeChild(self, oldChild):
14017db96d56Sopenharmony_ci        raise xml.dom.HierarchyRequestErr(
14027db96d56Sopenharmony_ci            "cannot remove children from an entity node")
14037db96d56Sopenharmony_ci
14047db96d56Sopenharmony_ci    def replaceChild(self, newChild, oldChild):
14057db96d56Sopenharmony_ci        raise xml.dom.HierarchyRequestErr(
14067db96d56Sopenharmony_ci            "cannot replace children of an entity node")
14077db96d56Sopenharmony_ci
14087db96d56Sopenharmony_ciclass Notation(Identified, Childless, Node):
14097db96d56Sopenharmony_ci    nodeType = Node.NOTATION_NODE
14107db96d56Sopenharmony_ci    nodeValue = None
14117db96d56Sopenharmony_ci
14127db96d56Sopenharmony_ci    def __init__(self, name, publicId, systemId):
14137db96d56Sopenharmony_ci        self.nodeName = name
14147db96d56Sopenharmony_ci        self._identified_mixin_init(publicId, systemId)
14157db96d56Sopenharmony_ci
14167db96d56Sopenharmony_ci
14177db96d56Sopenharmony_ciclass DOMImplementation(DOMImplementationLS):
14187db96d56Sopenharmony_ci    _features = [("core", "1.0"),
14197db96d56Sopenharmony_ci                 ("core", "2.0"),
14207db96d56Sopenharmony_ci                 ("core", None),
14217db96d56Sopenharmony_ci                 ("xml", "1.0"),
14227db96d56Sopenharmony_ci                 ("xml", "2.0"),
14237db96d56Sopenharmony_ci                 ("xml", None),
14247db96d56Sopenharmony_ci                 ("ls-load", "3.0"),
14257db96d56Sopenharmony_ci                 ("ls-load", None),
14267db96d56Sopenharmony_ci                 ]
14277db96d56Sopenharmony_ci
14287db96d56Sopenharmony_ci    def hasFeature(self, feature, version):
14297db96d56Sopenharmony_ci        if version == "":
14307db96d56Sopenharmony_ci            version = None
14317db96d56Sopenharmony_ci        return (feature.lower(), version) in self._features
14327db96d56Sopenharmony_ci
14337db96d56Sopenharmony_ci    def createDocument(self, namespaceURI, qualifiedName, doctype):
14347db96d56Sopenharmony_ci        if doctype and doctype.parentNode is not None:
14357db96d56Sopenharmony_ci            raise xml.dom.WrongDocumentErr(
14367db96d56Sopenharmony_ci                "doctype object owned by another DOM tree")
14377db96d56Sopenharmony_ci        doc = self._create_document()
14387db96d56Sopenharmony_ci
14397db96d56Sopenharmony_ci        add_root_element = not (namespaceURI is None
14407db96d56Sopenharmony_ci                                and qualifiedName is None
14417db96d56Sopenharmony_ci                                and doctype is None)
14427db96d56Sopenharmony_ci
14437db96d56Sopenharmony_ci        if not qualifiedName and add_root_element:
14447db96d56Sopenharmony_ci            # The spec is unclear what to raise here; SyntaxErr
14457db96d56Sopenharmony_ci            # would be the other obvious candidate. Since Xerces raises
14467db96d56Sopenharmony_ci            # InvalidCharacterErr, and since SyntaxErr is not listed
14477db96d56Sopenharmony_ci            # for createDocument, that seems to be the better choice.
14487db96d56Sopenharmony_ci            # XXX: need to check for illegal characters here and in
14497db96d56Sopenharmony_ci            # createElement.
14507db96d56Sopenharmony_ci
14517db96d56Sopenharmony_ci            # DOM Level III clears this up when talking about the return value
14527db96d56Sopenharmony_ci            # of this function.  If namespaceURI, qName and DocType are
14537db96d56Sopenharmony_ci            # Null the document is returned without a document element
14547db96d56Sopenharmony_ci            # Otherwise if doctype or namespaceURI are not None
14557db96d56Sopenharmony_ci            # Then we go back to the above problem
14567db96d56Sopenharmony_ci            raise xml.dom.InvalidCharacterErr("Element with no name")
14577db96d56Sopenharmony_ci
14587db96d56Sopenharmony_ci        if add_root_element:
14597db96d56Sopenharmony_ci            prefix, localname = _nssplit(qualifiedName)
14607db96d56Sopenharmony_ci            if prefix == "xml" \
14617db96d56Sopenharmony_ci               and namespaceURI != "http://www.w3.org/XML/1998/namespace":
14627db96d56Sopenharmony_ci                raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
14637db96d56Sopenharmony_ci            if prefix and not namespaceURI:
14647db96d56Sopenharmony_ci                raise xml.dom.NamespaceErr(
14657db96d56Sopenharmony_ci                    "illegal use of prefix without namespaces")
14667db96d56Sopenharmony_ci            element = doc.createElementNS(namespaceURI, qualifiedName)
14677db96d56Sopenharmony_ci            if doctype:
14687db96d56Sopenharmony_ci                doc.appendChild(doctype)
14697db96d56Sopenharmony_ci            doc.appendChild(element)
14707db96d56Sopenharmony_ci
14717db96d56Sopenharmony_ci        if doctype:
14727db96d56Sopenharmony_ci            doctype.parentNode = doctype.ownerDocument = doc
14737db96d56Sopenharmony_ci
14747db96d56Sopenharmony_ci        doc.doctype = doctype
14757db96d56Sopenharmony_ci        doc.implementation = self
14767db96d56Sopenharmony_ci        return doc
14777db96d56Sopenharmony_ci
14787db96d56Sopenharmony_ci    def createDocumentType(self, qualifiedName, publicId, systemId):
14797db96d56Sopenharmony_ci        doctype = DocumentType(qualifiedName)
14807db96d56Sopenharmony_ci        doctype.publicId = publicId
14817db96d56Sopenharmony_ci        doctype.systemId = systemId
14827db96d56Sopenharmony_ci        return doctype
14837db96d56Sopenharmony_ci
14847db96d56Sopenharmony_ci    # DOM Level 3 (WD 9 April 2002)
14857db96d56Sopenharmony_ci
14867db96d56Sopenharmony_ci    def getInterface(self, feature):
14877db96d56Sopenharmony_ci        if self.hasFeature(feature, None):
14887db96d56Sopenharmony_ci            return self
14897db96d56Sopenharmony_ci        else:
14907db96d56Sopenharmony_ci            return None
14917db96d56Sopenharmony_ci
14927db96d56Sopenharmony_ci    # internal
14937db96d56Sopenharmony_ci    def _create_document(self):
14947db96d56Sopenharmony_ci        return Document()
14957db96d56Sopenharmony_ci
14967db96d56Sopenharmony_ciclass ElementInfo(object):
14977db96d56Sopenharmony_ci    """Object that represents content-model information for an element.
14987db96d56Sopenharmony_ci
14997db96d56Sopenharmony_ci    This implementation is not expected to be used in practice; DOM
15007db96d56Sopenharmony_ci    builders should provide implementations which do the right thing
15017db96d56Sopenharmony_ci    using information available to it.
15027db96d56Sopenharmony_ci
15037db96d56Sopenharmony_ci    """
15047db96d56Sopenharmony_ci
15057db96d56Sopenharmony_ci    __slots__ = 'tagName',
15067db96d56Sopenharmony_ci
15077db96d56Sopenharmony_ci    def __init__(self, name):
15087db96d56Sopenharmony_ci        self.tagName = name
15097db96d56Sopenharmony_ci
15107db96d56Sopenharmony_ci    def getAttributeType(self, aname):
15117db96d56Sopenharmony_ci        return _no_type
15127db96d56Sopenharmony_ci
15137db96d56Sopenharmony_ci    def getAttributeTypeNS(self, namespaceURI, localName):
15147db96d56Sopenharmony_ci        return _no_type
15157db96d56Sopenharmony_ci
15167db96d56Sopenharmony_ci    def isElementContent(self):
15177db96d56Sopenharmony_ci        return False
15187db96d56Sopenharmony_ci
15197db96d56Sopenharmony_ci    def isEmpty(self):
15207db96d56Sopenharmony_ci        """Returns true iff this element is declared to have an EMPTY
15217db96d56Sopenharmony_ci        content model."""
15227db96d56Sopenharmony_ci        return False
15237db96d56Sopenharmony_ci
15247db96d56Sopenharmony_ci    def isId(self, aname):
15257db96d56Sopenharmony_ci        """Returns true iff the named attribute is a DTD-style ID."""
15267db96d56Sopenharmony_ci        return False
15277db96d56Sopenharmony_ci
15287db96d56Sopenharmony_ci    def isIdNS(self, namespaceURI, localName):
15297db96d56Sopenharmony_ci        """Returns true iff the identified attribute is a DTD-style ID."""
15307db96d56Sopenharmony_ci        return False
15317db96d56Sopenharmony_ci
15327db96d56Sopenharmony_ci    def __getstate__(self):
15337db96d56Sopenharmony_ci        return self.tagName
15347db96d56Sopenharmony_ci
15357db96d56Sopenharmony_ci    def __setstate__(self, state):
15367db96d56Sopenharmony_ci        self.tagName = state
15377db96d56Sopenharmony_ci
15387db96d56Sopenharmony_cidef _clear_id_cache(node):
15397db96d56Sopenharmony_ci    if node.nodeType == Node.DOCUMENT_NODE:
15407db96d56Sopenharmony_ci        node._id_cache.clear()
15417db96d56Sopenharmony_ci        node._id_search_stack = None
15427db96d56Sopenharmony_ci    elif _in_document(node):
15437db96d56Sopenharmony_ci        node.ownerDocument._id_cache.clear()
15447db96d56Sopenharmony_ci        node.ownerDocument._id_search_stack= None
15457db96d56Sopenharmony_ci
15467db96d56Sopenharmony_ciclass Document(Node, DocumentLS):
15477db96d56Sopenharmony_ci    __slots__ = ('_elem_info', 'doctype',
15487db96d56Sopenharmony_ci                 '_id_search_stack', 'childNodes', '_id_cache')
15497db96d56Sopenharmony_ci    _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
15507db96d56Sopenharmony_ci                         Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
15517db96d56Sopenharmony_ci
15527db96d56Sopenharmony_ci    implementation = DOMImplementation()
15537db96d56Sopenharmony_ci    nodeType = Node.DOCUMENT_NODE
15547db96d56Sopenharmony_ci    nodeName = "#document"
15557db96d56Sopenharmony_ci    nodeValue = None
15567db96d56Sopenharmony_ci    attributes = None
15577db96d56Sopenharmony_ci    parentNode = None
15587db96d56Sopenharmony_ci    previousSibling = nextSibling = None
15597db96d56Sopenharmony_ci
15607db96d56Sopenharmony_ci
15617db96d56Sopenharmony_ci    # Document attributes from Level 3 (WD 9 April 2002)
15627db96d56Sopenharmony_ci
15637db96d56Sopenharmony_ci    actualEncoding = None
15647db96d56Sopenharmony_ci    encoding = None
15657db96d56Sopenharmony_ci    standalone = None
15667db96d56Sopenharmony_ci    version = None
15677db96d56Sopenharmony_ci    strictErrorChecking = False
15687db96d56Sopenharmony_ci    errorHandler = None
15697db96d56Sopenharmony_ci    documentURI = None
15707db96d56Sopenharmony_ci
15717db96d56Sopenharmony_ci    _magic_id_count = 0
15727db96d56Sopenharmony_ci
15737db96d56Sopenharmony_ci    def __init__(self):
15747db96d56Sopenharmony_ci        self.doctype = None
15757db96d56Sopenharmony_ci        self.childNodes = NodeList()
15767db96d56Sopenharmony_ci        # mapping of (namespaceURI, localName) -> ElementInfo
15777db96d56Sopenharmony_ci        #        and tagName -> ElementInfo
15787db96d56Sopenharmony_ci        self._elem_info = {}
15797db96d56Sopenharmony_ci        self._id_cache = {}
15807db96d56Sopenharmony_ci        self._id_search_stack = None
15817db96d56Sopenharmony_ci
15827db96d56Sopenharmony_ci    def _get_elem_info(self, element):
15837db96d56Sopenharmony_ci        if element.namespaceURI:
15847db96d56Sopenharmony_ci            key = element.namespaceURI, element.localName
15857db96d56Sopenharmony_ci        else:
15867db96d56Sopenharmony_ci            key = element.tagName
15877db96d56Sopenharmony_ci        return self._elem_info.get(key)
15887db96d56Sopenharmony_ci
15897db96d56Sopenharmony_ci    def _get_actualEncoding(self):
15907db96d56Sopenharmony_ci        return self.actualEncoding
15917db96d56Sopenharmony_ci
15927db96d56Sopenharmony_ci    def _get_doctype(self):
15937db96d56Sopenharmony_ci        return self.doctype
15947db96d56Sopenharmony_ci
15957db96d56Sopenharmony_ci    def _get_documentURI(self):
15967db96d56Sopenharmony_ci        return self.documentURI
15977db96d56Sopenharmony_ci
15987db96d56Sopenharmony_ci    def _get_encoding(self):
15997db96d56Sopenharmony_ci        return self.encoding
16007db96d56Sopenharmony_ci
16017db96d56Sopenharmony_ci    def _get_errorHandler(self):
16027db96d56Sopenharmony_ci        return self.errorHandler
16037db96d56Sopenharmony_ci
16047db96d56Sopenharmony_ci    def _get_standalone(self):
16057db96d56Sopenharmony_ci        return self.standalone
16067db96d56Sopenharmony_ci
16077db96d56Sopenharmony_ci    def _get_strictErrorChecking(self):
16087db96d56Sopenharmony_ci        return self.strictErrorChecking
16097db96d56Sopenharmony_ci
16107db96d56Sopenharmony_ci    def _get_version(self):
16117db96d56Sopenharmony_ci        return self.version
16127db96d56Sopenharmony_ci
16137db96d56Sopenharmony_ci    def appendChild(self, node):
16147db96d56Sopenharmony_ci        if node.nodeType not in self._child_node_types:
16157db96d56Sopenharmony_ci            raise xml.dom.HierarchyRequestErr(
16167db96d56Sopenharmony_ci                "%s cannot be child of %s" % (repr(node), repr(self)))
16177db96d56Sopenharmony_ci        if node.parentNode is not None:
16187db96d56Sopenharmony_ci            # This needs to be done before the next test since this
16197db96d56Sopenharmony_ci            # may *be* the document element, in which case it should
16207db96d56Sopenharmony_ci            # end up re-ordered to the end.
16217db96d56Sopenharmony_ci            node.parentNode.removeChild(node)
16227db96d56Sopenharmony_ci
16237db96d56Sopenharmony_ci        if node.nodeType == Node.ELEMENT_NODE \
16247db96d56Sopenharmony_ci           and self._get_documentElement():
16257db96d56Sopenharmony_ci            raise xml.dom.HierarchyRequestErr(
16267db96d56Sopenharmony_ci                "two document elements disallowed")
16277db96d56Sopenharmony_ci        return Node.appendChild(self, node)
16287db96d56Sopenharmony_ci
16297db96d56Sopenharmony_ci    def removeChild(self, oldChild):
16307db96d56Sopenharmony_ci        try:
16317db96d56Sopenharmony_ci            self.childNodes.remove(oldChild)
16327db96d56Sopenharmony_ci        except ValueError:
16337db96d56Sopenharmony_ci            raise xml.dom.NotFoundErr()
16347db96d56Sopenharmony_ci        oldChild.nextSibling = oldChild.previousSibling = None
16357db96d56Sopenharmony_ci        oldChild.parentNode = None
16367db96d56Sopenharmony_ci        if self.documentElement is oldChild:
16377db96d56Sopenharmony_ci            self.documentElement = None
16387db96d56Sopenharmony_ci
16397db96d56Sopenharmony_ci        return oldChild
16407db96d56Sopenharmony_ci
16417db96d56Sopenharmony_ci    def _get_documentElement(self):
16427db96d56Sopenharmony_ci        for node in self.childNodes:
16437db96d56Sopenharmony_ci            if node.nodeType == Node.ELEMENT_NODE:
16447db96d56Sopenharmony_ci                return node
16457db96d56Sopenharmony_ci
16467db96d56Sopenharmony_ci    def unlink(self):
16477db96d56Sopenharmony_ci        if self.doctype is not None:
16487db96d56Sopenharmony_ci            self.doctype.unlink()
16497db96d56Sopenharmony_ci            self.doctype = None
16507db96d56Sopenharmony_ci        Node.unlink(self)
16517db96d56Sopenharmony_ci
16527db96d56Sopenharmony_ci    def cloneNode(self, deep):
16537db96d56Sopenharmony_ci        if not deep:
16547db96d56Sopenharmony_ci            return None
16557db96d56Sopenharmony_ci        clone = self.implementation.createDocument(None, None, None)
16567db96d56Sopenharmony_ci        clone.encoding = self.encoding
16577db96d56Sopenharmony_ci        clone.standalone = self.standalone
16587db96d56Sopenharmony_ci        clone.version = self.version
16597db96d56Sopenharmony_ci        for n in self.childNodes:
16607db96d56Sopenharmony_ci            childclone = _clone_node(n, deep, clone)
16617db96d56Sopenharmony_ci            assert childclone.ownerDocument.isSameNode(clone)
16627db96d56Sopenharmony_ci            clone.childNodes.append(childclone)
16637db96d56Sopenharmony_ci            if childclone.nodeType == Node.DOCUMENT_NODE:
16647db96d56Sopenharmony_ci                assert clone.documentElement is None
16657db96d56Sopenharmony_ci            elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
16667db96d56Sopenharmony_ci                assert clone.doctype is None
16677db96d56Sopenharmony_ci                clone.doctype = childclone
16687db96d56Sopenharmony_ci            childclone.parentNode = clone
16697db96d56Sopenharmony_ci        self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
16707db96d56Sopenharmony_ci                                     self, clone)
16717db96d56Sopenharmony_ci        return clone
16727db96d56Sopenharmony_ci
16737db96d56Sopenharmony_ci    def createDocumentFragment(self):
16747db96d56Sopenharmony_ci        d = DocumentFragment()
16757db96d56Sopenharmony_ci        d.ownerDocument = self
16767db96d56Sopenharmony_ci        return d
16777db96d56Sopenharmony_ci
16787db96d56Sopenharmony_ci    def createElement(self, tagName):
16797db96d56Sopenharmony_ci        e = Element(tagName)
16807db96d56Sopenharmony_ci        e.ownerDocument = self
16817db96d56Sopenharmony_ci        return e
16827db96d56Sopenharmony_ci
16837db96d56Sopenharmony_ci    def createTextNode(self, data):
16847db96d56Sopenharmony_ci        if not isinstance(data, str):
16857db96d56Sopenharmony_ci            raise TypeError("node contents must be a string")
16867db96d56Sopenharmony_ci        t = Text()
16877db96d56Sopenharmony_ci        t.data = data
16887db96d56Sopenharmony_ci        t.ownerDocument = self
16897db96d56Sopenharmony_ci        return t
16907db96d56Sopenharmony_ci
16917db96d56Sopenharmony_ci    def createCDATASection(self, data):
16927db96d56Sopenharmony_ci        if not isinstance(data, str):
16937db96d56Sopenharmony_ci            raise TypeError("node contents must be a string")
16947db96d56Sopenharmony_ci        c = CDATASection()
16957db96d56Sopenharmony_ci        c.data = data
16967db96d56Sopenharmony_ci        c.ownerDocument = self
16977db96d56Sopenharmony_ci        return c
16987db96d56Sopenharmony_ci
16997db96d56Sopenharmony_ci    def createComment(self, data):
17007db96d56Sopenharmony_ci        c = Comment(data)
17017db96d56Sopenharmony_ci        c.ownerDocument = self
17027db96d56Sopenharmony_ci        return c
17037db96d56Sopenharmony_ci
17047db96d56Sopenharmony_ci    def createProcessingInstruction(self, target, data):
17057db96d56Sopenharmony_ci        p = ProcessingInstruction(target, data)
17067db96d56Sopenharmony_ci        p.ownerDocument = self
17077db96d56Sopenharmony_ci        return p
17087db96d56Sopenharmony_ci
17097db96d56Sopenharmony_ci    def createAttribute(self, qName):
17107db96d56Sopenharmony_ci        a = Attr(qName)
17117db96d56Sopenharmony_ci        a.ownerDocument = self
17127db96d56Sopenharmony_ci        a.value = ""
17137db96d56Sopenharmony_ci        return a
17147db96d56Sopenharmony_ci
17157db96d56Sopenharmony_ci    def createElementNS(self, namespaceURI, qualifiedName):
17167db96d56Sopenharmony_ci        prefix, localName = _nssplit(qualifiedName)
17177db96d56Sopenharmony_ci        e = Element(qualifiedName, namespaceURI, prefix)
17187db96d56Sopenharmony_ci        e.ownerDocument = self
17197db96d56Sopenharmony_ci        return e
17207db96d56Sopenharmony_ci
17217db96d56Sopenharmony_ci    def createAttributeNS(self, namespaceURI, qualifiedName):
17227db96d56Sopenharmony_ci        prefix, localName = _nssplit(qualifiedName)
17237db96d56Sopenharmony_ci        a = Attr(qualifiedName, namespaceURI, localName, prefix)
17247db96d56Sopenharmony_ci        a.ownerDocument = self
17257db96d56Sopenharmony_ci        a.value = ""
17267db96d56Sopenharmony_ci        return a
17277db96d56Sopenharmony_ci
17287db96d56Sopenharmony_ci    # A couple of implementation-specific helpers to create node types
17297db96d56Sopenharmony_ci    # not supported by the W3C DOM specs:
17307db96d56Sopenharmony_ci
17317db96d56Sopenharmony_ci    def _create_entity(self, name, publicId, systemId, notationName):
17327db96d56Sopenharmony_ci        e = Entity(name, publicId, systemId, notationName)
17337db96d56Sopenharmony_ci        e.ownerDocument = self
17347db96d56Sopenharmony_ci        return e
17357db96d56Sopenharmony_ci
17367db96d56Sopenharmony_ci    def _create_notation(self, name, publicId, systemId):
17377db96d56Sopenharmony_ci        n = Notation(name, publicId, systemId)
17387db96d56Sopenharmony_ci        n.ownerDocument = self
17397db96d56Sopenharmony_ci        return n
17407db96d56Sopenharmony_ci
17417db96d56Sopenharmony_ci    def getElementById(self, id):
17427db96d56Sopenharmony_ci        if id in self._id_cache:
17437db96d56Sopenharmony_ci            return self._id_cache[id]
17447db96d56Sopenharmony_ci        if not (self._elem_info or self._magic_id_count):
17457db96d56Sopenharmony_ci            return None
17467db96d56Sopenharmony_ci
17477db96d56Sopenharmony_ci        stack = self._id_search_stack
17487db96d56Sopenharmony_ci        if stack is None:
17497db96d56Sopenharmony_ci            # we never searched before, or the cache has been cleared
17507db96d56Sopenharmony_ci            stack = [self.documentElement]
17517db96d56Sopenharmony_ci            self._id_search_stack = stack
17527db96d56Sopenharmony_ci        elif not stack:
17537db96d56Sopenharmony_ci            # Previous search was completed and cache is still valid;
17547db96d56Sopenharmony_ci            # no matching node.
17557db96d56Sopenharmony_ci            return None
17567db96d56Sopenharmony_ci
17577db96d56Sopenharmony_ci        result = None
17587db96d56Sopenharmony_ci        while stack:
17597db96d56Sopenharmony_ci            node = stack.pop()
17607db96d56Sopenharmony_ci            # add child elements to stack for continued searching
17617db96d56Sopenharmony_ci            stack.extend([child for child in node.childNodes
17627db96d56Sopenharmony_ci                          if child.nodeType in _nodeTypes_with_children])
17637db96d56Sopenharmony_ci            # check this node
17647db96d56Sopenharmony_ci            info = self._get_elem_info(node)
17657db96d56Sopenharmony_ci            if info:
17667db96d56Sopenharmony_ci                # We have to process all ID attributes before
17677db96d56Sopenharmony_ci                # returning in order to get all the attributes set to
17687db96d56Sopenharmony_ci                # be IDs using Element.setIdAttribute*().
17697db96d56Sopenharmony_ci                for attr in node.attributes.values():
17707db96d56Sopenharmony_ci                    if attr.namespaceURI:
17717db96d56Sopenharmony_ci                        if info.isIdNS(attr.namespaceURI, attr.localName):
17727db96d56Sopenharmony_ci                            self._id_cache[attr.value] = node
17737db96d56Sopenharmony_ci                            if attr.value == id:
17747db96d56Sopenharmony_ci                                result = node
17757db96d56Sopenharmony_ci                            elif not node._magic_id_nodes:
17767db96d56Sopenharmony_ci                                break
17777db96d56Sopenharmony_ci                    elif info.isId(attr.name):
17787db96d56Sopenharmony_ci                        self._id_cache[attr.value] = node
17797db96d56Sopenharmony_ci                        if attr.value == id:
17807db96d56Sopenharmony_ci                            result = node
17817db96d56Sopenharmony_ci                        elif not node._magic_id_nodes:
17827db96d56Sopenharmony_ci                            break
17837db96d56Sopenharmony_ci                    elif attr._is_id:
17847db96d56Sopenharmony_ci                        self._id_cache[attr.value] = node
17857db96d56Sopenharmony_ci                        if attr.value == id:
17867db96d56Sopenharmony_ci                            result = node
17877db96d56Sopenharmony_ci                        elif node._magic_id_nodes == 1:
17887db96d56Sopenharmony_ci                            break
17897db96d56Sopenharmony_ci            elif node._magic_id_nodes:
17907db96d56Sopenharmony_ci                for attr in node.attributes.values():
17917db96d56Sopenharmony_ci                    if attr._is_id:
17927db96d56Sopenharmony_ci                        self._id_cache[attr.value] = node
17937db96d56Sopenharmony_ci                        if attr.value == id:
17947db96d56Sopenharmony_ci                            result = node
17957db96d56Sopenharmony_ci            if result is not None:
17967db96d56Sopenharmony_ci                break
17977db96d56Sopenharmony_ci        return result
17987db96d56Sopenharmony_ci
17997db96d56Sopenharmony_ci    def getElementsByTagName(self, name):
18007db96d56Sopenharmony_ci        return _get_elements_by_tagName_helper(self, name, NodeList())
18017db96d56Sopenharmony_ci
18027db96d56Sopenharmony_ci    def getElementsByTagNameNS(self, namespaceURI, localName):
18037db96d56Sopenharmony_ci        return _get_elements_by_tagName_ns_helper(
18047db96d56Sopenharmony_ci            self, namespaceURI, localName, NodeList())
18057db96d56Sopenharmony_ci
18067db96d56Sopenharmony_ci    def isSupported(self, feature, version):
18077db96d56Sopenharmony_ci        return self.implementation.hasFeature(feature, version)
18087db96d56Sopenharmony_ci
18097db96d56Sopenharmony_ci    def importNode(self, node, deep):
18107db96d56Sopenharmony_ci        if node.nodeType == Node.DOCUMENT_NODE:
18117db96d56Sopenharmony_ci            raise xml.dom.NotSupportedErr("cannot import document nodes")
18127db96d56Sopenharmony_ci        elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
18137db96d56Sopenharmony_ci            raise xml.dom.NotSupportedErr("cannot import document type nodes")
18147db96d56Sopenharmony_ci        return _clone_node(node, deep, self)
18157db96d56Sopenharmony_ci
18167db96d56Sopenharmony_ci    def writexml(self, writer, indent="", addindent="", newl="", encoding=None,
18177db96d56Sopenharmony_ci                 standalone=None):
18187db96d56Sopenharmony_ci        declarations = []
18197db96d56Sopenharmony_ci
18207db96d56Sopenharmony_ci        if encoding:
18217db96d56Sopenharmony_ci            declarations.append(f'encoding="{encoding}"')
18227db96d56Sopenharmony_ci        if standalone is not None:
18237db96d56Sopenharmony_ci            declarations.append(f'standalone="{"yes" if standalone else "no"}"')
18247db96d56Sopenharmony_ci
18257db96d56Sopenharmony_ci        writer.write(f'<?xml version="1.0" {" ".join(declarations)}?>{newl}')
18267db96d56Sopenharmony_ci
18277db96d56Sopenharmony_ci        for node in self.childNodes:
18287db96d56Sopenharmony_ci            node.writexml(writer, indent, addindent, newl)
18297db96d56Sopenharmony_ci
18307db96d56Sopenharmony_ci    # DOM Level 3 (WD 9 April 2002)
18317db96d56Sopenharmony_ci
18327db96d56Sopenharmony_ci    def renameNode(self, n, namespaceURI, name):
18337db96d56Sopenharmony_ci        if n.ownerDocument is not self:
18347db96d56Sopenharmony_ci            raise xml.dom.WrongDocumentErr(
18357db96d56Sopenharmony_ci                "cannot rename nodes from other documents;\n"
18367db96d56Sopenharmony_ci                "expected %s,\nfound %s" % (self, n.ownerDocument))
18377db96d56Sopenharmony_ci        if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
18387db96d56Sopenharmony_ci            raise xml.dom.NotSupportedErr(
18397db96d56Sopenharmony_ci                "renameNode() only applies to element and attribute nodes")
18407db96d56Sopenharmony_ci        if namespaceURI != EMPTY_NAMESPACE:
18417db96d56Sopenharmony_ci            if ':' in name:
18427db96d56Sopenharmony_ci                prefix, localName = name.split(':', 1)
18437db96d56Sopenharmony_ci                if (  prefix == "xmlns"
18447db96d56Sopenharmony_ci                      and namespaceURI != xml.dom.XMLNS_NAMESPACE):
18457db96d56Sopenharmony_ci                    raise xml.dom.NamespaceErr(
18467db96d56Sopenharmony_ci                        "illegal use of 'xmlns' prefix")
18477db96d56Sopenharmony_ci            else:
18487db96d56Sopenharmony_ci                if (  name == "xmlns"
18497db96d56Sopenharmony_ci                      and namespaceURI != xml.dom.XMLNS_NAMESPACE
18507db96d56Sopenharmony_ci                      and n.nodeType == Node.ATTRIBUTE_NODE):
18517db96d56Sopenharmony_ci                    raise xml.dom.NamespaceErr(
18527db96d56Sopenharmony_ci                        "illegal use of the 'xmlns' attribute")
18537db96d56Sopenharmony_ci                prefix = None
18547db96d56Sopenharmony_ci                localName = name
18557db96d56Sopenharmony_ci        else:
18567db96d56Sopenharmony_ci            prefix = None
18577db96d56Sopenharmony_ci            localName = None
18587db96d56Sopenharmony_ci        if n.nodeType == Node.ATTRIBUTE_NODE:
18597db96d56Sopenharmony_ci            element = n.ownerElement
18607db96d56Sopenharmony_ci            if element is not None:
18617db96d56Sopenharmony_ci                is_id = n._is_id
18627db96d56Sopenharmony_ci                element.removeAttributeNode(n)
18637db96d56Sopenharmony_ci        else:
18647db96d56Sopenharmony_ci            element = None
18657db96d56Sopenharmony_ci        n.prefix = prefix
18667db96d56Sopenharmony_ci        n._localName = localName
18677db96d56Sopenharmony_ci        n.namespaceURI = namespaceURI
18687db96d56Sopenharmony_ci        n.nodeName = name
18697db96d56Sopenharmony_ci        if n.nodeType == Node.ELEMENT_NODE:
18707db96d56Sopenharmony_ci            n.tagName = name
18717db96d56Sopenharmony_ci        else:
18727db96d56Sopenharmony_ci            # attribute node
18737db96d56Sopenharmony_ci            n.name = name
18747db96d56Sopenharmony_ci            if element is not None:
18757db96d56Sopenharmony_ci                element.setAttributeNode(n)
18767db96d56Sopenharmony_ci                if is_id:
18777db96d56Sopenharmony_ci                    element.setIdAttributeNode(n)
18787db96d56Sopenharmony_ci        # It's not clear from a semantic perspective whether we should
18797db96d56Sopenharmony_ci        # call the user data handlers for the NODE_RENAMED event since
18807db96d56Sopenharmony_ci        # we're re-using the existing node.  The draft spec has been
18817db96d56Sopenharmony_ci        # interpreted as meaning "no, don't call the handler unless a
18827db96d56Sopenharmony_ci        # new node is created."
18837db96d56Sopenharmony_ci        return n
18847db96d56Sopenharmony_ci
18857db96d56Sopenharmony_cidefproperty(Document, "documentElement",
18867db96d56Sopenharmony_ci            doc="Top-level element of this document.")
18877db96d56Sopenharmony_ci
18887db96d56Sopenharmony_ci
18897db96d56Sopenharmony_cidef _clone_node(node, deep, newOwnerDocument):
18907db96d56Sopenharmony_ci    """
18917db96d56Sopenharmony_ci    Clone a node and give it the new owner document.
18927db96d56Sopenharmony_ci    Called by Node.cloneNode and Document.importNode
18937db96d56Sopenharmony_ci    """
18947db96d56Sopenharmony_ci    if node.ownerDocument.isSameNode(newOwnerDocument):
18957db96d56Sopenharmony_ci        operation = xml.dom.UserDataHandler.NODE_CLONED
18967db96d56Sopenharmony_ci    else:
18977db96d56Sopenharmony_ci        operation = xml.dom.UserDataHandler.NODE_IMPORTED
18987db96d56Sopenharmony_ci    if node.nodeType == Node.ELEMENT_NODE:
18997db96d56Sopenharmony_ci        clone = newOwnerDocument.createElementNS(node.namespaceURI,
19007db96d56Sopenharmony_ci                                                 node.nodeName)
19017db96d56Sopenharmony_ci        for attr in node.attributes.values():
19027db96d56Sopenharmony_ci            clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
19037db96d56Sopenharmony_ci            a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
19047db96d56Sopenharmony_ci            a.specified = attr.specified
19057db96d56Sopenharmony_ci
19067db96d56Sopenharmony_ci        if deep:
19077db96d56Sopenharmony_ci            for child in node.childNodes:
19087db96d56Sopenharmony_ci                c = _clone_node(child, deep, newOwnerDocument)
19097db96d56Sopenharmony_ci                clone.appendChild(c)
19107db96d56Sopenharmony_ci
19117db96d56Sopenharmony_ci    elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
19127db96d56Sopenharmony_ci        clone = newOwnerDocument.createDocumentFragment()
19137db96d56Sopenharmony_ci        if deep:
19147db96d56Sopenharmony_ci            for child in node.childNodes:
19157db96d56Sopenharmony_ci                c = _clone_node(child, deep, newOwnerDocument)
19167db96d56Sopenharmony_ci                clone.appendChild(c)
19177db96d56Sopenharmony_ci
19187db96d56Sopenharmony_ci    elif node.nodeType == Node.TEXT_NODE:
19197db96d56Sopenharmony_ci        clone = newOwnerDocument.createTextNode(node.data)
19207db96d56Sopenharmony_ci    elif node.nodeType == Node.CDATA_SECTION_NODE:
19217db96d56Sopenharmony_ci        clone = newOwnerDocument.createCDATASection(node.data)
19227db96d56Sopenharmony_ci    elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
19237db96d56Sopenharmony_ci        clone = newOwnerDocument.createProcessingInstruction(node.target,
19247db96d56Sopenharmony_ci                                                             node.data)
19257db96d56Sopenharmony_ci    elif node.nodeType == Node.COMMENT_NODE:
19267db96d56Sopenharmony_ci        clone = newOwnerDocument.createComment(node.data)
19277db96d56Sopenharmony_ci    elif node.nodeType == Node.ATTRIBUTE_NODE:
19287db96d56Sopenharmony_ci        clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
19297db96d56Sopenharmony_ci                                                   node.nodeName)
19307db96d56Sopenharmony_ci        clone.specified = True
19317db96d56Sopenharmony_ci        clone.value = node.value
19327db96d56Sopenharmony_ci    elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
19337db96d56Sopenharmony_ci        assert node.ownerDocument is not newOwnerDocument
19347db96d56Sopenharmony_ci        operation = xml.dom.UserDataHandler.NODE_IMPORTED
19357db96d56Sopenharmony_ci        clone = newOwnerDocument.implementation.createDocumentType(
19367db96d56Sopenharmony_ci            node.name, node.publicId, node.systemId)
19377db96d56Sopenharmony_ci        clone.ownerDocument = newOwnerDocument
19387db96d56Sopenharmony_ci        if deep:
19397db96d56Sopenharmony_ci            clone.entities._seq = []
19407db96d56Sopenharmony_ci            clone.notations._seq = []
19417db96d56Sopenharmony_ci            for n in node.notations._seq:
19427db96d56Sopenharmony_ci                notation = Notation(n.nodeName, n.publicId, n.systemId)
19437db96d56Sopenharmony_ci                notation.ownerDocument = newOwnerDocument
19447db96d56Sopenharmony_ci                clone.notations._seq.append(notation)
19457db96d56Sopenharmony_ci                if hasattr(n, '_call_user_data_handler'):
19467db96d56Sopenharmony_ci                    n._call_user_data_handler(operation, n, notation)
19477db96d56Sopenharmony_ci            for e in node.entities._seq:
19487db96d56Sopenharmony_ci                entity = Entity(e.nodeName, e.publicId, e.systemId,
19497db96d56Sopenharmony_ci                                e.notationName)
19507db96d56Sopenharmony_ci                entity.actualEncoding = e.actualEncoding
19517db96d56Sopenharmony_ci                entity.encoding = e.encoding
19527db96d56Sopenharmony_ci                entity.version = e.version
19537db96d56Sopenharmony_ci                entity.ownerDocument = newOwnerDocument
19547db96d56Sopenharmony_ci                clone.entities._seq.append(entity)
19557db96d56Sopenharmony_ci                if hasattr(e, '_call_user_data_handler'):
19567db96d56Sopenharmony_ci                    e._call_user_data_handler(operation, e, entity)
19577db96d56Sopenharmony_ci    else:
19587db96d56Sopenharmony_ci        # Note the cloning of Document and DocumentType nodes is
19597db96d56Sopenharmony_ci        # implementation specific.  minidom handles those cases
19607db96d56Sopenharmony_ci        # directly in the cloneNode() methods.
19617db96d56Sopenharmony_ci        raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
19627db96d56Sopenharmony_ci
19637db96d56Sopenharmony_ci    # Check for _call_user_data_handler() since this could conceivably
19647db96d56Sopenharmony_ci    # used with other DOM implementations (one of the FourThought
19657db96d56Sopenharmony_ci    # DOMs, perhaps?).
19667db96d56Sopenharmony_ci    if hasattr(node, '_call_user_data_handler'):
19677db96d56Sopenharmony_ci        node._call_user_data_handler(operation, node, clone)
19687db96d56Sopenharmony_ci    return clone
19697db96d56Sopenharmony_ci
19707db96d56Sopenharmony_ci
19717db96d56Sopenharmony_cidef _nssplit(qualifiedName):
19727db96d56Sopenharmony_ci    fields = qualifiedName.split(':', 1)
19737db96d56Sopenharmony_ci    if len(fields) == 2:
19747db96d56Sopenharmony_ci        return fields
19757db96d56Sopenharmony_ci    else:
19767db96d56Sopenharmony_ci        return (None, fields[0])
19777db96d56Sopenharmony_ci
19787db96d56Sopenharmony_ci
19797db96d56Sopenharmony_cidef _do_pulldom_parse(func, args, kwargs):
19807db96d56Sopenharmony_ci    events = func(*args, **kwargs)
19817db96d56Sopenharmony_ci    toktype, rootNode = events.getEvent()
19827db96d56Sopenharmony_ci    events.expandNode(rootNode)
19837db96d56Sopenharmony_ci    events.clear()
19847db96d56Sopenharmony_ci    return rootNode
19857db96d56Sopenharmony_ci
19867db96d56Sopenharmony_cidef parse(file, parser=None, bufsize=None):
19877db96d56Sopenharmony_ci    """Parse a file into a DOM by filename or file object."""
19887db96d56Sopenharmony_ci    if parser is None and not bufsize:
19897db96d56Sopenharmony_ci        from xml.dom import expatbuilder
19907db96d56Sopenharmony_ci        return expatbuilder.parse(file)
19917db96d56Sopenharmony_ci    else:
19927db96d56Sopenharmony_ci        from xml.dom import pulldom
19937db96d56Sopenharmony_ci        return _do_pulldom_parse(pulldom.parse, (file,),
19947db96d56Sopenharmony_ci            {'parser': parser, 'bufsize': bufsize})
19957db96d56Sopenharmony_ci
19967db96d56Sopenharmony_cidef parseString(string, parser=None):
19977db96d56Sopenharmony_ci    """Parse a file into a DOM from a string."""
19987db96d56Sopenharmony_ci    if parser is None:
19997db96d56Sopenharmony_ci        from xml.dom import expatbuilder
20007db96d56Sopenharmony_ci        return expatbuilder.parseString(string)
20017db96d56Sopenharmony_ci    else:
20027db96d56Sopenharmony_ci        from xml.dom import pulldom
20037db96d56Sopenharmony_ci        return _do_pulldom_parse(pulldom.parseString, (string,),
20047db96d56Sopenharmony_ci                                 {'parser': parser})
20057db96d56Sopenharmony_ci
20067db96d56Sopenharmony_cidef getDOMImplementation(features=None):
20077db96d56Sopenharmony_ci    if features:
20087db96d56Sopenharmony_ci        if isinstance(features, str):
20097db96d56Sopenharmony_ci            features = domreg._parse_feature_string(features)
20107db96d56Sopenharmony_ci        for f, v in features:
20117db96d56Sopenharmony_ci            if not Document.implementation.hasFeature(f, v):
20127db96d56Sopenharmony_ci                return None
20137db96d56Sopenharmony_ci    return Document.implementation
2014