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("&", "&").replace("<", "<"). \ 3077db96d56Sopenharmony_ci replace("\"", """).replace(">", ">") 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