1*cda5da8dSAndroid Build Coastguard Worker"""Simple implementation of the Level 1 DOM. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerNamespaces and other minor Level 2 features are also supported. 4*cda5da8dSAndroid Build Coastguard Worker 5*cda5da8dSAndroid Build Coastguard Workerparse("foo.xml") 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard WorkerparseString("<foo><bar/></foo>") 8*cda5da8dSAndroid Build Coastguard Worker 9*cda5da8dSAndroid Build Coastguard WorkerTodo: 10*cda5da8dSAndroid Build Coastguard Worker===== 11*cda5da8dSAndroid Build Coastguard Worker * convenience methods for getting elements and text. 12*cda5da8dSAndroid Build Coastguard Worker * more testing 13*cda5da8dSAndroid Build Coastguard Worker * bring some of the writer and linearizer code into conformance with this 14*cda5da8dSAndroid Build Coastguard Worker interface 15*cda5da8dSAndroid Build Coastguard Worker * SAX 2 namespaces 16*cda5da8dSAndroid Build Coastguard Worker""" 17*cda5da8dSAndroid Build Coastguard Worker 18*cda5da8dSAndroid Build Coastguard Workerimport io 19*cda5da8dSAndroid Build Coastguard Workerimport xml.dom 20*cda5da8dSAndroid Build Coastguard Worker 21*cda5da8dSAndroid Build Coastguard Workerfrom xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg 22*cda5da8dSAndroid Build Coastguard Workerfrom xml.dom.minicompat import * 23*cda5da8dSAndroid Build Coastguard Workerfrom xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS 24*cda5da8dSAndroid Build Coastguard Worker 25*cda5da8dSAndroid Build Coastguard Worker# This is used by the ID-cache invalidation checks; the list isn't 26*cda5da8dSAndroid Build Coastguard Worker# actually complete, since the nodes being checked will never be the 27*cda5da8dSAndroid Build Coastguard Worker# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE. (The node being checked is 28*cda5da8dSAndroid Build Coastguard Worker# the node being added or removed, not the node being modified.) 29*cda5da8dSAndroid Build Coastguard Worker# 30*cda5da8dSAndroid Build Coastguard Worker_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE, 31*cda5da8dSAndroid Build Coastguard Worker xml.dom.Node.ENTITY_REFERENCE_NODE) 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker 34*cda5da8dSAndroid Build Coastguard Workerclass Node(xml.dom.Node): 35*cda5da8dSAndroid Build Coastguard Worker namespaceURI = None # this is non-null only for elements and attributes 36*cda5da8dSAndroid Build Coastguard Worker parentNode = None 37*cda5da8dSAndroid Build Coastguard Worker ownerDocument = None 38*cda5da8dSAndroid Build Coastguard Worker nextSibling = None 39*cda5da8dSAndroid Build Coastguard Worker previousSibling = None 40*cda5da8dSAndroid Build Coastguard Worker 41*cda5da8dSAndroid Build Coastguard Worker prefix = EMPTY_PREFIX # non-null only for NS elements and attributes 42*cda5da8dSAndroid Build Coastguard Worker 43*cda5da8dSAndroid Build Coastguard Worker def __bool__(self): 44*cda5da8dSAndroid Build Coastguard Worker return True 45*cda5da8dSAndroid Build Coastguard Worker 46*cda5da8dSAndroid Build Coastguard Worker def toxml(self, encoding=None, standalone=None): 47*cda5da8dSAndroid Build Coastguard Worker return self.toprettyxml("", "", encoding, standalone) 48*cda5da8dSAndroid Build Coastguard Worker 49*cda5da8dSAndroid Build Coastguard Worker def toprettyxml(self, indent="\t", newl="\n", encoding=None, 50*cda5da8dSAndroid Build Coastguard Worker standalone=None): 51*cda5da8dSAndroid Build Coastguard Worker if encoding is None: 52*cda5da8dSAndroid Build Coastguard Worker writer = io.StringIO() 53*cda5da8dSAndroid Build Coastguard Worker else: 54*cda5da8dSAndroid Build Coastguard Worker writer = io.TextIOWrapper(io.BytesIO(), 55*cda5da8dSAndroid Build Coastguard Worker encoding=encoding, 56*cda5da8dSAndroid Build Coastguard Worker errors="xmlcharrefreplace", 57*cda5da8dSAndroid Build Coastguard Worker newline='\n') 58*cda5da8dSAndroid Build Coastguard Worker if self.nodeType == Node.DOCUMENT_NODE: 59*cda5da8dSAndroid Build Coastguard Worker # Can pass encoding only to document, to put it into XML header 60*cda5da8dSAndroid Build Coastguard Worker self.writexml(writer, "", indent, newl, encoding, standalone) 61*cda5da8dSAndroid Build Coastguard Worker else: 62*cda5da8dSAndroid Build Coastguard Worker self.writexml(writer, "", indent, newl) 63*cda5da8dSAndroid Build Coastguard Worker if encoding is None: 64*cda5da8dSAndroid Build Coastguard Worker return writer.getvalue() 65*cda5da8dSAndroid Build Coastguard Worker else: 66*cda5da8dSAndroid Build Coastguard Worker return writer.detach().getvalue() 67*cda5da8dSAndroid Build Coastguard Worker 68*cda5da8dSAndroid Build Coastguard Worker def hasChildNodes(self): 69*cda5da8dSAndroid Build Coastguard Worker return bool(self.childNodes) 70*cda5da8dSAndroid Build Coastguard Worker 71*cda5da8dSAndroid Build Coastguard Worker def _get_childNodes(self): 72*cda5da8dSAndroid Build Coastguard Worker return self.childNodes 73*cda5da8dSAndroid Build Coastguard Worker 74*cda5da8dSAndroid Build Coastguard Worker def _get_firstChild(self): 75*cda5da8dSAndroid Build Coastguard Worker if self.childNodes: 76*cda5da8dSAndroid Build Coastguard Worker return self.childNodes[0] 77*cda5da8dSAndroid Build Coastguard Worker 78*cda5da8dSAndroid Build Coastguard Worker def _get_lastChild(self): 79*cda5da8dSAndroid Build Coastguard Worker if self.childNodes: 80*cda5da8dSAndroid Build Coastguard Worker return self.childNodes[-1] 81*cda5da8dSAndroid Build Coastguard Worker 82*cda5da8dSAndroid Build Coastguard Worker def insertBefore(self, newChild, refChild): 83*cda5da8dSAndroid Build Coastguard Worker if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE: 84*cda5da8dSAndroid Build Coastguard Worker for c in tuple(newChild.childNodes): 85*cda5da8dSAndroid Build Coastguard Worker self.insertBefore(c, refChild) 86*cda5da8dSAndroid Build Coastguard Worker ### The DOM does not clearly specify what to return in this case 87*cda5da8dSAndroid Build Coastguard Worker return newChild 88*cda5da8dSAndroid Build Coastguard Worker if newChild.nodeType not in self._child_node_types: 89*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 90*cda5da8dSAndroid Build Coastguard Worker "%s cannot be child of %s" % (repr(newChild), repr(self))) 91*cda5da8dSAndroid Build Coastguard Worker if newChild.parentNode is not None: 92*cda5da8dSAndroid Build Coastguard Worker newChild.parentNode.removeChild(newChild) 93*cda5da8dSAndroid Build Coastguard Worker if refChild is None: 94*cda5da8dSAndroid Build Coastguard Worker self.appendChild(newChild) 95*cda5da8dSAndroid Build Coastguard Worker else: 96*cda5da8dSAndroid Build Coastguard Worker try: 97*cda5da8dSAndroid Build Coastguard Worker index = self.childNodes.index(refChild) 98*cda5da8dSAndroid Build Coastguard Worker except ValueError: 99*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 100*cda5da8dSAndroid Build Coastguard Worker if newChild.nodeType in _nodeTypes_with_children: 101*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self) 102*cda5da8dSAndroid Build Coastguard Worker self.childNodes.insert(index, newChild) 103*cda5da8dSAndroid Build Coastguard Worker newChild.nextSibling = refChild 104*cda5da8dSAndroid Build Coastguard Worker refChild.previousSibling = newChild 105*cda5da8dSAndroid Build Coastguard Worker if index: 106*cda5da8dSAndroid Build Coastguard Worker node = self.childNodes[index-1] 107*cda5da8dSAndroid Build Coastguard Worker node.nextSibling = newChild 108*cda5da8dSAndroid Build Coastguard Worker newChild.previousSibling = node 109*cda5da8dSAndroid Build Coastguard Worker else: 110*cda5da8dSAndroid Build Coastguard Worker newChild.previousSibling = None 111*cda5da8dSAndroid Build Coastguard Worker newChild.parentNode = self 112*cda5da8dSAndroid Build Coastguard Worker return newChild 113*cda5da8dSAndroid Build Coastguard Worker 114*cda5da8dSAndroid Build Coastguard Worker def appendChild(self, node): 115*cda5da8dSAndroid Build Coastguard Worker if node.nodeType == self.DOCUMENT_FRAGMENT_NODE: 116*cda5da8dSAndroid Build Coastguard Worker for c in tuple(node.childNodes): 117*cda5da8dSAndroid Build Coastguard Worker self.appendChild(c) 118*cda5da8dSAndroid Build Coastguard Worker ### The DOM does not clearly specify what to return in this case 119*cda5da8dSAndroid Build Coastguard Worker return node 120*cda5da8dSAndroid Build Coastguard Worker if node.nodeType not in self._child_node_types: 121*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 122*cda5da8dSAndroid Build Coastguard Worker "%s cannot be child of %s" % (repr(node), repr(self))) 123*cda5da8dSAndroid Build Coastguard Worker elif node.nodeType in _nodeTypes_with_children: 124*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self) 125*cda5da8dSAndroid Build Coastguard Worker if node.parentNode is not None: 126*cda5da8dSAndroid Build Coastguard Worker node.parentNode.removeChild(node) 127*cda5da8dSAndroid Build Coastguard Worker _append_child(self, node) 128*cda5da8dSAndroid Build Coastguard Worker node.nextSibling = None 129*cda5da8dSAndroid Build Coastguard Worker return node 130*cda5da8dSAndroid Build Coastguard Worker 131*cda5da8dSAndroid Build Coastguard Worker def replaceChild(self, newChild, oldChild): 132*cda5da8dSAndroid Build Coastguard Worker if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE: 133*cda5da8dSAndroid Build Coastguard Worker refChild = oldChild.nextSibling 134*cda5da8dSAndroid Build Coastguard Worker self.removeChild(oldChild) 135*cda5da8dSAndroid Build Coastguard Worker return self.insertBefore(newChild, refChild) 136*cda5da8dSAndroid Build Coastguard Worker if newChild.nodeType not in self._child_node_types: 137*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 138*cda5da8dSAndroid Build Coastguard Worker "%s cannot be child of %s" % (repr(newChild), repr(self))) 139*cda5da8dSAndroid Build Coastguard Worker if newChild is oldChild: 140*cda5da8dSAndroid Build Coastguard Worker return 141*cda5da8dSAndroid Build Coastguard Worker if newChild.parentNode is not None: 142*cda5da8dSAndroid Build Coastguard Worker newChild.parentNode.removeChild(newChild) 143*cda5da8dSAndroid Build Coastguard Worker try: 144*cda5da8dSAndroid Build Coastguard Worker index = self.childNodes.index(oldChild) 145*cda5da8dSAndroid Build Coastguard Worker except ValueError: 146*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 147*cda5da8dSAndroid Build Coastguard Worker self.childNodes[index] = newChild 148*cda5da8dSAndroid Build Coastguard Worker newChild.parentNode = self 149*cda5da8dSAndroid Build Coastguard Worker oldChild.parentNode = None 150*cda5da8dSAndroid Build Coastguard Worker if (newChild.nodeType in _nodeTypes_with_children 151*cda5da8dSAndroid Build Coastguard Worker or oldChild.nodeType in _nodeTypes_with_children): 152*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self) 153*cda5da8dSAndroid Build Coastguard Worker newChild.nextSibling = oldChild.nextSibling 154*cda5da8dSAndroid Build Coastguard Worker newChild.previousSibling = oldChild.previousSibling 155*cda5da8dSAndroid Build Coastguard Worker oldChild.nextSibling = None 156*cda5da8dSAndroid Build Coastguard Worker oldChild.previousSibling = None 157*cda5da8dSAndroid Build Coastguard Worker if newChild.previousSibling: 158*cda5da8dSAndroid Build Coastguard Worker newChild.previousSibling.nextSibling = newChild 159*cda5da8dSAndroid Build Coastguard Worker if newChild.nextSibling: 160*cda5da8dSAndroid Build Coastguard Worker newChild.nextSibling.previousSibling = newChild 161*cda5da8dSAndroid Build Coastguard Worker return oldChild 162*cda5da8dSAndroid Build Coastguard Worker 163*cda5da8dSAndroid Build Coastguard Worker def removeChild(self, oldChild): 164*cda5da8dSAndroid Build Coastguard Worker try: 165*cda5da8dSAndroid Build Coastguard Worker self.childNodes.remove(oldChild) 166*cda5da8dSAndroid Build Coastguard Worker except ValueError: 167*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 168*cda5da8dSAndroid Build Coastguard Worker if oldChild.nextSibling is not None: 169*cda5da8dSAndroid Build Coastguard Worker oldChild.nextSibling.previousSibling = oldChild.previousSibling 170*cda5da8dSAndroid Build Coastguard Worker if oldChild.previousSibling is not None: 171*cda5da8dSAndroid Build Coastguard Worker oldChild.previousSibling.nextSibling = oldChild.nextSibling 172*cda5da8dSAndroid Build Coastguard Worker oldChild.nextSibling = oldChild.previousSibling = None 173*cda5da8dSAndroid Build Coastguard Worker if oldChild.nodeType in _nodeTypes_with_children: 174*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self) 175*cda5da8dSAndroid Build Coastguard Worker 176*cda5da8dSAndroid Build Coastguard Worker oldChild.parentNode = None 177*cda5da8dSAndroid Build Coastguard Worker return oldChild 178*cda5da8dSAndroid Build Coastguard Worker 179*cda5da8dSAndroid Build Coastguard Worker def normalize(self): 180*cda5da8dSAndroid Build Coastguard Worker L = [] 181*cda5da8dSAndroid Build Coastguard Worker for child in self.childNodes: 182*cda5da8dSAndroid Build Coastguard Worker if child.nodeType == Node.TEXT_NODE: 183*cda5da8dSAndroid Build Coastguard Worker if not child.data: 184*cda5da8dSAndroid Build Coastguard Worker # empty text node; discard 185*cda5da8dSAndroid Build Coastguard Worker if L: 186*cda5da8dSAndroid Build Coastguard Worker L[-1].nextSibling = child.nextSibling 187*cda5da8dSAndroid Build Coastguard Worker if child.nextSibling: 188*cda5da8dSAndroid Build Coastguard Worker child.nextSibling.previousSibling = child.previousSibling 189*cda5da8dSAndroid Build Coastguard Worker child.unlink() 190*cda5da8dSAndroid Build Coastguard Worker elif L and L[-1].nodeType == child.nodeType: 191*cda5da8dSAndroid Build Coastguard Worker # collapse text node 192*cda5da8dSAndroid Build Coastguard Worker node = L[-1] 193*cda5da8dSAndroid Build Coastguard Worker node.data = node.data + child.data 194*cda5da8dSAndroid Build Coastguard Worker node.nextSibling = child.nextSibling 195*cda5da8dSAndroid Build Coastguard Worker if child.nextSibling: 196*cda5da8dSAndroid Build Coastguard Worker child.nextSibling.previousSibling = node 197*cda5da8dSAndroid Build Coastguard Worker child.unlink() 198*cda5da8dSAndroid Build Coastguard Worker else: 199*cda5da8dSAndroid Build Coastguard Worker L.append(child) 200*cda5da8dSAndroid Build Coastguard Worker else: 201*cda5da8dSAndroid Build Coastguard Worker L.append(child) 202*cda5da8dSAndroid Build Coastguard Worker if child.nodeType == Node.ELEMENT_NODE: 203*cda5da8dSAndroid Build Coastguard Worker child.normalize() 204*cda5da8dSAndroid Build Coastguard Worker self.childNodes[:] = L 205*cda5da8dSAndroid Build Coastguard Worker 206*cda5da8dSAndroid Build Coastguard Worker def cloneNode(self, deep): 207*cda5da8dSAndroid Build Coastguard Worker return _clone_node(self, deep, self.ownerDocument or self) 208*cda5da8dSAndroid Build Coastguard Worker 209*cda5da8dSAndroid Build Coastguard Worker def isSupported(self, feature, version): 210*cda5da8dSAndroid Build Coastguard Worker return self.ownerDocument.implementation.hasFeature(feature, version) 211*cda5da8dSAndroid Build Coastguard Worker 212*cda5da8dSAndroid Build Coastguard Worker def _get_localName(self): 213*cda5da8dSAndroid Build Coastguard Worker # Overridden in Element and Attr where localName can be Non-Null 214*cda5da8dSAndroid Build Coastguard Worker return None 215*cda5da8dSAndroid Build Coastguard Worker 216*cda5da8dSAndroid Build Coastguard Worker # Node interfaces from Level 3 (WD 9 April 2002) 217*cda5da8dSAndroid Build Coastguard Worker 218*cda5da8dSAndroid Build Coastguard Worker def isSameNode(self, other): 219*cda5da8dSAndroid Build Coastguard Worker return self is other 220*cda5da8dSAndroid Build Coastguard Worker 221*cda5da8dSAndroid Build Coastguard Worker def getInterface(self, feature): 222*cda5da8dSAndroid Build Coastguard Worker if self.isSupported(feature, None): 223*cda5da8dSAndroid Build Coastguard Worker return self 224*cda5da8dSAndroid Build Coastguard Worker else: 225*cda5da8dSAndroid Build Coastguard Worker return None 226*cda5da8dSAndroid Build Coastguard Worker 227*cda5da8dSAndroid Build Coastguard Worker # The "user data" functions use a dictionary that is only present 228*cda5da8dSAndroid Build Coastguard Worker # if some user data has been set, so be careful not to assume it 229*cda5da8dSAndroid Build Coastguard Worker # exists. 230*cda5da8dSAndroid Build Coastguard Worker 231*cda5da8dSAndroid Build Coastguard Worker def getUserData(self, key): 232*cda5da8dSAndroid Build Coastguard Worker try: 233*cda5da8dSAndroid Build Coastguard Worker return self._user_data[key][0] 234*cda5da8dSAndroid Build Coastguard Worker except (AttributeError, KeyError): 235*cda5da8dSAndroid Build Coastguard Worker return None 236*cda5da8dSAndroid Build Coastguard Worker 237*cda5da8dSAndroid Build Coastguard Worker def setUserData(self, key, data, handler): 238*cda5da8dSAndroid Build Coastguard Worker old = None 239*cda5da8dSAndroid Build Coastguard Worker try: 240*cda5da8dSAndroid Build Coastguard Worker d = self._user_data 241*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 242*cda5da8dSAndroid Build Coastguard Worker d = {} 243*cda5da8dSAndroid Build Coastguard Worker self._user_data = d 244*cda5da8dSAndroid Build Coastguard Worker if key in d: 245*cda5da8dSAndroid Build Coastguard Worker old = d[key][0] 246*cda5da8dSAndroid Build Coastguard Worker if data is None: 247*cda5da8dSAndroid Build Coastguard Worker # ignore handlers passed for None 248*cda5da8dSAndroid Build Coastguard Worker handler = None 249*cda5da8dSAndroid Build Coastguard Worker if old is not None: 250*cda5da8dSAndroid Build Coastguard Worker del d[key] 251*cda5da8dSAndroid Build Coastguard Worker else: 252*cda5da8dSAndroid Build Coastguard Worker d[key] = (data, handler) 253*cda5da8dSAndroid Build Coastguard Worker return old 254*cda5da8dSAndroid Build Coastguard Worker 255*cda5da8dSAndroid Build Coastguard Worker def _call_user_data_handler(self, operation, src, dst): 256*cda5da8dSAndroid Build Coastguard Worker if hasattr(self, "_user_data"): 257*cda5da8dSAndroid Build Coastguard Worker for key, (data, handler) in list(self._user_data.items()): 258*cda5da8dSAndroid Build Coastguard Worker if handler is not None: 259*cda5da8dSAndroid Build Coastguard Worker handler.handle(operation, key, data, src, dst) 260*cda5da8dSAndroid Build Coastguard Worker 261*cda5da8dSAndroid Build Coastguard Worker # minidom-specific API: 262*cda5da8dSAndroid Build Coastguard Worker 263*cda5da8dSAndroid Build Coastguard Worker def unlink(self): 264*cda5da8dSAndroid Build Coastguard Worker self.parentNode = self.ownerDocument = None 265*cda5da8dSAndroid Build Coastguard Worker if self.childNodes: 266*cda5da8dSAndroid Build Coastguard Worker for child in self.childNodes: 267*cda5da8dSAndroid Build Coastguard Worker child.unlink() 268*cda5da8dSAndroid Build Coastguard Worker self.childNodes = NodeList() 269*cda5da8dSAndroid Build Coastguard Worker self.previousSibling = None 270*cda5da8dSAndroid Build Coastguard Worker self.nextSibling = None 271*cda5da8dSAndroid Build Coastguard Worker 272*cda5da8dSAndroid Build Coastguard Worker # A Node is its own context manager, to ensure that an unlink() call occurs. 273*cda5da8dSAndroid Build Coastguard Worker # This is similar to how a file object works. 274*cda5da8dSAndroid Build Coastguard Worker def __enter__(self): 275*cda5da8dSAndroid Build Coastguard Worker return self 276*cda5da8dSAndroid Build Coastguard Worker 277*cda5da8dSAndroid Build Coastguard Worker def __exit__(self, et, ev, tb): 278*cda5da8dSAndroid Build Coastguard Worker self.unlink() 279*cda5da8dSAndroid Build Coastguard Worker 280*cda5da8dSAndroid Build Coastguard Workerdefproperty(Node, "firstChild", doc="First child node, or None.") 281*cda5da8dSAndroid Build Coastguard Workerdefproperty(Node, "lastChild", doc="Last child node, or None.") 282*cda5da8dSAndroid Build Coastguard Workerdefproperty(Node, "localName", doc="Namespace-local name of this node.") 283*cda5da8dSAndroid Build Coastguard Worker 284*cda5da8dSAndroid Build Coastguard Worker 285*cda5da8dSAndroid Build Coastguard Workerdef _append_child(self, node): 286*cda5da8dSAndroid Build Coastguard Worker # fast path with less checks; usable by DOM builders if careful 287*cda5da8dSAndroid Build Coastguard Worker childNodes = self.childNodes 288*cda5da8dSAndroid Build Coastguard Worker if childNodes: 289*cda5da8dSAndroid Build Coastguard Worker last = childNodes[-1] 290*cda5da8dSAndroid Build Coastguard Worker node.previousSibling = last 291*cda5da8dSAndroid Build Coastguard Worker last.nextSibling = node 292*cda5da8dSAndroid Build Coastguard Worker childNodes.append(node) 293*cda5da8dSAndroid Build Coastguard Worker node.parentNode = self 294*cda5da8dSAndroid Build Coastguard Worker 295*cda5da8dSAndroid Build Coastguard Workerdef _in_document(node): 296*cda5da8dSAndroid Build Coastguard Worker # return True iff node is part of a document tree 297*cda5da8dSAndroid Build Coastguard Worker while node is not None: 298*cda5da8dSAndroid Build Coastguard Worker if node.nodeType == Node.DOCUMENT_NODE: 299*cda5da8dSAndroid Build Coastguard Worker return True 300*cda5da8dSAndroid Build Coastguard Worker node = node.parentNode 301*cda5da8dSAndroid Build Coastguard Worker return False 302*cda5da8dSAndroid Build Coastguard Worker 303*cda5da8dSAndroid Build Coastguard Workerdef _write_data(writer, data): 304*cda5da8dSAndroid Build Coastguard Worker "Writes datachars to writer." 305*cda5da8dSAndroid Build Coastguard Worker if data: 306*cda5da8dSAndroid Build Coastguard Worker data = data.replace("&", "&").replace("<", "<"). \ 307*cda5da8dSAndroid Build Coastguard Worker replace("\"", """).replace(">", ">") 308*cda5da8dSAndroid Build Coastguard Worker writer.write(data) 309*cda5da8dSAndroid Build Coastguard Worker 310*cda5da8dSAndroid Build Coastguard Workerdef _get_elements_by_tagName_helper(parent, name, rc): 311*cda5da8dSAndroid Build Coastguard Worker for node in parent.childNodes: 312*cda5da8dSAndroid Build Coastguard Worker if node.nodeType == Node.ELEMENT_NODE and \ 313*cda5da8dSAndroid Build Coastguard Worker (name == "*" or node.tagName == name): 314*cda5da8dSAndroid Build Coastguard Worker rc.append(node) 315*cda5da8dSAndroid Build Coastguard Worker _get_elements_by_tagName_helper(node, name, rc) 316*cda5da8dSAndroid Build Coastguard Worker return rc 317*cda5da8dSAndroid Build Coastguard Worker 318*cda5da8dSAndroid Build Coastguard Workerdef _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc): 319*cda5da8dSAndroid Build Coastguard Worker for node in parent.childNodes: 320*cda5da8dSAndroid Build Coastguard Worker if node.nodeType == Node.ELEMENT_NODE: 321*cda5da8dSAndroid Build Coastguard Worker if ((localName == "*" or node.localName == localName) and 322*cda5da8dSAndroid Build Coastguard Worker (nsURI == "*" or node.namespaceURI == nsURI)): 323*cda5da8dSAndroid Build Coastguard Worker rc.append(node) 324*cda5da8dSAndroid Build Coastguard Worker _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc) 325*cda5da8dSAndroid Build Coastguard Worker return rc 326*cda5da8dSAndroid Build Coastguard Worker 327*cda5da8dSAndroid Build Coastguard Workerclass DocumentFragment(Node): 328*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.DOCUMENT_FRAGMENT_NODE 329*cda5da8dSAndroid Build Coastguard Worker nodeName = "#document-fragment" 330*cda5da8dSAndroid Build Coastguard Worker nodeValue = None 331*cda5da8dSAndroid Build Coastguard Worker attributes = None 332*cda5da8dSAndroid Build Coastguard Worker parentNode = None 333*cda5da8dSAndroid Build Coastguard Worker _child_node_types = (Node.ELEMENT_NODE, 334*cda5da8dSAndroid Build Coastguard Worker Node.TEXT_NODE, 335*cda5da8dSAndroid Build Coastguard Worker Node.CDATA_SECTION_NODE, 336*cda5da8dSAndroid Build Coastguard Worker Node.ENTITY_REFERENCE_NODE, 337*cda5da8dSAndroid Build Coastguard Worker Node.PROCESSING_INSTRUCTION_NODE, 338*cda5da8dSAndroid Build Coastguard Worker Node.COMMENT_NODE, 339*cda5da8dSAndroid Build Coastguard Worker Node.NOTATION_NODE) 340*cda5da8dSAndroid Build Coastguard Worker 341*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 342*cda5da8dSAndroid Build Coastguard Worker self.childNodes = NodeList() 343*cda5da8dSAndroid Build Coastguard Worker 344*cda5da8dSAndroid Build Coastguard Worker 345*cda5da8dSAndroid Build Coastguard Workerclass Attr(Node): 346*cda5da8dSAndroid Build Coastguard Worker __slots__=('_name', '_value', 'namespaceURI', 347*cda5da8dSAndroid Build Coastguard Worker '_prefix', 'childNodes', '_localName', 'ownerDocument', 'ownerElement') 348*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.ATTRIBUTE_NODE 349*cda5da8dSAndroid Build Coastguard Worker attributes = None 350*cda5da8dSAndroid Build Coastguard Worker specified = False 351*cda5da8dSAndroid Build Coastguard Worker _is_id = False 352*cda5da8dSAndroid Build Coastguard Worker 353*cda5da8dSAndroid Build Coastguard Worker _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE) 354*cda5da8dSAndroid Build Coastguard Worker 355*cda5da8dSAndroid Build Coastguard Worker def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None, 356*cda5da8dSAndroid Build Coastguard Worker prefix=None): 357*cda5da8dSAndroid Build Coastguard Worker self.ownerElement = None 358*cda5da8dSAndroid Build Coastguard Worker self._name = qName 359*cda5da8dSAndroid Build Coastguard Worker self.namespaceURI = namespaceURI 360*cda5da8dSAndroid Build Coastguard Worker self._prefix = prefix 361*cda5da8dSAndroid Build Coastguard Worker if localName is not None: 362*cda5da8dSAndroid Build Coastguard Worker self._localName = localName 363*cda5da8dSAndroid Build Coastguard Worker self.childNodes = NodeList() 364*cda5da8dSAndroid Build Coastguard Worker 365*cda5da8dSAndroid Build Coastguard Worker # Add the single child node that represents the value of the attr 366*cda5da8dSAndroid Build Coastguard Worker self.childNodes.append(Text()) 367*cda5da8dSAndroid Build Coastguard Worker 368*cda5da8dSAndroid Build Coastguard Worker # nodeValue and value are set elsewhere 369*cda5da8dSAndroid Build Coastguard Worker 370*cda5da8dSAndroid Build Coastguard Worker def _get_localName(self): 371*cda5da8dSAndroid Build Coastguard Worker try: 372*cda5da8dSAndroid Build Coastguard Worker return self._localName 373*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 374*cda5da8dSAndroid Build Coastguard Worker return self.nodeName.split(":", 1)[-1] 375*cda5da8dSAndroid Build Coastguard Worker 376*cda5da8dSAndroid Build Coastguard Worker def _get_specified(self): 377*cda5da8dSAndroid Build Coastguard Worker return self.specified 378*cda5da8dSAndroid Build Coastguard Worker 379*cda5da8dSAndroid Build Coastguard Worker def _get_name(self): 380*cda5da8dSAndroid Build Coastguard Worker return self._name 381*cda5da8dSAndroid Build Coastguard Worker 382*cda5da8dSAndroid Build Coastguard Worker def _set_name(self, value): 383*cda5da8dSAndroid Build Coastguard Worker self._name = value 384*cda5da8dSAndroid Build Coastguard Worker if self.ownerElement is not None: 385*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self.ownerElement) 386*cda5da8dSAndroid Build Coastguard Worker 387*cda5da8dSAndroid Build Coastguard Worker nodeName = name = property(_get_name, _set_name) 388*cda5da8dSAndroid Build Coastguard Worker 389*cda5da8dSAndroid Build Coastguard Worker def _get_value(self): 390*cda5da8dSAndroid Build Coastguard Worker return self._value 391*cda5da8dSAndroid Build Coastguard Worker 392*cda5da8dSAndroid Build Coastguard Worker def _set_value(self, value): 393*cda5da8dSAndroid Build Coastguard Worker self._value = value 394*cda5da8dSAndroid Build Coastguard Worker self.childNodes[0].data = value 395*cda5da8dSAndroid Build Coastguard Worker if self.ownerElement is not None: 396*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self.ownerElement) 397*cda5da8dSAndroid Build Coastguard Worker self.childNodes[0].data = value 398*cda5da8dSAndroid Build Coastguard Worker 399*cda5da8dSAndroid Build Coastguard Worker nodeValue = value = property(_get_value, _set_value) 400*cda5da8dSAndroid Build Coastguard Worker 401*cda5da8dSAndroid Build Coastguard Worker def _get_prefix(self): 402*cda5da8dSAndroid Build Coastguard Worker return self._prefix 403*cda5da8dSAndroid Build Coastguard Worker 404*cda5da8dSAndroid Build Coastguard Worker def _set_prefix(self, prefix): 405*cda5da8dSAndroid Build Coastguard Worker nsuri = self.namespaceURI 406*cda5da8dSAndroid Build Coastguard Worker if prefix == "xmlns": 407*cda5da8dSAndroid Build Coastguard Worker if nsuri and nsuri != XMLNS_NAMESPACE: 408*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NamespaceErr( 409*cda5da8dSAndroid Build Coastguard Worker "illegal use of 'xmlns' prefix for the wrong namespace") 410*cda5da8dSAndroid Build Coastguard Worker self._prefix = prefix 411*cda5da8dSAndroid Build Coastguard Worker if prefix is None: 412*cda5da8dSAndroid Build Coastguard Worker newName = self.localName 413*cda5da8dSAndroid Build Coastguard Worker else: 414*cda5da8dSAndroid Build Coastguard Worker newName = "%s:%s" % (prefix, self.localName) 415*cda5da8dSAndroid Build Coastguard Worker if self.ownerElement: 416*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self.ownerElement) 417*cda5da8dSAndroid Build Coastguard Worker self.name = newName 418*cda5da8dSAndroid Build Coastguard Worker 419*cda5da8dSAndroid Build Coastguard Worker prefix = property(_get_prefix, _set_prefix) 420*cda5da8dSAndroid Build Coastguard Worker 421*cda5da8dSAndroid Build Coastguard Worker def unlink(self): 422*cda5da8dSAndroid Build Coastguard Worker # This implementation does not call the base implementation 423*cda5da8dSAndroid Build Coastguard Worker # since most of that is not needed, and the expense of the 424*cda5da8dSAndroid Build Coastguard Worker # method call is not warranted. We duplicate the removal of 425*cda5da8dSAndroid Build Coastguard Worker # children, but that's all we needed from the base class. 426*cda5da8dSAndroid Build Coastguard Worker elem = self.ownerElement 427*cda5da8dSAndroid Build Coastguard Worker if elem is not None: 428*cda5da8dSAndroid Build Coastguard Worker del elem._attrs[self.nodeName] 429*cda5da8dSAndroid Build Coastguard Worker del elem._attrsNS[(self.namespaceURI, self.localName)] 430*cda5da8dSAndroid Build Coastguard Worker if self._is_id: 431*cda5da8dSAndroid Build Coastguard Worker self._is_id = False 432*cda5da8dSAndroid Build Coastguard Worker elem._magic_id_nodes -= 1 433*cda5da8dSAndroid Build Coastguard Worker self.ownerDocument._magic_id_count -= 1 434*cda5da8dSAndroid Build Coastguard Worker for child in self.childNodes: 435*cda5da8dSAndroid Build Coastguard Worker child.unlink() 436*cda5da8dSAndroid Build Coastguard Worker del self.childNodes[:] 437*cda5da8dSAndroid Build Coastguard Worker 438*cda5da8dSAndroid Build Coastguard Worker def _get_isId(self): 439*cda5da8dSAndroid Build Coastguard Worker if self._is_id: 440*cda5da8dSAndroid Build Coastguard Worker return True 441*cda5da8dSAndroid Build Coastguard Worker doc = self.ownerDocument 442*cda5da8dSAndroid Build Coastguard Worker elem = self.ownerElement 443*cda5da8dSAndroid Build Coastguard Worker if doc is None or elem is None: 444*cda5da8dSAndroid Build Coastguard Worker return False 445*cda5da8dSAndroid Build Coastguard Worker 446*cda5da8dSAndroid Build Coastguard Worker info = doc._get_elem_info(elem) 447*cda5da8dSAndroid Build Coastguard Worker if info is None: 448*cda5da8dSAndroid Build Coastguard Worker return False 449*cda5da8dSAndroid Build Coastguard Worker if self.namespaceURI: 450*cda5da8dSAndroid Build Coastguard Worker return info.isIdNS(self.namespaceURI, self.localName) 451*cda5da8dSAndroid Build Coastguard Worker else: 452*cda5da8dSAndroid Build Coastguard Worker return info.isId(self.nodeName) 453*cda5da8dSAndroid Build Coastguard Worker 454*cda5da8dSAndroid Build Coastguard Worker def _get_schemaType(self): 455*cda5da8dSAndroid Build Coastguard Worker doc = self.ownerDocument 456*cda5da8dSAndroid Build Coastguard Worker elem = self.ownerElement 457*cda5da8dSAndroid Build Coastguard Worker if doc is None or elem is None: 458*cda5da8dSAndroid Build Coastguard Worker return _no_type 459*cda5da8dSAndroid Build Coastguard Worker 460*cda5da8dSAndroid Build Coastguard Worker info = doc._get_elem_info(elem) 461*cda5da8dSAndroid Build Coastguard Worker if info is None: 462*cda5da8dSAndroid Build Coastguard Worker return _no_type 463*cda5da8dSAndroid Build Coastguard Worker if self.namespaceURI: 464*cda5da8dSAndroid Build Coastguard Worker return info.getAttributeTypeNS(self.namespaceURI, self.localName) 465*cda5da8dSAndroid Build Coastguard Worker else: 466*cda5da8dSAndroid Build Coastguard Worker return info.getAttributeType(self.nodeName) 467*cda5da8dSAndroid Build Coastguard Worker 468*cda5da8dSAndroid Build Coastguard Workerdefproperty(Attr, "isId", doc="True if this attribute is an ID.") 469*cda5da8dSAndroid Build Coastguard Workerdefproperty(Attr, "localName", doc="Namespace-local name of this attribute.") 470*cda5da8dSAndroid Build Coastguard Workerdefproperty(Attr, "schemaType", doc="Schema type for this attribute.") 471*cda5da8dSAndroid Build Coastguard Worker 472*cda5da8dSAndroid Build Coastguard Worker 473*cda5da8dSAndroid Build Coastguard Workerclass NamedNodeMap(object): 474*cda5da8dSAndroid Build Coastguard Worker """The attribute list is a transient interface to the underlying 475*cda5da8dSAndroid Build Coastguard Worker dictionaries. Mutations here will change the underlying element's 476*cda5da8dSAndroid Build Coastguard Worker dictionary. 477*cda5da8dSAndroid Build Coastguard Worker 478*cda5da8dSAndroid Build Coastguard Worker Ordering is imposed artificially and does not reflect the order of 479*cda5da8dSAndroid Build Coastguard Worker attributes as found in an input document. 480*cda5da8dSAndroid Build Coastguard Worker """ 481*cda5da8dSAndroid Build Coastguard Worker 482*cda5da8dSAndroid Build Coastguard Worker __slots__ = ('_attrs', '_attrsNS', '_ownerElement') 483*cda5da8dSAndroid Build Coastguard Worker 484*cda5da8dSAndroid Build Coastguard Worker def __init__(self, attrs, attrsNS, ownerElement): 485*cda5da8dSAndroid Build Coastguard Worker self._attrs = attrs 486*cda5da8dSAndroid Build Coastguard Worker self._attrsNS = attrsNS 487*cda5da8dSAndroid Build Coastguard Worker self._ownerElement = ownerElement 488*cda5da8dSAndroid Build Coastguard Worker 489*cda5da8dSAndroid Build Coastguard Worker def _get_length(self): 490*cda5da8dSAndroid Build Coastguard Worker return len(self._attrs) 491*cda5da8dSAndroid Build Coastguard Worker 492*cda5da8dSAndroid Build Coastguard Worker def item(self, index): 493*cda5da8dSAndroid Build Coastguard Worker try: 494*cda5da8dSAndroid Build Coastguard Worker return self[list(self._attrs.keys())[index]] 495*cda5da8dSAndroid Build Coastguard Worker except IndexError: 496*cda5da8dSAndroid Build Coastguard Worker return None 497*cda5da8dSAndroid Build Coastguard Worker 498*cda5da8dSAndroid Build Coastguard Worker def items(self): 499*cda5da8dSAndroid Build Coastguard Worker L = [] 500*cda5da8dSAndroid Build Coastguard Worker for node in self._attrs.values(): 501*cda5da8dSAndroid Build Coastguard Worker L.append((node.nodeName, node.value)) 502*cda5da8dSAndroid Build Coastguard Worker return L 503*cda5da8dSAndroid Build Coastguard Worker 504*cda5da8dSAndroid Build Coastguard Worker def itemsNS(self): 505*cda5da8dSAndroid Build Coastguard Worker L = [] 506*cda5da8dSAndroid Build Coastguard Worker for node in self._attrs.values(): 507*cda5da8dSAndroid Build Coastguard Worker L.append(((node.namespaceURI, node.localName), node.value)) 508*cda5da8dSAndroid Build Coastguard Worker return L 509*cda5da8dSAndroid Build Coastguard Worker 510*cda5da8dSAndroid Build Coastguard Worker def __contains__(self, key): 511*cda5da8dSAndroid Build Coastguard Worker if isinstance(key, str): 512*cda5da8dSAndroid Build Coastguard Worker return key in self._attrs 513*cda5da8dSAndroid Build Coastguard Worker else: 514*cda5da8dSAndroid Build Coastguard Worker return key in self._attrsNS 515*cda5da8dSAndroid Build Coastguard Worker 516*cda5da8dSAndroid Build Coastguard Worker def keys(self): 517*cda5da8dSAndroid Build Coastguard Worker return self._attrs.keys() 518*cda5da8dSAndroid Build Coastguard Worker 519*cda5da8dSAndroid Build Coastguard Worker def keysNS(self): 520*cda5da8dSAndroid Build Coastguard Worker return self._attrsNS.keys() 521*cda5da8dSAndroid Build Coastguard Worker 522*cda5da8dSAndroid Build Coastguard Worker def values(self): 523*cda5da8dSAndroid Build Coastguard Worker return self._attrs.values() 524*cda5da8dSAndroid Build Coastguard Worker 525*cda5da8dSAndroid Build Coastguard Worker def get(self, name, value=None): 526*cda5da8dSAndroid Build Coastguard Worker return self._attrs.get(name, value) 527*cda5da8dSAndroid Build Coastguard Worker 528*cda5da8dSAndroid Build Coastguard Worker __len__ = _get_length 529*cda5da8dSAndroid Build Coastguard Worker 530*cda5da8dSAndroid Build Coastguard Worker def _cmp(self, other): 531*cda5da8dSAndroid Build Coastguard Worker if self._attrs is getattr(other, "_attrs", None): 532*cda5da8dSAndroid Build Coastguard Worker return 0 533*cda5da8dSAndroid Build Coastguard Worker else: 534*cda5da8dSAndroid Build Coastguard Worker return (id(self) > id(other)) - (id(self) < id(other)) 535*cda5da8dSAndroid Build Coastguard Worker 536*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 537*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) == 0 538*cda5da8dSAndroid Build Coastguard Worker 539*cda5da8dSAndroid Build Coastguard Worker def __ge__(self, other): 540*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) >= 0 541*cda5da8dSAndroid Build Coastguard Worker 542*cda5da8dSAndroid Build Coastguard Worker def __gt__(self, other): 543*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) > 0 544*cda5da8dSAndroid Build Coastguard Worker 545*cda5da8dSAndroid Build Coastguard Worker def __le__(self, other): 546*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) <= 0 547*cda5da8dSAndroid Build Coastguard Worker 548*cda5da8dSAndroid Build Coastguard Worker def __lt__(self, other): 549*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) < 0 550*cda5da8dSAndroid Build Coastguard Worker 551*cda5da8dSAndroid Build Coastguard Worker def __getitem__(self, attname_or_tuple): 552*cda5da8dSAndroid Build Coastguard Worker if isinstance(attname_or_tuple, tuple): 553*cda5da8dSAndroid Build Coastguard Worker return self._attrsNS[attname_or_tuple] 554*cda5da8dSAndroid Build Coastguard Worker else: 555*cda5da8dSAndroid Build Coastguard Worker return self._attrs[attname_or_tuple] 556*cda5da8dSAndroid Build Coastguard Worker 557*cda5da8dSAndroid Build Coastguard Worker # same as set 558*cda5da8dSAndroid Build Coastguard Worker def __setitem__(self, attname, value): 559*cda5da8dSAndroid Build Coastguard Worker if isinstance(value, str): 560*cda5da8dSAndroid Build Coastguard Worker try: 561*cda5da8dSAndroid Build Coastguard Worker node = self._attrs[attname] 562*cda5da8dSAndroid Build Coastguard Worker except KeyError: 563*cda5da8dSAndroid Build Coastguard Worker node = Attr(attname) 564*cda5da8dSAndroid Build Coastguard Worker node.ownerDocument = self._ownerElement.ownerDocument 565*cda5da8dSAndroid Build Coastguard Worker self.setNamedItem(node) 566*cda5da8dSAndroid Build Coastguard Worker node.value = value 567*cda5da8dSAndroid Build Coastguard Worker else: 568*cda5da8dSAndroid Build Coastguard Worker if not isinstance(value, Attr): 569*cda5da8dSAndroid Build Coastguard Worker raise TypeError("value must be a string or Attr object") 570*cda5da8dSAndroid Build Coastguard Worker node = value 571*cda5da8dSAndroid Build Coastguard Worker self.setNamedItem(node) 572*cda5da8dSAndroid Build Coastguard Worker 573*cda5da8dSAndroid Build Coastguard Worker def getNamedItem(self, name): 574*cda5da8dSAndroid Build Coastguard Worker try: 575*cda5da8dSAndroid Build Coastguard Worker return self._attrs[name] 576*cda5da8dSAndroid Build Coastguard Worker except KeyError: 577*cda5da8dSAndroid Build Coastguard Worker return None 578*cda5da8dSAndroid Build Coastguard Worker 579*cda5da8dSAndroid Build Coastguard Worker def getNamedItemNS(self, namespaceURI, localName): 580*cda5da8dSAndroid Build Coastguard Worker try: 581*cda5da8dSAndroid Build Coastguard Worker return self._attrsNS[(namespaceURI, localName)] 582*cda5da8dSAndroid Build Coastguard Worker except KeyError: 583*cda5da8dSAndroid Build Coastguard Worker return None 584*cda5da8dSAndroid Build Coastguard Worker 585*cda5da8dSAndroid Build Coastguard Worker def removeNamedItem(self, name): 586*cda5da8dSAndroid Build Coastguard Worker n = self.getNamedItem(name) 587*cda5da8dSAndroid Build Coastguard Worker if n is not None: 588*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self._ownerElement) 589*cda5da8dSAndroid Build Coastguard Worker del self._attrs[n.nodeName] 590*cda5da8dSAndroid Build Coastguard Worker del self._attrsNS[(n.namespaceURI, n.localName)] 591*cda5da8dSAndroid Build Coastguard Worker if hasattr(n, 'ownerElement'): 592*cda5da8dSAndroid Build Coastguard Worker n.ownerElement = None 593*cda5da8dSAndroid Build Coastguard Worker return n 594*cda5da8dSAndroid Build Coastguard Worker else: 595*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 596*cda5da8dSAndroid Build Coastguard Worker 597*cda5da8dSAndroid Build Coastguard Worker def removeNamedItemNS(self, namespaceURI, localName): 598*cda5da8dSAndroid Build Coastguard Worker n = self.getNamedItemNS(namespaceURI, localName) 599*cda5da8dSAndroid Build Coastguard Worker if n is not None: 600*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self._ownerElement) 601*cda5da8dSAndroid Build Coastguard Worker del self._attrsNS[(n.namespaceURI, n.localName)] 602*cda5da8dSAndroid Build Coastguard Worker del self._attrs[n.nodeName] 603*cda5da8dSAndroid Build Coastguard Worker if hasattr(n, 'ownerElement'): 604*cda5da8dSAndroid Build Coastguard Worker n.ownerElement = None 605*cda5da8dSAndroid Build Coastguard Worker return n 606*cda5da8dSAndroid Build Coastguard Worker else: 607*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 608*cda5da8dSAndroid Build Coastguard Worker 609*cda5da8dSAndroid Build Coastguard Worker def setNamedItem(self, node): 610*cda5da8dSAndroid Build Coastguard Worker if not isinstance(node, Attr): 611*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 612*cda5da8dSAndroid Build Coastguard Worker "%s cannot be child of %s" % (repr(node), repr(self))) 613*cda5da8dSAndroid Build Coastguard Worker old = self._attrs.get(node.name) 614*cda5da8dSAndroid Build Coastguard Worker if old: 615*cda5da8dSAndroid Build Coastguard Worker old.unlink() 616*cda5da8dSAndroid Build Coastguard Worker self._attrs[node.name] = node 617*cda5da8dSAndroid Build Coastguard Worker self._attrsNS[(node.namespaceURI, node.localName)] = node 618*cda5da8dSAndroid Build Coastguard Worker node.ownerElement = self._ownerElement 619*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(node.ownerElement) 620*cda5da8dSAndroid Build Coastguard Worker return old 621*cda5da8dSAndroid Build Coastguard Worker 622*cda5da8dSAndroid Build Coastguard Worker def setNamedItemNS(self, node): 623*cda5da8dSAndroid Build Coastguard Worker return self.setNamedItem(node) 624*cda5da8dSAndroid Build Coastguard Worker 625*cda5da8dSAndroid Build Coastguard Worker def __delitem__(self, attname_or_tuple): 626*cda5da8dSAndroid Build Coastguard Worker node = self[attname_or_tuple] 627*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(node.ownerElement) 628*cda5da8dSAndroid Build Coastguard Worker node.unlink() 629*cda5da8dSAndroid Build Coastguard Worker 630*cda5da8dSAndroid Build Coastguard Worker def __getstate__(self): 631*cda5da8dSAndroid Build Coastguard Worker return self._attrs, self._attrsNS, self._ownerElement 632*cda5da8dSAndroid Build Coastguard Worker 633*cda5da8dSAndroid Build Coastguard Worker def __setstate__(self, state): 634*cda5da8dSAndroid Build Coastguard Worker self._attrs, self._attrsNS, self._ownerElement = state 635*cda5da8dSAndroid Build Coastguard Worker 636*cda5da8dSAndroid Build Coastguard Workerdefproperty(NamedNodeMap, "length", 637*cda5da8dSAndroid Build Coastguard Worker doc="Number of nodes in the NamedNodeMap.") 638*cda5da8dSAndroid Build Coastguard Worker 639*cda5da8dSAndroid Build Coastguard WorkerAttributeList = NamedNodeMap 640*cda5da8dSAndroid Build Coastguard Worker 641*cda5da8dSAndroid Build Coastguard Worker 642*cda5da8dSAndroid Build Coastguard Workerclass TypeInfo(object): 643*cda5da8dSAndroid Build Coastguard Worker __slots__ = 'namespace', 'name' 644*cda5da8dSAndroid Build Coastguard Worker 645*cda5da8dSAndroid Build Coastguard Worker def __init__(self, namespace, name): 646*cda5da8dSAndroid Build Coastguard Worker self.namespace = namespace 647*cda5da8dSAndroid Build Coastguard Worker self.name = name 648*cda5da8dSAndroid Build Coastguard Worker 649*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 650*cda5da8dSAndroid Build Coastguard Worker if self.namespace: 651*cda5da8dSAndroid Build Coastguard Worker return "<%s %r (from %r)>" % (self.__class__.__name__, self.name, 652*cda5da8dSAndroid Build Coastguard Worker self.namespace) 653*cda5da8dSAndroid Build Coastguard Worker else: 654*cda5da8dSAndroid Build Coastguard Worker return "<%s %r>" % (self.__class__.__name__, self.name) 655*cda5da8dSAndroid Build Coastguard Worker 656*cda5da8dSAndroid Build Coastguard Worker def _get_name(self): 657*cda5da8dSAndroid Build Coastguard Worker return self.name 658*cda5da8dSAndroid Build Coastguard Worker 659*cda5da8dSAndroid Build Coastguard Worker def _get_namespace(self): 660*cda5da8dSAndroid Build Coastguard Worker return self.namespace 661*cda5da8dSAndroid Build Coastguard Worker 662*cda5da8dSAndroid Build Coastguard Worker_no_type = TypeInfo(None, None) 663*cda5da8dSAndroid Build Coastguard Worker 664*cda5da8dSAndroid Build Coastguard Workerclass Element(Node): 665*cda5da8dSAndroid Build Coastguard Worker __slots__=('ownerDocument', 'parentNode', 'tagName', 'nodeName', 'prefix', 666*cda5da8dSAndroid Build Coastguard Worker 'namespaceURI', '_localName', 'childNodes', '_attrs', '_attrsNS', 667*cda5da8dSAndroid Build Coastguard Worker 'nextSibling', 'previousSibling') 668*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.ELEMENT_NODE 669*cda5da8dSAndroid Build Coastguard Worker nodeValue = None 670*cda5da8dSAndroid Build Coastguard Worker schemaType = _no_type 671*cda5da8dSAndroid Build Coastguard Worker 672*cda5da8dSAndroid Build Coastguard Worker _magic_id_nodes = 0 673*cda5da8dSAndroid Build Coastguard Worker 674*cda5da8dSAndroid Build Coastguard Worker _child_node_types = (Node.ELEMENT_NODE, 675*cda5da8dSAndroid Build Coastguard Worker Node.PROCESSING_INSTRUCTION_NODE, 676*cda5da8dSAndroid Build Coastguard Worker Node.COMMENT_NODE, 677*cda5da8dSAndroid Build Coastguard Worker Node.TEXT_NODE, 678*cda5da8dSAndroid Build Coastguard Worker Node.CDATA_SECTION_NODE, 679*cda5da8dSAndroid Build Coastguard Worker Node.ENTITY_REFERENCE_NODE) 680*cda5da8dSAndroid Build Coastguard Worker 681*cda5da8dSAndroid Build Coastguard Worker def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None, 682*cda5da8dSAndroid Build Coastguard Worker localName=None): 683*cda5da8dSAndroid Build Coastguard Worker self.parentNode = None 684*cda5da8dSAndroid Build Coastguard Worker self.tagName = self.nodeName = tagName 685*cda5da8dSAndroid Build Coastguard Worker self.prefix = prefix 686*cda5da8dSAndroid Build Coastguard Worker self.namespaceURI = namespaceURI 687*cda5da8dSAndroid Build Coastguard Worker self.childNodes = NodeList() 688*cda5da8dSAndroid Build Coastguard Worker self.nextSibling = self.previousSibling = None 689*cda5da8dSAndroid Build Coastguard Worker 690*cda5da8dSAndroid Build Coastguard Worker # Attribute dictionaries are lazily created 691*cda5da8dSAndroid Build Coastguard Worker # attributes are double-indexed: 692*cda5da8dSAndroid Build Coastguard Worker # tagName -> Attribute 693*cda5da8dSAndroid Build Coastguard Worker # URI,localName -> Attribute 694*cda5da8dSAndroid Build Coastguard Worker # in the future: consider lazy generation 695*cda5da8dSAndroid Build Coastguard Worker # of attribute objects this is too tricky 696*cda5da8dSAndroid Build Coastguard Worker # for now because of headaches with 697*cda5da8dSAndroid Build Coastguard Worker # namespaces. 698*cda5da8dSAndroid Build Coastguard Worker self._attrs = None 699*cda5da8dSAndroid Build Coastguard Worker self._attrsNS = None 700*cda5da8dSAndroid Build Coastguard Worker 701*cda5da8dSAndroid Build Coastguard Worker def _ensure_attributes(self): 702*cda5da8dSAndroid Build Coastguard Worker if self._attrs is None: 703*cda5da8dSAndroid Build Coastguard Worker self._attrs = {} 704*cda5da8dSAndroid Build Coastguard Worker self._attrsNS = {} 705*cda5da8dSAndroid Build Coastguard Worker 706*cda5da8dSAndroid Build Coastguard Worker def _get_localName(self): 707*cda5da8dSAndroid Build Coastguard Worker try: 708*cda5da8dSAndroid Build Coastguard Worker return self._localName 709*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 710*cda5da8dSAndroid Build Coastguard Worker return self.tagName.split(":", 1)[-1] 711*cda5da8dSAndroid Build Coastguard Worker 712*cda5da8dSAndroid Build Coastguard Worker def _get_tagName(self): 713*cda5da8dSAndroid Build Coastguard Worker return self.tagName 714*cda5da8dSAndroid Build Coastguard Worker 715*cda5da8dSAndroid Build Coastguard Worker def unlink(self): 716*cda5da8dSAndroid Build Coastguard Worker if self._attrs is not None: 717*cda5da8dSAndroid Build Coastguard Worker for attr in list(self._attrs.values()): 718*cda5da8dSAndroid Build Coastguard Worker attr.unlink() 719*cda5da8dSAndroid Build Coastguard Worker self._attrs = None 720*cda5da8dSAndroid Build Coastguard Worker self._attrsNS = None 721*cda5da8dSAndroid Build Coastguard Worker Node.unlink(self) 722*cda5da8dSAndroid Build Coastguard Worker 723*cda5da8dSAndroid Build Coastguard Worker def getAttribute(self, attname): 724*cda5da8dSAndroid Build Coastguard Worker """Returns the value of the specified attribute. 725*cda5da8dSAndroid Build Coastguard Worker 726*cda5da8dSAndroid Build Coastguard Worker Returns the value of the element's attribute named attname as 727*cda5da8dSAndroid Build Coastguard Worker a string. An empty string is returned if the element does not 728*cda5da8dSAndroid Build Coastguard Worker have such an attribute. Note that an empty string may also be 729*cda5da8dSAndroid Build Coastguard Worker returned as an explicitly given attribute value, use the 730*cda5da8dSAndroid Build Coastguard Worker hasAttribute method to distinguish these two cases. 731*cda5da8dSAndroid Build Coastguard Worker """ 732*cda5da8dSAndroid Build Coastguard Worker if self._attrs is None: 733*cda5da8dSAndroid Build Coastguard Worker return "" 734*cda5da8dSAndroid Build Coastguard Worker try: 735*cda5da8dSAndroid Build Coastguard Worker return self._attrs[attname].value 736*cda5da8dSAndroid Build Coastguard Worker except KeyError: 737*cda5da8dSAndroid Build Coastguard Worker return "" 738*cda5da8dSAndroid Build Coastguard Worker 739*cda5da8dSAndroid Build Coastguard Worker def getAttributeNS(self, namespaceURI, localName): 740*cda5da8dSAndroid Build Coastguard Worker if self._attrsNS is None: 741*cda5da8dSAndroid Build Coastguard Worker return "" 742*cda5da8dSAndroid Build Coastguard Worker try: 743*cda5da8dSAndroid Build Coastguard Worker return self._attrsNS[(namespaceURI, localName)].value 744*cda5da8dSAndroid Build Coastguard Worker except KeyError: 745*cda5da8dSAndroid Build Coastguard Worker return "" 746*cda5da8dSAndroid Build Coastguard Worker 747*cda5da8dSAndroid Build Coastguard Worker def setAttribute(self, attname, value): 748*cda5da8dSAndroid Build Coastguard Worker attr = self.getAttributeNode(attname) 749*cda5da8dSAndroid Build Coastguard Worker if attr is None: 750*cda5da8dSAndroid Build Coastguard Worker attr = Attr(attname) 751*cda5da8dSAndroid Build Coastguard Worker attr.value = value # also sets nodeValue 752*cda5da8dSAndroid Build Coastguard Worker attr.ownerDocument = self.ownerDocument 753*cda5da8dSAndroid Build Coastguard Worker self.setAttributeNode(attr) 754*cda5da8dSAndroid Build Coastguard Worker elif value != attr.value: 755*cda5da8dSAndroid Build Coastguard Worker attr.value = value 756*cda5da8dSAndroid Build Coastguard Worker if attr.isId: 757*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self) 758*cda5da8dSAndroid Build Coastguard Worker 759*cda5da8dSAndroid Build Coastguard Worker def setAttributeNS(self, namespaceURI, qualifiedName, value): 760*cda5da8dSAndroid Build Coastguard Worker prefix, localname = _nssplit(qualifiedName) 761*cda5da8dSAndroid Build Coastguard Worker attr = self.getAttributeNodeNS(namespaceURI, localname) 762*cda5da8dSAndroid Build Coastguard Worker if attr is None: 763*cda5da8dSAndroid Build Coastguard Worker attr = Attr(qualifiedName, namespaceURI, localname, prefix) 764*cda5da8dSAndroid Build Coastguard Worker attr.value = value 765*cda5da8dSAndroid Build Coastguard Worker attr.ownerDocument = self.ownerDocument 766*cda5da8dSAndroid Build Coastguard Worker self.setAttributeNode(attr) 767*cda5da8dSAndroid Build Coastguard Worker else: 768*cda5da8dSAndroid Build Coastguard Worker if value != attr.value: 769*cda5da8dSAndroid Build Coastguard Worker attr.value = value 770*cda5da8dSAndroid Build Coastguard Worker if attr.isId: 771*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self) 772*cda5da8dSAndroid Build Coastguard Worker if attr.prefix != prefix: 773*cda5da8dSAndroid Build Coastguard Worker attr.prefix = prefix 774*cda5da8dSAndroid Build Coastguard Worker attr.nodeName = qualifiedName 775*cda5da8dSAndroid Build Coastguard Worker 776*cda5da8dSAndroid Build Coastguard Worker def getAttributeNode(self, attrname): 777*cda5da8dSAndroid Build Coastguard Worker if self._attrs is None: 778*cda5da8dSAndroid Build Coastguard Worker return None 779*cda5da8dSAndroid Build Coastguard Worker return self._attrs.get(attrname) 780*cda5da8dSAndroid Build Coastguard Worker 781*cda5da8dSAndroid Build Coastguard Worker def getAttributeNodeNS(self, namespaceURI, localName): 782*cda5da8dSAndroid Build Coastguard Worker if self._attrsNS is None: 783*cda5da8dSAndroid Build Coastguard Worker return None 784*cda5da8dSAndroid Build Coastguard Worker return self._attrsNS.get((namespaceURI, localName)) 785*cda5da8dSAndroid Build Coastguard Worker 786*cda5da8dSAndroid Build Coastguard Worker def setAttributeNode(self, attr): 787*cda5da8dSAndroid Build Coastguard Worker if attr.ownerElement not in (None, self): 788*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.InuseAttributeErr("attribute node already owned") 789*cda5da8dSAndroid Build Coastguard Worker self._ensure_attributes() 790*cda5da8dSAndroid Build Coastguard Worker old1 = self._attrs.get(attr.name, None) 791*cda5da8dSAndroid Build Coastguard Worker if old1 is not None: 792*cda5da8dSAndroid Build Coastguard Worker self.removeAttributeNode(old1) 793*cda5da8dSAndroid Build Coastguard Worker old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None) 794*cda5da8dSAndroid Build Coastguard Worker if old2 is not None and old2 is not old1: 795*cda5da8dSAndroid Build Coastguard Worker self.removeAttributeNode(old2) 796*cda5da8dSAndroid Build Coastguard Worker _set_attribute_node(self, attr) 797*cda5da8dSAndroid Build Coastguard Worker 798*cda5da8dSAndroid Build Coastguard Worker if old1 is not attr: 799*cda5da8dSAndroid Build Coastguard Worker # It might have already been part of this node, in which case 800*cda5da8dSAndroid Build Coastguard Worker # it doesn't represent a change, and should not be returned. 801*cda5da8dSAndroid Build Coastguard Worker return old1 802*cda5da8dSAndroid Build Coastguard Worker if old2 is not attr: 803*cda5da8dSAndroid Build Coastguard Worker return old2 804*cda5da8dSAndroid Build Coastguard Worker 805*cda5da8dSAndroid Build Coastguard Worker setAttributeNodeNS = setAttributeNode 806*cda5da8dSAndroid Build Coastguard Worker 807*cda5da8dSAndroid Build Coastguard Worker def removeAttribute(self, name): 808*cda5da8dSAndroid Build Coastguard Worker if self._attrsNS is None: 809*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 810*cda5da8dSAndroid Build Coastguard Worker try: 811*cda5da8dSAndroid Build Coastguard Worker attr = self._attrs[name] 812*cda5da8dSAndroid Build Coastguard Worker except KeyError: 813*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 814*cda5da8dSAndroid Build Coastguard Worker self.removeAttributeNode(attr) 815*cda5da8dSAndroid Build Coastguard Worker 816*cda5da8dSAndroid Build Coastguard Worker def removeAttributeNS(self, namespaceURI, localName): 817*cda5da8dSAndroid Build Coastguard Worker if self._attrsNS is None: 818*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 819*cda5da8dSAndroid Build Coastguard Worker try: 820*cda5da8dSAndroid Build Coastguard Worker attr = self._attrsNS[(namespaceURI, localName)] 821*cda5da8dSAndroid Build Coastguard Worker except KeyError: 822*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 823*cda5da8dSAndroid Build Coastguard Worker self.removeAttributeNode(attr) 824*cda5da8dSAndroid Build Coastguard Worker 825*cda5da8dSAndroid Build Coastguard Worker def removeAttributeNode(self, node): 826*cda5da8dSAndroid Build Coastguard Worker if node is None: 827*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 828*cda5da8dSAndroid Build Coastguard Worker try: 829*cda5da8dSAndroid Build Coastguard Worker self._attrs[node.name] 830*cda5da8dSAndroid Build Coastguard Worker except KeyError: 831*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 832*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self) 833*cda5da8dSAndroid Build Coastguard Worker node.unlink() 834*cda5da8dSAndroid Build Coastguard Worker # Restore this since the node is still useful and otherwise 835*cda5da8dSAndroid Build Coastguard Worker # unlinked 836*cda5da8dSAndroid Build Coastguard Worker node.ownerDocument = self.ownerDocument 837*cda5da8dSAndroid Build Coastguard Worker return node 838*cda5da8dSAndroid Build Coastguard Worker 839*cda5da8dSAndroid Build Coastguard Worker removeAttributeNodeNS = removeAttributeNode 840*cda5da8dSAndroid Build Coastguard Worker 841*cda5da8dSAndroid Build Coastguard Worker def hasAttribute(self, name): 842*cda5da8dSAndroid Build Coastguard Worker """Checks whether the element has an attribute with the specified name. 843*cda5da8dSAndroid Build Coastguard Worker 844*cda5da8dSAndroid Build Coastguard Worker Returns True if the element has an attribute with the specified name. 845*cda5da8dSAndroid Build Coastguard Worker Otherwise, returns False. 846*cda5da8dSAndroid Build Coastguard Worker """ 847*cda5da8dSAndroid Build Coastguard Worker if self._attrs is None: 848*cda5da8dSAndroid Build Coastguard Worker return False 849*cda5da8dSAndroid Build Coastguard Worker return name in self._attrs 850*cda5da8dSAndroid Build Coastguard Worker 851*cda5da8dSAndroid Build Coastguard Worker def hasAttributeNS(self, namespaceURI, localName): 852*cda5da8dSAndroid Build Coastguard Worker if self._attrsNS is None: 853*cda5da8dSAndroid Build Coastguard Worker return False 854*cda5da8dSAndroid Build Coastguard Worker return (namespaceURI, localName) in self._attrsNS 855*cda5da8dSAndroid Build Coastguard Worker 856*cda5da8dSAndroid Build Coastguard Worker def getElementsByTagName(self, name): 857*cda5da8dSAndroid Build Coastguard Worker """Returns all descendant elements with the given tag name. 858*cda5da8dSAndroid Build Coastguard Worker 859*cda5da8dSAndroid Build Coastguard Worker Returns the list of all descendant elements (not direct children 860*cda5da8dSAndroid Build Coastguard Worker only) with the specified tag name. 861*cda5da8dSAndroid Build Coastguard Worker """ 862*cda5da8dSAndroid Build Coastguard Worker return _get_elements_by_tagName_helper(self, name, NodeList()) 863*cda5da8dSAndroid Build Coastguard Worker 864*cda5da8dSAndroid Build Coastguard Worker def getElementsByTagNameNS(self, namespaceURI, localName): 865*cda5da8dSAndroid Build Coastguard Worker return _get_elements_by_tagName_ns_helper( 866*cda5da8dSAndroid Build Coastguard Worker self, namespaceURI, localName, NodeList()) 867*cda5da8dSAndroid Build Coastguard Worker 868*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 869*cda5da8dSAndroid Build Coastguard Worker return "<DOM Element: %s at %#x>" % (self.tagName, id(self)) 870*cda5da8dSAndroid Build Coastguard Worker 871*cda5da8dSAndroid Build Coastguard Worker def writexml(self, writer, indent="", addindent="", newl=""): 872*cda5da8dSAndroid Build Coastguard Worker """Write an XML element to a file-like object 873*cda5da8dSAndroid Build Coastguard Worker 874*cda5da8dSAndroid Build Coastguard Worker Write the element to the writer object that must provide 875*cda5da8dSAndroid Build Coastguard Worker a write method (e.g. a file or StringIO object). 876*cda5da8dSAndroid Build Coastguard Worker """ 877*cda5da8dSAndroid Build Coastguard Worker # indent = current indentation 878*cda5da8dSAndroid Build Coastguard Worker # addindent = indentation to add to higher levels 879*cda5da8dSAndroid Build Coastguard Worker # newl = newline string 880*cda5da8dSAndroid Build Coastguard Worker writer.write(indent+"<" + self.tagName) 881*cda5da8dSAndroid Build Coastguard Worker 882*cda5da8dSAndroid Build Coastguard Worker attrs = self._get_attributes() 883*cda5da8dSAndroid Build Coastguard Worker 884*cda5da8dSAndroid Build Coastguard Worker for a_name in attrs.keys(): 885*cda5da8dSAndroid Build Coastguard Worker writer.write(" %s=\"" % a_name) 886*cda5da8dSAndroid Build Coastguard Worker _write_data(writer, attrs[a_name].value) 887*cda5da8dSAndroid Build Coastguard Worker writer.write("\"") 888*cda5da8dSAndroid Build Coastguard Worker if self.childNodes: 889*cda5da8dSAndroid Build Coastguard Worker writer.write(">") 890*cda5da8dSAndroid Build Coastguard Worker if (len(self.childNodes) == 1 and 891*cda5da8dSAndroid Build Coastguard Worker self.childNodes[0].nodeType in ( 892*cda5da8dSAndroid Build Coastguard Worker Node.TEXT_NODE, Node.CDATA_SECTION_NODE)): 893*cda5da8dSAndroid Build Coastguard Worker self.childNodes[0].writexml(writer, '', '', '') 894*cda5da8dSAndroid Build Coastguard Worker else: 895*cda5da8dSAndroid Build Coastguard Worker writer.write(newl) 896*cda5da8dSAndroid Build Coastguard Worker for node in self.childNodes: 897*cda5da8dSAndroid Build Coastguard Worker node.writexml(writer, indent+addindent, addindent, newl) 898*cda5da8dSAndroid Build Coastguard Worker writer.write(indent) 899*cda5da8dSAndroid Build Coastguard Worker writer.write("</%s>%s" % (self.tagName, newl)) 900*cda5da8dSAndroid Build Coastguard Worker else: 901*cda5da8dSAndroid Build Coastguard Worker writer.write("/>%s"%(newl)) 902*cda5da8dSAndroid Build Coastguard Worker 903*cda5da8dSAndroid Build Coastguard Worker def _get_attributes(self): 904*cda5da8dSAndroid Build Coastguard Worker self._ensure_attributes() 905*cda5da8dSAndroid Build Coastguard Worker return NamedNodeMap(self._attrs, self._attrsNS, self) 906*cda5da8dSAndroid Build Coastguard Worker 907*cda5da8dSAndroid Build Coastguard Worker def hasAttributes(self): 908*cda5da8dSAndroid Build Coastguard Worker if self._attrs: 909*cda5da8dSAndroid Build Coastguard Worker return True 910*cda5da8dSAndroid Build Coastguard Worker else: 911*cda5da8dSAndroid Build Coastguard Worker return False 912*cda5da8dSAndroid Build Coastguard Worker 913*cda5da8dSAndroid Build Coastguard Worker # DOM Level 3 attributes, based on the 22 Oct 2002 draft 914*cda5da8dSAndroid Build Coastguard Worker 915*cda5da8dSAndroid Build Coastguard Worker def setIdAttribute(self, name): 916*cda5da8dSAndroid Build Coastguard Worker idAttr = self.getAttributeNode(name) 917*cda5da8dSAndroid Build Coastguard Worker self.setIdAttributeNode(idAttr) 918*cda5da8dSAndroid Build Coastguard Worker 919*cda5da8dSAndroid Build Coastguard Worker def setIdAttributeNS(self, namespaceURI, localName): 920*cda5da8dSAndroid Build Coastguard Worker idAttr = self.getAttributeNodeNS(namespaceURI, localName) 921*cda5da8dSAndroid Build Coastguard Worker self.setIdAttributeNode(idAttr) 922*cda5da8dSAndroid Build Coastguard Worker 923*cda5da8dSAndroid Build Coastguard Worker def setIdAttributeNode(self, idAttr): 924*cda5da8dSAndroid Build Coastguard Worker if idAttr is None or not self.isSameNode(idAttr.ownerElement): 925*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 926*cda5da8dSAndroid Build Coastguard Worker if _get_containing_entref(self) is not None: 927*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NoModificationAllowedErr() 928*cda5da8dSAndroid Build Coastguard Worker if not idAttr._is_id: 929*cda5da8dSAndroid Build Coastguard Worker idAttr._is_id = True 930*cda5da8dSAndroid Build Coastguard Worker self._magic_id_nodes += 1 931*cda5da8dSAndroid Build Coastguard Worker self.ownerDocument._magic_id_count += 1 932*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(self) 933*cda5da8dSAndroid Build Coastguard Worker 934*cda5da8dSAndroid Build Coastguard Workerdefproperty(Element, "attributes", 935*cda5da8dSAndroid Build Coastguard Worker doc="NamedNodeMap of attributes on the element.") 936*cda5da8dSAndroid Build Coastguard Workerdefproperty(Element, "localName", 937*cda5da8dSAndroid Build Coastguard Worker doc="Namespace-local name of this element.") 938*cda5da8dSAndroid Build Coastguard Worker 939*cda5da8dSAndroid Build Coastguard Worker 940*cda5da8dSAndroid Build Coastguard Workerdef _set_attribute_node(element, attr): 941*cda5da8dSAndroid Build Coastguard Worker _clear_id_cache(element) 942*cda5da8dSAndroid Build Coastguard Worker element._ensure_attributes() 943*cda5da8dSAndroid Build Coastguard Worker element._attrs[attr.name] = attr 944*cda5da8dSAndroid Build Coastguard Worker element._attrsNS[(attr.namespaceURI, attr.localName)] = attr 945*cda5da8dSAndroid Build Coastguard Worker 946*cda5da8dSAndroid Build Coastguard Worker # This creates a circular reference, but Element.unlink() 947*cda5da8dSAndroid Build Coastguard Worker # breaks the cycle since the references to the attribute 948*cda5da8dSAndroid Build Coastguard Worker # dictionaries are tossed. 949*cda5da8dSAndroid Build Coastguard Worker attr.ownerElement = element 950*cda5da8dSAndroid Build Coastguard Worker 951*cda5da8dSAndroid Build Coastguard Workerclass Childless: 952*cda5da8dSAndroid Build Coastguard Worker """Mixin that makes childless-ness easy to implement and avoids 953*cda5da8dSAndroid Build Coastguard Worker the complexity of the Node methods that deal with children. 954*cda5da8dSAndroid Build Coastguard Worker """ 955*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 956*cda5da8dSAndroid Build Coastguard Worker 957*cda5da8dSAndroid Build Coastguard Worker attributes = None 958*cda5da8dSAndroid Build Coastguard Worker childNodes = EmptyNodeList() 959*cda5da8dSAndroid Build Coastguard Worker firstChild = None 960*cda5da8dSAndroid Build Coastguard Worker lastChild = None 961*cda5da8dSAndroid Build Coastguard Worker 962*cda5da8dSAndroid Build Coastguard Worker def _get_firstChild(self): 963*cda5da8dSAndroid Build Coastguard Worker return None 964*cda5da8dSAndroid Build Coastguard Worker 965*cda5da8dSAndroid Build Coastguard Worker def _get_lastChild(self): 966*cda5da8dSAndroid Build Coastguard Worker return None 967*cda5da8dSAndroid Build Coastguard Worker 968*cda5da8dSAndroid Build Coastguard Worker def appendChild(self, node): 969*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 970*cda5da8dSAndroid Build Coastguard Worker self.nodeName + " nodes cannot have children") 971*cda5da8dSAndroid Build Coastguard Worker 972*cda5da8dSAndroid Build Coastguard Worker def hasChildNodes(self): 973*cda5da8dSAndroid Build Coastguard Worker return False 974*cda5da8dSAndroid Build Coastguard Worker 975*cda5da8dSAndroid Build Coastguard Worker def insertBefore(self, newChild, refChild): 976*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 977*cda5da8dSAndroid Build Coastguard Worker self.nodeName + " nodes do not have children") 978*cda5da8dSAndroid Build Coastguard Worker 979*cda5da8dSAndroid Build Coastguard Worker def removeChild(self, oldChild): 980*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr( 981*cda5da8dSAndroid Build Coastguard Worker self.nodeName + " nodes do not have children") 982*cda5da8dSAndroid Build Coastguard Worker 983*cda5da8dSAndroid Build Coastguard Worker def normalize(self): 984*cda5da8dSAndroid Build Coastguard Worker # For childless nodes, normalize() has nothing to do. 985*cda5da8dSAndroid Build Coastguard Worker pass 986*cda5da8dSAndroid Build Coastguard Worker 987*cda5da8dSAndroid Build Coastguard Worker def replaceChild(self, newChild, oldChild): 988*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 989*cda5da8dSAndroid Build Coastguard Worker self.nodeName + " nodes do not have children") 990*cda5da8dSAndroid Build Coastguard Worker 991*cda5da8dSAndroid Build Coastguard Worker 992*cda5da8dSAndroid Build Coastguard Workerclass ProcessingInstruction(Childless, Node): 993*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.PROCESSING_INSTRUCTION_NODE 994*cda5da8dSAndroid Build Coastguard Worker __slots__ = ('target', 'data') 995*cda5da8dSAndroid Build Coastguard Worker 996*cda5da8dSAndroid Build Coastguard Worker def __init__(self, target, data): 997*cda5da8dSAndroid Build Coastguard Worker self.target = target 998*cda5da8dSAndroid Build Coastguard Worker self.data = data 999*cda5da8dSAndroid Build Coastguard Worker 1000*cda5da8dSAndroid Build Coastguard Worker # nodeValue is an alias for data 1001*cda5da8dSAndroid Build Coastguard Worker def _get_nodeValue(self): 1002*cda5da8dSAndroid Build Coastguard Worker return self.data 1003*cda5da8dSAndroid Build Coastguard Worker def _set_nodeValue(self, value): 1004*cda5da8dSAndroid Build Coastguard Worker self.data = value 1005*cda5da8dSAndroid Build Coastguard Worker nodeValue = property(_get_nodeValue, _set_nodeValue) 1006*cda5da8dSAndroid Build Coastguard Worker 1007*cda5da8dSAndroid Build Coastguard Worker # nodeName is an alias for target 1008*cda5da8dSAndroid Build Coastguard Worker def _get_nodeName(self): 1009*cda5da8dSAndroid Build Coastguard Worker return self.target 1010*cda5da8dSAndroid Build Coastguard Worker def _set_nodeName(self, value): 1011*cda5da8dSAndroid Build Coastguard Worker self.target = value 1012*cda5da8dSAndroid Build Coastguard Worker nodeName = property(_get_nodeName, _set_nodeName) 1013*cda5da8dSAndroid Build Coastguard Worker 1014*cda5da8dSAndroid Build Coastguard Worker def writexml(self, writer, indent="", addindent="", newl=""): 1015*cda5da8dSAndroid Build Coastguard Worker writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl)) 1016*cda5da8dSAndroid Build Coastguard Worker 1017*cda5da8dSAndroid Build Coastguard Worker 1018*cda5da8dSAndroid Build Coastguard Workerclass CharacterData(Childless, Node): 1019*cda5da8dSAndroid Build Coastguard Worker __slots__=('_data', 'ownerDocument','parentNode', 'previousSibling', 'nextSibling') 1020*cda5da8dSAndroid Build Coastguard Worker 1021*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 1022*cda5da8dSAndroid Build Coastguard Worker self.ownerDocument = self.parentNode = None 1023*cda5da8dSAndroid Build Coastguard Worker self.previousSibling = self.nextSibling = None 1024*cda5da8dSAndroid Build Coastguard Worker self._data = '' 1025*cda5da8dSAndroid Build Coastguard Worker Node.__init__(self) 1026*cda5da8dSAndroid Build Coastguard Worker 1027*cda5da8dSAndroid Build Coastguard Worker def _get_length(self): 1028*cda5da8dSAndroid Build Coastguard Worker return len(self.data) 1029*cda5da8dSAndroid Build Coastguard Worker __len__ = _get_length 1030*cda5da8dSAndroid Build Coastguard Worker 1031*cda5da8dSAndroid Build Coastguard Worker def _get_data(self): 1032*cda5da8dSAndroid Build Coastguard Worker return self._data 1033*cda5da8dSAndroid Build Coastguard Worker def _set_data(self, data): 1034*cda5da8dSAndroid Build Coastguard Worker self._data = data 1035*cda5da8dSAndroid Build Coastguard Worker 1036*cda5da8dSAndroid Build Coastguard Worker data = nodeValue = property(_get_data, _set_data) 1037*cda5da8dSAndroid Build Coastguard Worker 1038*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 1039*cda5da8dSAndroid Build Coastguard Worker data = self.data 1040*cda5da8dSAndroid Build Coastguard Worker if len(data) > 10: 1041*cda5da8dSAndroid Build Coastguard Worker dotdotdot = "..." 1042*cda5da8dSAndroid Build Coastguard Worker else: 1043*cda5da8dSAndroid Build Coastguard Worker dotdotdot = "" 1044*cda5da8dSAndroid Build Coastguard Worker return '<DOM %s node "%r%s">' % ( 1045*cda5da8dSAndroid Build Coastguard Worker self.__class__.__name__, data[0:10], dotdotdot) 1046*cda5da8dSAndroid Build Coastguard Worker 1047*cda5da8dSAndroid Build Coastguard Worker def substringData(self, offset, count): 1048*cda5da8dSAndroid Build Coastguard Worker if offset < 0: 1049*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("offset cannot be negative") 1050*cda5da8dSAndroid Build Coastguard Worker if offset >= len(self.data): 1051*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("offset cannot be beyond end of data") 1052*cda5da8dSAndroid Build Coastguard Worker if count < 0: 1053*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("count cannot be negative") 1054*cda5da8dSAndroid Build Coastguard Worker return self.data[offset:offset+count] 1055*cda5da8dSAndroid Build Coastguard Worker 1056*cda5da8dSAndroid Build Coastguard Worker def appendData(self, arg): 1057*cda5da8dSAndroid Build Coastguard Worker self.data = self.data + arg 1058*cda5da8dSAndroid Build Coastguard Worker 1059*cda5da8dSAndroid Build Coastguard Worker def insertData(self, offset, arg): 1060*cda5da8dSAndroid Build Coastguard Worker if offset < 0: 1061*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("offset cannot be negative") 1062*cda5da8dSAndroid Build Coastguard Worker if offset >= len(self.data): 1063*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("offset cannot be beyond end of data") 1064*cda5da8dSAndroid Build Coastguard Worker if arg: 1065*cda5da8dSAndroid Build Coastguard Worker self.data = "%s%s%s" % ( 1066*cda5da8dSAndroid Build Coastguard Worker self.data[:offset], arg, self.data[offset:]) 1067*cda5da8dSAndroid Build Coastguard Worker 1068*cda5da8dSAndroid Build Coastguard Worker def deleteData(self, offset, count): 1069*cda5da8dSAndroid Build Coastguard Worker if offset < 0: 1070*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("offset cannot be negative") 1071*cda5da8dSAndroid Build Coastguard Worker if offset >= len(self.data): 1072*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("offset cannot be beyond end of data") 1073*cda5da8dSAndroid Build Coastguard Worker if count < 0: 1074*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("count cannot be negative") 1075*cda5da8dSAndroid Build Coastguard Worker if count: 1076*cda5da8dSAndroid Build Coastguard Worker self.data = self.data[:offset] + self.data[offset+count:] 1077*cda5da8dSAndroid Build Coastguard Worker 1078*cda5da8dSAndroid Build Coastguard Worker def replaceData(self, offset, count, arg): 1079*cda5da8dSAndroid Build Coastguard Worker if offset < 0: 1080*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("offset cannot be negative") 1081*cda5da8dSAndroid Build Coastguard Worker if offset >= len(self.data): 1082*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("offset cannot be beyond end of data") 1083*cda5da8dSAndroid Build Coastguard Worker if count < 0: 1084*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("count cannot be negative") 1085*cda5da8dSAndroid Build Coastguard Worker if count: 1086*cda5da8dSAndroid Build Coastguard Worker self.data = "%s%s%s" % ( 1087*cda5da8dSAndroid Build Coastguard Worker self.data[:offset], arg, self.data[offset+count:]) 1088*cda5da8dSAndroid Build Coastguard Worker 1089*cda5da8dSAndroid Build Coastguard Workerdefproperty(CharacterData, "length", doc="Length of the string data.") 1090*cda5da8dSAndroid Build Coastguard Worker 1091*cda5da8dSAndroid Build Coastguard Worker 1092*cda5da8dSAndroid Build Coastguard Workerclass Text(CharacterData): 1093*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 1094*cda5da8dSAndroid Build Coastguard Worker 1095*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.TEXT_NODE 1096*cda5da8dSAndroid Build Coastguard Worker nodeName = "#text" 1097*cda5da8dSAndroid Build Coastguard Worker attributes = None 1098*cda5da8dSAndroid Build Coastguard Worker 1099*cda5da8dSAndroid Build Coastguard Worker def splitText(self, offset): 1100*cda5da8dSAndroid Build Coastguard Worker if offset < 0 or offset > len(self.data): 1101*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.IndexSizeErr("illegal offset value") 1102*cda5da8dSAndroid Build Coastguard Worker newText = self.__class__() 1103*cda5da8dSAndroid Build Coastguard Worker newText.data = self.data[offset:] 1104*cda5da8dSAndroid Build Coastguard Worker newText.ownerDocument = self.ownerDocument 1105*cda5da8dSAndroid Build Coastguard Worker next = self.nextSibling 1106*cda5da8dSAndroid Build Coastguard Worker if self.parentNode and self in self.parentNode.childNodes: 1107*cda5da8dSAndroid Build Coastguard Worker if next is None: 1108*cda5da8dSAndroid Build Coastguard Worker self.parentNode.appendChild(newText) 1109*cda5da8dSAndroid Build Coastguard Worker else: 1110*cda5da8dSAndroid Build Coastguard Worker self.parentNode.insertBefore(newText, next) 1111*cda5da8dSAndroid Build Coastguard Worker self.data = self.data[:offset] 1112*cda5da8dSAndroid Build Coastguard Worker return newText 1113*cda5da8dSAndroid Build Coastguard Worker 1114*cda5da8dSAndroid Build Coastguard Worker def writexml(self, writer, indent="", addindent="", newl=""): 1115*cda5da8dSAndroid Build Coastguard Worker _write_data(writer, "%s%s%s" % (indent, self.data, newl)) 1116*cda5da8dSAndroid Build Coastguard Worker 1117*cda5da8dSAndroid Build Coastguard Worker # DOM Level 3 (WD 9 April 2002) 1118*cda5da8dSAndroid Build Coastguard Worker 1119*cda5da8dSAndroid Build Coastguard Worker def _get_wholeText(self): 1120*cda5da8dSAndroid Build Coastguard Worker L = [self.data] 1121*cda5da8dSAndroid Build Coastguard Worker n = self.previousSibling 1122*cda5da8dSAndroid Build Coastguard Worker while n is not None: 1123*cda5da8dSAndroid Build Coastguard Worker if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): 1124*cda5da8dSAndroid Build Coastguard Worker L.insert(0, n.data) 1125*cda5da8dSAndroid Build Coastguard Worker n = n.previousSibling 1126*cda5da8dSAndroid Build Coastguard Worker else: 1127*cda5da8dSAndroid Build Coastguard Worker break 1128*cda5da8dSAndroid Build Coastguard Worker n = self.nextSibling 1129*cda5da8dSAndroid Build Coastguard Worker while n is not None: 1130*cda5da8dSAndroid Build Coastguard Worker if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): 1131*cda5da8dSAndroid Build Coastguard Worker L.append(n.data) 1132*cda5da8dSAndroid Build Coastguard Worker n = n.nextSibling 1133*cda5da8dSAndroid Build Coastguard Worker else: 1134*cda5da8dSAndroid Build Coastguard Worker break 1135*cda5da8dSAndroid Build Coastguard Worker return ''.join(L) 1136*cda5da8dSAndroid Build Coastguard Worker 1137*cda5da8dSAndroid Build Coastguard Worker def replaceWholeText(self, content): 1138*cda5da8dSAndroid Build Coastguard Worker # XXX This needs to be seriously changed if minidom ever 1139*cda5da8dSAndroid Build Coastguard Worker # supports EntityReference nodes. 1140*cda5da8dSAndroid Build Coastguard Worker parent = self.parentNode 1141*cda5da8dSAndroid Build Coastguard Worker n = self.previousSibling 1142*cda5da8dSAndroid Build Coastguard Worker while n is not None: 1143*cda5da8dSAndroid Build Coastguard Worker if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): 1144*cda5da8dSAndroid Build Coastguard Worker next = n.previousSibling 1145*cda5da8dSAndroid Build Coastguard Worker parent.removeChild(n) 1146*cda5da8dSAndroid Build Coastguard Worker n = next 1147*cda5da8dSAndroid Build Coastguard Worker else: 1148*cda5da8dSAndroid Build Coastguard Worker break 1149*cda5da8dSAndroid Build Coastguard Worker n = self.nextSibling 1150*cda5da8dSAndroid Build Coastguard Worker if not content: 1151*cda5da8dSAndroid Build Coastguard Worker parent.removeChild(self) 1152*cda5da8dSAndroid Build Coastguard Worker while n is not None: 1153*cda5da8dSAndroid Build Coastguard Worker if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): 1154*cda5da8dSAndroid Build Coastguard Worker next = n.nextSibling 1155*cda5da8dSAndroid Build Coastguard Worker parent.removeChild(n) 1156*cda5da8dSAndroid Build Coastguard Worker n = next 1157*cda5da8dSAndroid Build Coastguard Worker else: 1158*cda5da8dSAndroid Build Coastguard Worker break 1159*cda5da8dSAndroid Build Coastguard Worker if content: 1160*cda5da8dSAndroid Build Coastguard Worker self.data = content 1161*cda5da8dSAndroid Build Coastguard Worker return self 1162*cda5da8dSAndroid Build Coastguard Worker else: 1163*cda5da8dSAndroid Build Coastguard Worker return None 1164*cda5da8dSAndroid Build Coastguard Worker 1165*cda5da8dSAndroid Build Coastguard Worker def _get_isWhitespaceInElementContent(self): 1166*cda5da8dSAndroid Build Coastguard Worker if self.data.strip(): 1167*cda5da8dSAndroid Build Coastguard Worker return False 1168*cda5da8dSAndroid Build Coastguard Worker elem = _get_containing_element(self) 1169*cda5da8dSAndroid Build Coastguard Worker if elem is None: 1170*cda5da8dSAndroid Build Coastguard Worker return False 1171*cda5da8dSAndroid Build Coastguard Worker info = self.ownerDocument._get_elem_info(elem) 1172*cda5da8dSAndroid Build Coastguard Worker if info is None: 1173*cda5da8dSAndroid Build Coastguard Worker return False 1174*cda5da8dSAndroid Build Coastguard Worker else: 1175*cda5da8dSAndroid Build Coastguard Worker return info.isElementContent() 1176*cda5da8dSAndroid Build Coastguard Worker 1177*cda5da8dSAndroid Build Coastguard Workerdefproperty(Text, "isWhitespaceInElementContent", 1178*cda5da8dSAndroid Build Coastguard Worker doc="True iff this text node contains only whitespace" 1179*cda5da8dSAndroid Build Coastguard Worker " and is in element content.") 1180*cda5da8dSAndroid Build Coastguard Workerdefproperty(Text, "wholeText", 1181*cda5da8dSAndroid Build Coastguard Worker doc="The text of all logically-adjacent text nodes.") 1182*cda5da8dSAndroid Build Coastguard Worker 1183*cda5da8dSAndroid Build Coastguard Worker 1184*cda5da8dSAndroid Build Coastguard Workerdef _get_containing_element(node): 1185*cda5da8dSAndroid Build Coastguard Worker c = node.parentNode 1186*cda5da8dSAndroid Build Coastguard Worker while c is not None: 1187*cda5da8dSAndroid Build Coastguard Worker if c.nodeType == Node.ELEMENT_NODE: 1188*cda5da8dSAndroid Build Coastguard Worker return c 1189*cda5da8dSAndroid Build Coastguard Worker c = c.parentNode 1190*cda5da8dSAndroid Build Coastguard Worker return None 1191*cda5da8dSAndroid Build Coastguard Worker 1192*cda5da8dSAndroid Build Coastguard Workerdef _get_containing_entref(node): 1193*cda5da8dSAndroid Build Coastguard Worker c = node.parentNode 1194*cda5da8dSAndroid Build Coastguard Worker while c is not None: 1195*cda5da8dSAndroid Build Coastguard Worker if c.nodeType == Node.ENTITY_REFERENCE_NODE: 1196*cda5da8dSAndroid Build Coastguard Worker return c 1197*cda5da8dSAndroid Build Coastguard Worker c = c.parentNode 1198*cda5da8dSAndroid Build Coastguard Worker return None 1199*cda5da8dSAndroid Build Coastguard Worker 1200*cda5da8dSAndroid Build Coastguard Worker 1201*cda5da8dSAndroid Build Coastguard Workerclass Comment(CharacterData): 1202*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.COMMENT_NODE 1203*cda5da8dSAndroid Build Coastguard Worker nodeName = "#comment" 1204*cda5da8dSAndroid Build Coastguard Worker 1205*cda5da8dSAndroid Build Coastguard Worker def __init__(self, data): 1206*cda5da8dSAndroid Build Coastguard Worker CharacterData.__init__(self) 1207*cda5da8dSAndroid Build Coastguard Worker self._data = data 1208*cda5da8dSAndroid Build Coastguard Worker 1209*cda5da8dSAndroid Build Coastguard Worker def writexml(self, writer, indent="", addindent="", newl=""): 1210*cda5da8dSAndroid Build Coastguard Worker if "--" in self.data: 1211*cda5da8dSAndroid Build Coastguard Worker raise ValueError("'--' is not allowed in a comment node") 1212*cda5da8dSAndroid Build Coastguard Worker writer.write("%s<!--%s-->%s" % (indent, self.data, newl)) 1213*cda5da8dSAndroid Build Coastguard Worker 1214*cda5da8dSAndroid Build Coastguard Worker 1215*cda5da8dSAndroid Build Coastguard Workerclass CDATASection(Text): 1216*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 1217*cda5da8dSAndroid Build Coastguard Worker 1218*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.CDATA_SECTION_NODE 1219*cda5da8dSAndroid Build Coastguard Worker nodeName = "#cdata-section" 1220*cda5da8dSAndroid Build Coastguard Worker 1221*cda5da8dSAndroid Build Coastguard Worker def writexml(self, writer, indent="", addindent="", newl=""): 1222*cda5da8dSAndroid Build Coastguard Worker if self.data.find("]]>") >= 0: 1223*cda5da8dSAndroid Build Coastguard Worker raise ValueError("']]>' not allowed in a CDATA section") 1224*cda5da8dSAndroid Build Coastguard Worker writer.write("<![CDATA[%s]]>" % self.data) 1225*cda5da8dSAndroid Build Coastguard Worker 1226*cda5da8dSAndroid Build Coastguard Worker 1227*cda5da8dSAndroid Build Coastguard Workerclass ReadOnlySequentialNamedNodeMap(object): 1228*cda5da8dSAndroid Build Coastguard Worker __slots__ = '_seq', 1229*cda5da8dSAndroid Build Coastguard Worker 1230*cda5da8dSAndroid Build Coastguard Worker def __init__(self, seq=()): 1231*cda5da8dSAndroid Build Coastguard Worker # seq should be a list or tuple 1232*cda5da8dSAndroid Build Coastguard Worker self._seq = seq 1233*cda5da8dSAndroid Build Coastguard Worker 1234*cda5da8dSAndroid Build Coastguard Worker def __len__(self): 1235*cda5da8dSAndroid Build Coastguard Worker return len(self._seq) 1236*cda5da8dSAndroid Build Coastguard Worker 1237*cda5da8dSAndroid Build Coastguard Worker def _get_length(self): 1238*cda5da8dSAndroid Build Coastguard Worker return len(self._seq) 1239*cda5da8dSAndroid Build Coastguard Worker 1240*cda5da8dSAndroid Build Coastguard Worker def getNamedItem(self, name): 1241*cda5da8dSAndroid Build Coastguard Worker for n in self._seq: 1242*cda5da8dSAndroid Build Coastguard Worker if n.nodeName == name: 1243*cda5da8dSAndroid Build Coastguard Worker return n 1244*cda5da8dSAndroid Build Coastguard Worker 1245*cda5da8dSAndroid Build Coastguard Worker def getNamedItemNS(self, namespaceURI, localName): 1246*cda5da8dSAndroid Build Coastguard Worker for n in self._seq: 1247*cda5da8dSAndroid Build Coastguard Worker if n.namespaceURI == namespaceURI and n.localName == localName: 1248*cda5da8dSAndroid Build Coastguard Worker return n 1249*cda5da8dSAndroid Build Coastguard Worker 1250*cda5da8dSAndroid Build Coastguard Worker def __getitem__(self, name_or_tuple): 1251*cda5da8dSAndroid Build Coastguard Worker if isinstance(name_or_tuple, tuple): 1252*cda5da8dSAndroid Build Coastguard Worker node = self.getNamedItemNS(*name_or_tuple) 1253*cda5da8dSAndroid Build Coastguard Worker else: 1254*cda5da8dSAndroid Build Coastguard Worker node = self.getNamedItem(name_or_tuple) 1255*cda5da8dSAndroid Build Coastguard Worker if node is None: 1256*cda5da8dSAndroid Build Coastguard Worker raise KeyError(name_or_tuple) 1257*cda5da8dSAndroid Build Coastguard Worker return node 1258*cda5da8dSAndroid Build Coastguard Worker 1259*cda5da8dSAndroid Build Coastguard Worker def item(self, index): 1260*cda5da8dSAndroid Build Coastguard Worker if index < 0: 1261*cda5da8dSAndroid Build Coastguard Worker return None 1262*cda5da8dSAndroid Build Coastguard Worker try: 1263*cda5da8dSAndroid Build Coastguard Worker return self._seq[index] 1264*cda5da8dSAndroid Build Coastguard Worker except IndexError: 1265*cda5da8dSAndroid Build Coastguard Worker return None 1266*cda5da8dSAndroid Build Coastguard Worker 1267*cda5da8dSAndroid Build Coastguard Worker def removeNamedItem(self, name): 1268*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NoModificationAllowedErr( 1269*cda5da8dSAndroid Build Coastguard Worker "NamedNodeMap instance is read-only") 1270*cda5da8dSAndroid Build Coastguard Worker 1271*cda5da8dSAndroid Build Coastguard Worker def removeNamedItemNS(self, namespaceURI, localName): 1272*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NoModificationAllowedErr( 1273*cda5da8dSAndroid Build Coastguard Worker "NamedNodeMap instance is read-only") 1274*cda5da8dSAndroid Build Coastguard Worker 1275*cda5da8dSAndroid Build Coastguard Worker def setNamedItem(self, node): 1276*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NoModificationAllowedErr( 1277*cda5da8dSAndroid Build Coastguard Worker "NamedNodeMap instance is read-only") 1278*cda5da8dSAndroid Build Coastguard Worker 1279*cda5da8dSAndroid Build Coastguard Worker def setNamedItemNS(self, node): 1280*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NoModificationAllowedErr( 1281*cda5da8dSAndroid Build Coastguard Worker "NamedNodeMap instance is read-only") 1282*cda5da8dSAndroid Build Coastguard Worker 1283*cda5da8dSAndroid Build Coastguard Worker def __getstate__(self): 1284*cda5da8dSAndroid Build Coastguard Worker return [self._seq] 1285*cda5da8dSAndroid Build Coastguard Worker 1286*cda5da8dSAndroid Build Coastguard Worker def __setstate__(self, state): 1287*cda5da8dSAndroid Build Coastguard Worker self._seq = state[0] 1288*cda5da8dSAndroid Build Coastguard Worker 1289*cda5da8dSAndroid Build Coastguard Workerdefproperty(ReadOnlySequentialNamedNodeMap, "length", 1290*cda5da8dSAndroid Build Coastguard Worker doc="Number of entries in the NamedNodeMap.") 1291*cda5da8dSAndroid Build Coastguard Worker 1292*cda5da8dSAndroid Build Coastguard Worker 1293*cda5da8dSAndroid Build Coastguard Workerclass Identified: 1294*cda5da8dSAndroid Build Coastguard Worker """Mix-in class that supports the publicId and systemId attributes.""" 1295*cda5da8dSAndroid Build Coastguard Worker 1296*cda5da8dSAndroid Build Coastguard Worker __slots__ = 'publicId', 'systemId' 1297*cda5da8dSAndroid Build Coastguard Worker 1298*cda5da8dSAndroid Build Coastguard Worker def _identified_mixin_init(self, publicId, systemId): 1299*cda5da8dSAndroid Build Coastguard Worker self.publicId = publicId 1300*cda5da8dSAndroid Build Coastguard Worker self.systemId = systemId 1301*cda5da8dSAndroid Build Coastguard Worker 1302*cda5da8dSAndroid Build Coastguard Worker def _get_publicId(self): 1303*cda5da8dSAndroid Build Coastguard Worker return self.publicId 1304*cda5da8dSAndroid Build Coastguard Worker 1305*cda5da8dSAndroid Build Coastguard Worker def _get_systemId(self): 1306*cda5da8dSAndroid Build Coastguard Worker return self.systemId 1307*cda5da8dSAndroid Build Coastguard Worker 1308*cda5da8dSAndroid Build Coastguard Workerclass DocumentType(Identified, Childless, Node): 1309*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.DOCUMENT_TYPE_NODE 1310*cda5da8dSAndroid Build Coastguard Worker nodeValue = None 1311*cda5da8dSAndroid Build Coastguard Worker name = None 1312*cda5da8dSAndroid Build Coastguard Worker publicId = None 1313*cda5da8dSAndroid Build Coastguard Worker systemId = None 1314*cda5da8dSAndroid Build Coastguard Worker internalSubset = None 1315*cda5da8dSAndroid Build Coastguard Worker 1316*cda5da8dSAndroid Build Coastguard Worker def __init__(self, qualifiedName): 1317*cda5da8dSAndroid Build Coastguard Worker self.entities = ReadOnlySequentialNamedNodeMap() 1318*cda5da8dSAndroid Build Coastguard Worker self.notations = ReadOnlySequentialNamedNodeMap() 1319*cda5da8dSAndroid Build Coastguard Worker if qualifiedName: 1320*cda5da8dSAndroid Build Coastguard Worker prefix, localname = _nssplit(qualifiedName) 1321*cda5da8dSAndroid Build Coastguard Worker self.name = localname 1322*cda5da8dSAndroid Build Coastguard Worker self.nodeName = self.name 1323*cda5da8dSAndroid Build Coastguard Worker 1324*cda5da8dSAndroid Build Coastguard Worker def _get_internalSubset(self): 1325*cda5da8dSAndroid Build Coastguard Worker return self.internalSubset 1326*cda5da8dSAndroid Build Coastguard Worker 1327*cda5da8dSAndroid Build Coastguard Worker def cloneNode(self, deep): 1328*cda5da8dSAndroid Build Coastguard Worker if self.ownerDocument is None: 1329*cda5da8dSAndroid Build Coastguard Worker # it's ok 1330*cda5da8dSAndroid Build Coastguard Worker clone = DocumentType(None) 1331*cda5da8dSAndroid Build Coastguard Worker clone.name = self.name 1332*cda5da8dSAndroid Build Coastguard Worker clone.nodeName = self.name 1333*cda5da8dSAndroid Build Coastguard Worker operation = xml.dom.UserDataHandler.NODE_CLONED 1334*cda5da8dSAndroid Build Coastguard Worker if deep: 1335*cda5da8dSAndroid Build Coastguard Worker clone.entities._seq = [] 1336*cda5da8dSAndroid Build Coastguard Worker clone.notations._seq = [] 1337*cda5da8dSAndroid Build Coastguard Worker for n in self.notations._seq: 1338*cda5da8dSAndroid Build Coastguard Worker notation = Notation(n.nodeName, n.publicId, n.systemId) 1339*cda5da8dSAndroid Build Coastguard Worker clone.notations._seq.append(notation) 1340*cda5da8dSAndroid Build Coastguard Worker n._call_user_data_handler(operation, n, notation) 1341*cda5da8dSAndroid Build Coastguard Worker for e in self.entities._seq: 1342*cda5da8dSAndroid Build Coastguard Worker entity = Entity(e.nodeName, e.publicId, e.systemId, 1343*cda5da8dSAndroid Build Coastguard Worker e.notationName) 1344*cda5da8dSAndroid Build Coastguard Worker entity.actualEncoding = e.actualEncoding 1345*cda5da8dSAndroid Build Coastguard Worker entity.encoding = e.encoding 1346*cda5da8dSAndroid Build Coastguard Worker entity.version = e.version 1347*cda5da8dSAndroid Build Coastguard Worker clone.entities._seq.append(entity) 1348*cda5da8dSAndroid Build Coastguard Worker e._call_user_data_handler(operation, e, entity) 1349*cda5da8dSAndroid Build Coastguard Worker self._call_user_data_handler(operation, self, clone) 1350*cda5da8dSAndroid Build Coastguard Worker return clone 1351*cda5da8dSAndroid Build Coastguard Worker else: 1352*cda5da8dSAndroid Build Coastguard Worker return None 1353*cda5da8dSAndroid Build Coastguard Worker 1354*cda5da8dSAndroid Build Coastguard Worker def writexml(self, writer, indent="", addindent="", newl=""): 1355*cda5da8dSAndroid Build Coastguard Worker writer.write("<!DOCTYPE ") 1356*cda5da8dSAndroid Build Coastguard Worker writer.write(self.name) 1357*cda5da8dSAndroid Build Coastguard Worker if self.publicId: 1358*cda5da8dSAndroid Build Coastguard Worker writer.write("%s PUBLIC '%s'%s '%s'" 1359*cda5da8dSAndroid Build Coastguard Worker % (newl, self.publicId, newl, self.systemId)) 1360*cda5da8dSAndroid Build Coastguard Worker elif self.systemId: 1361*cda5da8dSAndroid Build Coastguard Worker writer.write("%s SYSTEM '%s'" % (newl, self.systemId)) 1362*cda5da8dSAndroid Build Coastguard Worker if self.internalSubset is not None: 1363*cda5da8dSAndroid Build Coastguard Worker writer.write(" [") 1364*cda5da8dSAndroid Build Coastguard Worker writer.write(self.internalSubset) 1365*cda5da8dSAndroid Build Coastguard Worker writer.write("]") 1366*cda5da8dSAndroid Build Coastguard Worker writer.write(">"+newl) 1367*cda5da8dSAndroid Build Coastguard Worker 1368*cda5da8dSAndroid Build Coastguard Workerclass Entity(Identified, Node): 1369*cda5da8dSAndroid Build Coastguard Worker attributes = None 1370*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.ENTITY_NODE 1371*cda5da8dSAndroid Build Coastguard Worker nodeValue = None 1372*cda5da8dSAndroid Build Coastguard Worker 1373*cda5da8dSAndroid Build Coastguard Worker actualEncoding = None 1374*cda5da8dSAndroid Build Coastguard Worker encoding = None 1375*cda5da8dSAndroid Build Coastguard Worker version = None 1376*cda5da8dSAndroid Build Coastguard Worker 1377*cda5da8dSAndroid Build Coastguard Worker def __init__(self, name, publicId, systemId, notation): 1378*cda5da8dSAndroid Build Coastguard Worker self.nodeName = name 1379*cda5da8dSAndroid Build Coastguard Worker self.notationName = notation 1380*cda5da8dSAndroid Build Coastguard Worker self.childNodes = NodeList() 1381*cda5da8dSAndroid Build Coastguard Worker self._identified_mixin_init(publicId, systemId) 1382*cda5da8dSAndroid Build Coastguard Worker 1383*cda5da8dSAndroid Build Coastguard Worker def _get_actualEncoding(self): 1384*cda5da8dSAndroid Build Coastguard Worker return self.actualEncoding 1385*cda5da8dSAndroid Build Coastguard Worker 1386*cda5da8dSAndroid Build Coastguard Worker def _get_encoding(self): 1387*cda5da8dSAndroid Build Coastguard Worker return self.encoding 1388*cda5da8dSAndroid Build Coastguard Worker 1389*cda5da8dSAndroid Build Coastguard Worker def _get_version(self): 1390*cda5da8dSAndroid Build Coastguard Worker return self.version 1391*cda5da8dSAndroid Build Coastguard Worker 1392*cda5da8dSAndroid Build Coastguard Worker def appendChild(self, newChild): 1393*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 1394*cda5da8dSAndroid Build Coastguard Worker "cannot append children to an entity node") 1395*cda5da8dSAndroid Build Coastguard Worker 1396*cda5da8dSAndroid Build Coastguard Worker def insertBefore(self, newChild, refChild): 1397*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 1398*cda5da8dSAndroid Build Coastguard Worker "cannot insert children below an entity node") 1399*cda5da8dSAndroid Build Coastguard Worker 1400*cda5da8dSAndroid Build Coastguard Worker def removeChild(self, oldChild): 1401*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 1402*cda5da8dSAndroid Build Coastguard Worker "cannot remove children from an entity node") 1403*cda5da8dSAndroid Build Coastguard Worker 1404*cda5da8dSAndroid Build Coastguard Worker def replaceChild(self, newChild, oldChild): 1405*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 1406*cda5da8dSAndroid Build Coastguard Worker "cannot replace children of an entity node") 1407*cda5da8dSAndroid Build Coastguard Worker 1408*cda5da8dSAndroid Build Coastguard Workerclass Notation(Identified, Childless, Node): 1409*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.NOTATION_NODE 1410*cda5da8dSAndroid Build Coastguard Worker nodeValue = None 1411*cda5da8dSAndroid Build Coastguard Worker 1412*cda5da8dSAndroid Build Coastguard Worker def __init__(self, name, publicId, systemId): 1413*cda5da8dSAndroid Build Coastguard Worker self.nodeName = name 1414*cda5da8dSAndroid Build Coastguard Worker self._identified_mixin_init(publicId, systemId) 1415*cda5da8dSAndroid Build Coastguard Worker 1416*cda5da8dSAndroid Build Coastguard Worker 1417*cda5da8dSAndroid Build Coastguard Workerclass DOMImplementation(DOMImplementationLS): 1418*cda5da8dSAndroid Build Coastguard Worker _features = [("core", "1.0"), 1419*cda5da8dSAndroid Build Coastguard Worker ("core", "2.0"), 1420*cda5da8dSAndroid Build Coastguard Worker ("core", None), 1421*cda5da8dSAndroid Build Coastguard Worker ("xml", "1.0"), 1422*cda5da8dSAndroid Build Coastguard Worker ("xml", "2.0"), 1423*cda5da8dSAndroid Build Coastguard Worker ("xml", None), 1424*cda5da8dSAndroid Build Coastguard Worker ("ls-load", "3.0"), 1425*cda5da8dSAndroid Build Coastguard Worker ("ls-load", None), 1426*cda5da8dSAndroid Build Coastguard Worker ] 1427*cda5da8dSAndroid Build Coastguard Worker 1428*cda5da8dSAndroid Build Coastguard Worker def hasFeature(self, feature, version): 1429*cda5da8dSAndroid Build Coastguard Worker if version == "": 1430*cda5da8dSAndroid Build Coastguard Worker version = None 1431*cda5da8dSAndroid Build Coastguard Worker return (feature.lower(), version) in self._features 1432*cda5da8dSAndroid Build Coastguard Worker 1433*cda5da8dSAndroid Build Coastguard Worker def createDocument(self, namespaceURI, qualifiedName, doctype): 1434*cda5da8dSAndroid Build Coastguard Worker if doctype and doctype.parentNode is not None: 1435*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.WrongDocumentErr( 1436*cda5da8dSAndroid Build Coastguard Worker "doctype object owned by another DOM tree") 1437*cda5da8dSAndroid Build Coastguard Worker doc = self._create_document() 1438*cda5da8dSAndroid Build Coastguard Worker 1439*cda5da8dSAndroid Build Coastguard Worker add_root_element = not (namespaceURI is None 1440*cda5da8dSAndroid Build Coastguard Worker and qualifiedName is None 1441*cda5da8dSAndroid Build Coastguard Worker and doctype is None) 1442*cda5da8dSAndroid Build Coastguard Worker 1443*cda5da8dSAndroid Build Coastguard Worker if not qualifiedName and add_root_element: 1444*cda5da8dSAndroid Build Coastguard Worker # The spec is unclear what to raise here; SyntaxErr 1445*cda5da8dSAndroid Build Coastguard Worker # would be the other obvious candidate. Since Xerces raises 1446*cda5da8dSAndroid Build Coastguard Worker # InvalidCharacterErr, and since SyntaxErr is not listed 1447*cda5da8dSAndroid Build Coastguard Worker # for createDocument, that seems to be the better choice. 1448*cda5da8dSAndroid Build Coastguard Worker # XXX: need to check for illegal characters here and in 1449*cda5da8dSAndroid Build Coastguard Worker # createElement. 1450*cda5da8dSAndroid Build Coastguard Worker 1451*cda5da8dSAndroid Build Coastguard Worker # DOM Level III clears this up when talking about the return value 1452*cda5da8dSAndroid Build Coastguard Worker # of this function. If namespaceURI, qName and DocType are 1453*cda5da8dSAndroid Build Coastguard Worker # Null the document is returned without a document element 1454*cda5da8dSAndroid Build Coastguard Worker # Otherwise if doctype or namespaceURI are not None 1455*cda5da8dSAndroid Build Coastguard Worker # Then we go back to the above problem 1456*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.InvalidCharacterErr("Element with no name") 1457*cda5da8dSAndroid Build Coastguard Worker 1458*cda5da8dSAndroid Build Coastguard Worker if add_root_element: 1459*cda5da8dSAndroid Build Coastguard Worker prefix, localname = _nssplit(qualifiedName) 1460*cda5da8dSAndroid Build Coastguard Worker if prefix == "xml" \ 1461*cda5da8dSAndroid Build Coastguard Worker and namespaceURI != "http://www.w3.org/XML/1998/namespace": 1462*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NamespaceErr("illegal use of 'xml' prefix") 1463*cda5da8dSAndroid Build Coastguard Worker if prefix and not namespaceURI: 1464*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NamespaceErr( 1465*cda5da8dSAndroid Build Coastguard Worker "illegal use of prefix without namespaces") 1466*cda5da8dSAndroid Build Coastguard Worker element = doc.createElementNS(namespaceURI, qualifiedName) 1467*cda5da8dSAndroid Build Coastguard Worker if doctype: 1468*cda5da8dSAndroid Build Coastguard Worker doc.appendChild(doctype) 1469*cda5da8dSAndroid Build Coastguard Worker doc.appendChild(element) 1470*cda5da8dSAndroid Build Coastguard Worker 1471*cda5da8dSAndroid Build Coastguard Worker if doctype: 1472*cda5da8dSAndroid Build Coastguard Worker doctype.parentNode = doctype.ownerDocument = doc 1473*cda5da8dSAndroid Build Coastguard Worker 1474*cda5da8dSAndroid Build Coastguard Worker doc.doctype = doctype 1475*cda5da8dSAndroid Build Coastguard Worker doc.implementation = self 1476*cda5da8dSAndroid Build Coastguard Worker return doc 1477*cda5da8dSAndroid Build Coastguard Worker 1478*cda5da8dSAndroid Build Coastguard Worker def createDocumentType(self, qualifiedName, publicId, systemId): 1479*cda5da8dSAndroid Build Coastguard Worker doctype = DocumentType(qualifiedName) 1480*cda5da8dSAndroid Build Coastguard Worker doctype.publicId = publicId 1481*cda5da8dSAndroid Build Coastguard Worker doctype.systemId = systemId 1482*cda5da8dSAndroid Build Coastguard Worker return doctype 1483*cda5da8dSAndroid Build Coastguard Worker 1484*cda5da8dSAndroid Build Coastguard Worker # DOM Level 3 (WD 9 April 2002) 1485*cda5da8dSAndroid Build Coastguard Worker 1486*cda5da8dSAndroid Build Coastguard Worker def getInterface(self, feature): 1487*cda5da8dSAndroid Build Coastguard Worker if self.hasFeature(feature, None): 1488*cda5da8dSAndroid Build Coastguard Worker return self 1489*cda5da8dSAndroid Build Coastguard Worker else: 1490*cda5da8dSAndroid Build Coastguard Worker return None 1491*cda5da8dSAndroid Build Coastguard Worker 1492*cda5da8dSAndroid Build Coastguard Worker # internal 1493*cda5da8dSAndroid Build Coastguard Worker def _create_document(self): 1494*cda5da8dSAndroid Build Coastguard Worker return Document() 1495*cda5da8dSAndroid Build Coastguard Worker 1496*cda5da8dSAndroid Build Coastguard Workerclass ElementInfo(object): 1497*cda5da8dSAndroid Build Coastguard Worker """Object that represents content-model information for an element. 1498*cda5da8dSAndroid Build Coastguard Worker 1499*cda5da8dSAndroid Build Coastguard Worker This implementation is not expected to be used in practice; DOM 1500*cda5da8dSAndroid Build Coastguard Worker builders should provide implementations which do the right thing 1501*cda5da8dSAndroid Build Coastguard Worker using information available to it. 1502*cda5da8dSAndroid Build Coastguard Worker 1503*cda5da8dSAndroid Build Coastguard Worker """ 1504*cda5da8dSAndroid Build Coastguard Worker 1505*cda5da8dSAndroid Build Coastguard Worker __slots__ = 'tagName', 1506*cda5da8dSAndroid Build Coastguard Worker 1507*cda5da8dSAndroid Build Coastguard Worker def __init__(self, name): 1508*cda5da8dSAndroid Build Coastguard Worker self.tagName = name 1509*cda5da8dSAndroid Build Coastguard Worker 1510*cda5da8dSAndroid Build Coastguard Worker def getAttributeType(self, aname): 1511*cda5da8dSAndroid Build Coastguard Worker return _no_type 1512*cda5da8dSAndroid Build Coastguard Worker 1513*cda5da8dSAndroid Build Coastguard Worker def getAttributeTypeNS(self, namespaceURI, localName): 1514*cda5da8dSAndroid Build Coastguard Worker return _no_type 1515*cda5da8dSAndroid Build Coastguard Worker 1516*cda5da8dSAndroid Build Coastguard Worker def isElementContent(self): 1517*cda5da8dSAndroid Build Coastguard Worker return False 1518*cda5da8dSAndroid Build Coastguard Worker 1519*cda5da8dSAndroid Build Coastguard Worker def isEmpty(self): 1520*cda5da8dSAndroid Build Coastguard Worker """Returns true iff this element is declared to have an EMPTY 1521*cda5da8dSAndroid Build Coastguard Worker content model.""" 1522*cda5da8dSAndroid Build Coastguard Worker return False 1523*cda5da8dSAndroid Build Coastguard Worker 1524*cda5da8dSAndroid Build Coastguard Worker def isId(self, aname): 1525*cda5da8dSAndroid Build Coastguard Worker """Returns true iff the named attribute is a DTD-style ID.""" 1526*cda5da8dSAndroid Build Coastguard Worker return False 1527*cda5da8dSAndroid Build Coastguard Worker 1528*cda5da8dSAndroid Build Coastguard Worker def isIdNS(self, namespaceURI, localName): 1529*cda5da8dSAndroid Build Coastguard Worker """Returns true iff the identified attribute is a DTD-style ID.""" 1530*cda5da8dSAndroid Build Coastguard Worker return False 1531*cda5da8dSAndroid Build Coastguard Worker 1532*cda5da8dSAndroid Build Coastguard Worker def __getstate__(self): 1533*cda5da8dSAndroid Build Coastguard Worker return self.tagName 1534*cda5da8dSAndroid Build Coastguard Worker 1535*cda5da8dSAndroid Build Coastguard Worker def __setstate__(self, state): 1536*cda5da8dSAndroid Build Coastguard Worker self.tagName = state 1537*cda5da8dSAndroid Build Coastguard Worker 1538*cda5da8dSAndroid Build Coastguard Workerdef _clear_id_cache(node): 1539*cda5da8dSAndroid Build Coastguard Worker if node.nodeType == Node.DOCUMENT_NODE: 1540*cda5da8dSAndroid Build Coastguard Worker node._id_cache.clear() 1541*cda5da8dSAndroid Build Coastguard Worker node._id_search_stack = None 1542*cda5da8dSAndroid Build Coastguard Worker elif _in_document(node): 1543*cda5da8dSAndroid Build Coastguard Worker node.ownerDocument._id_cache.clear() 1544*cda5da8dSAndroid Build Coastguard Worker node.ownerDocument._id_search_stack= None 1545*cda5da8dSAndroid Build Coastguard Worker 1546*cda5da8dSAndroid Build Coastguard Workerclass Document(Node, DocumentLS): 1547*cda5da8dSAndroid Build Coastguard Worker __slots__ = ('_elem_info', 'doctype', 1548*cda5da8dSAndroid Build Coastguard Worker '_id_search_stack', 'childNodes', '_id_cache') 1549*cda5da8dSAndroid Build Coastguard Worker _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, 1550*cda5da8dSAndroid Build Coastguard Worker Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE) 1551*cda5da8dSAndroid Build Coastguard Worker 1552*cda5da8dSAndroid Build Coastguard Worker implementation = DOMImplementation() 1553*cda5da8dSAndroid Build Coastguard Worker nodeType = Node.DOCUMENT_NODE 1554*cda5da8dSAndroid Build Coastguard Worker nodeName = "#document" 1555*cda5da8dSAndroid Build Coastguard Worker nodeValue = None 1556*cda5da8dSAndroid Build Coastguard Worker attributes = None 1557*cda5da8dSAndroid Build Coastguard Worker parentNode = None 1558*cda5da8dSAndroid Build Coastguard Worker previousSibling = nextSibling = None 1559*cda5da8dSAndroid Build Coastguard Worker 1560*cda5da8dSAndroid Build Coastguard Worker 1561*cda5da8dSAndroid Build Coastguard Worker # Document attributes from Level 3 (WD 9 April 2002) 1562*cda5da8dSAndroid Build Coastguard Worker 1563*cda5da8dSAndroid Build Coastguard Worker actualEncoding = None 1564*cda5da8dSAndroid Build Coastguard Worker encoding = None 1565*cda5da8dSAndroid Build Coastguard Worker standalone = None 1566*cda5da8dSAndroid Build Coastguard Worker version = None 1567*cda5da8dSAndroid Build Coastguard Worker strictErrorChecking = False 1568*cda5da8dSAndroid Build Coastguard Worker errorHandler = None 1569*cda5da8dSAndroid Build Coastguard Worker documentURI = None 1570*cda5da8dSAndroid Build Coastguard Worker 1571*cda5da8dSAndroid Build Coastguard Worker _magic_id_count = 0 1572*cda5da8dSAndroid Build Coastguard Worker 1573*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 1574*cda5da8dSAndroid Build Coastguard Worker self.doctype = None 1575*cda5da8dSAndroid Build Coastguard Worker self.childNodes = NodeList() 1576*cda5da8dSAndroid Build Coastguard Worker # mapping of (namespaceURI, localName) -> ElementInfo 1577*cda5da8dSAndroid Build Coastguard Worker # and tagName -> ElementInfo 1578*cda5da8dSAndroid Build Coastguard Worker self._elem_info = {} 1579*cda5da8dSAndroid Build Coastguard Worker self._id_cache = {} 1580*cda5da8dSAndroid Build Coastguard Worker self._id_search_stack = None 1581*cda5da8dSAndroid Build Coastguard Worker 1582*cda5da8dSAndroid Build Coastguard Worker def _get_elem_info(self, element): 1583*cda5da8dSAndroid Build Coastguard Worker if element.namespaceURI: 1584*cda5da8dSAndroid Build Coastguard Worker key = element.namespaceURI, element.localName 1585*cda5da8dSAndroid Build Coastguard Worker else: 1586*cda5da8dSAndroid Build Coastguard Worker key = element.tagName 1587*cda5da8dSAndroid Build Coastguard Worker return self._elem_info.get(key) 1588*cda5da8dSAndroid Build Coastguard Worker 1589*cda5da8dSAndroid Build Coastguard Worker def _get_actualEncoding(self): 1590*cda5da8dSAndroid Build Coastguard Worker return self.actualEncoding 1591*cda5da8dSAndroid Build Coastguard Worker 1592*cda5da8dSAndroid Build Coastguard Worker def _get_doctype(self): 1593*cda5da8dSAndroid Build Coastguard Worker return self.doctype 1594*cda5da8dSAndroid Build Coastguard Worker 1595*cda5da8dSAndroid Build Coastguard Worker def _get_documentURI(self): 1596*cda5da8dSAndroid Build Coastguard Worker return self.documentURI 1597*cda5da8dSAndroid Build Coastguard Worker 1598*cda5da8dSAndroid Build Coastguard Worker def _get_encoding(self): 1599*cda5da8dSAndroid Build Coastguard Worker return self.encoding 1600*cda5da8dSAndroid Build Coastguard Worker 1601*cda5da8dSAndroid Build Coastguard Worker def _get_errorHandler(self): 1602*cda5da8dSAndroid Build Coastguard Worker return self.errorHandler 1603*cda5da8dSAndroid Build Coastguard Worker 1604*cda5da8dSAndroid Build Coastguard Worker def _get_standalone(self): 1605*cda5da8dSAndroid Build Coastguard Worker return self.standalone 1606*cda5da8dSAndroid Build Coastguard Worker 1607*cda5da8dSAndroid Build Coastguard Worker def _get_strictErrorChecking(self): 1608*cda5da8dSAndroid Build Coastguard Worker return self.strictErrorChecking 1609*cda5da8dSAndroid Build Coastguard Worker 1610*cda5da8dSAndroid Build Coastguard Worker def _get_version(self): 1611*cda5da8dSAndroid Build Coastguard Worker return self.version 1612*cda5da8dSAndroid Build Coastguard Worker 1613*cda5da8dSAndroid Build Coastguard Worker def appendChild(self, node): 1614*cda5da8dSAndroid Build Coastguard Worker if node.nodeType not in self._child_node_types: 1615*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 1616*cda5da8dSAndroid Build Coastguard Worker "%s cannot be child of %s" % (repr(node), repr(self))) 1617*cda5da8dSAndroid Build Coastguard Worker if node.parentNode is not None: 1618*cda5da8dSAndroid Build Coastguard Worker # This needs to be done before the next test since this 1619*cda5da8dSAndroid Build Coastguard Worker # may *be* the document element, in which case it should 1620*cda5da8dSAndroid Build Coastguard Worker # end up re-ordered to the end. 1621*cda5da8dSAndroid Build Coastguard Worker node.parentNode.removeChild(node) 1622*cda5da8dSAndroid Build Coastguard Worker 1623*cda5da8dSAndroid Build Coastguard Worker if node.nodeType == Node.ELEMENT_NODE \ 1624*cda5da8dSAndroid Build Coastguard Worker and self._get_documentElement(): 1625*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.HierarchyRequestErr( 1626*cda5da8dSAndroid Build Coastguard Worker "two document elements disallowed") 1627*cda5da8dSAndroid Build Coastguard Worker return Node.appendChild(self, node) 1628*cda5da8dSAndroid Build Coastguard Worker 1629*cda5da8dSAndroid Build Coastguard Worker def removeChild(self, oldChild): 1630*cda5da8dSAndroid Build Coastguard Worker try: 1631*cda5da8dSAndroid Build Coastguard Worker self.childNodes.remove(oldChild) 1632*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1633*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotFoundErr() 1634*cda5da8dSAndroid Build Coastguard Worker oldChild.nextSibling = oldChild.previousSibling = None 1635*cda5da8dSAndroid Build Coastguard Worker oldChild.parentNode = None 1636*cda5da8dSAndroid Build Coastguard Worker if self.documentElement is oldChild: 1637*cda5da8dSAndroid Build Coastguard Worker self.documentElement = None 1638*cda5da8dSAndroid Build Coastguard Worker 1639*cda5da8dSAndroid Build Coastguard Worker return oldChild 1640*cda5da8dSAndroid Build Coastguard Worker 1641*cda5da8dSAndroid Build Coastguard Worker def _get_documentElement(self): 1642*cda5da8dSAndroid Build Coastguard Worker for node in self.childNodes: 1643*cda5da8dSAndroid Build Coastguard Worker if node.nodeType == Node.ELEMENT_NODE: 1644*cda5da8dSAndroid Build Coastguard Worker return node 1645*cda5da8dSAndroid Build Coastguard Worker 1646*cda5da8dSAndroid Build Coastguard Worker def unlink(self): 1647*cda5da8dSAndroid Build Coastguard Worker if self.doctype is not None: 1648*cda5da8dSAndroid Build Coastguard Worker self.doctype.unlink() 1649*cda5da8dSAndroid Build Coastguard Worker self.doctype = None 1650*cda5da8dSAndroid Build Coastguard Worker Node.unlink(self) 1651*cda5da8dSAndroid Build Coastguard Worker 1652*cda5da8dSAndroid Build Coastguard Worker def cloneNode(self, deep): 1653*cda5da8dSAndroid Build Coastguard Worker if not deep: 1654*cda5da8dSAndroid Build Coastguard Worker return None 1655*cda5da8dSAndroid Build Coastguard Worker clone = self.implementation.createDocument(None, None, None) 1656*cda5da8dSAndroid Build Coastguard Worker clone.encoding = self.encoding 1657*cda5da8dSAndroid Build Coastguard Worker clone.standalone = self.standalone 1658*cda5da8dSAndroid Build Coastguard Worker clone.version = self.version 1659*cda5da8dSAndroid Build Coastguard Worker for n in self.childNodes: 1660*cda5da8dSAndroid Build Coastguard Worker childclone = _clone_node(n, deep, clone) 1661*cda5da8dSAndroid Build Coastguard Worker assert childclone.ownerDocument.isSameNode(clone) 1662*cda5da8dSAndroid Build Coastguard Worker clone.childNodes.append(childclone) 1663*cda5da8dSAndroid Build Coastguard Worker if childclone.nodeType == Node.DOCUMENT_NODE: 1664*cda5da8dSAndroid Build Coastguard Worker assert clone.documentElement is None 1665*cda5da8dSAndroid Build Coastguard Worker elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE: 1666*cda5da8dSAndroid Build Coastguard Worker assert clone.doctype is None 1667*cda5da8dSAndroid Build Coastguard Worker clone.doctype = childclone 1668*cda5da8dSAndroid Build Coastguard Worker childclone.parentNode = clone 1669*cda5da8dSAndroid Build Coastguard Worker self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED, 1670*cda5da8dSAndroid Build Coastguard Worker self, clone) 1671*cda5da8dSAndroid Build Coastguard Worker return clone 1672*cda5da8dSAndroid Build Coastguard Worker 1673*cda5da8dSAndroid Build Coastguard Worker def createDocumentFragment(self): 1674*cda5da8dSAndroid Build Coastguard Worker d = DocumentFragment() 1675*cda5da8dSAndroid Build Coastguard Worker d.ownerDocument = self 1676*cda5da8dSAndroid Build Coastguard Worker return d 1677*cda5da8dSAndroid Build Coastguard Worker 1678*cda5da8dSAndroid Build Coastguard Worker def createElement(self, tagName): 1679*cda5da8dSAndroid Build Coastguard Worker e = Element(tagName) 1680*cda5da8dSAndroid Build Coastguard Worker e.ownerDocument = self 1681*cda5da8dSAndroid Build Coastguard Worker return e 1682*cda5da8dSAndroid Build Coastguard Worker 1683*cda5da8dSAndroid Build Coastguard Worker def createTextNode(self, data): 1684*cda5da8dSAndroid Build Coastguard Worker if not isinstance(data, str): 1685*cda5da8dSAndroid Build Coastguard Worker raise TypeError("node contents must be a string") 1686*cda5da8dSAndroid Build Coastguard Worker t = Text() 1687*cda5da8dSAndroid Build Coastguard Worker t.data = data 1688*cda5da8dSAndroid Build Coastguard Worker t.ownerDocument = self 1689*cda5da8dSAndroid Build Coastguard Worker return t 1690*cda5da8dSAndroid Build Coastguard Worker 1691*cda5da8dSAndroid Build Coastguard Worker def createCDATASection(self, data): 1692*cda5da8dSAndroid Build Coastguard Worker if not isinstance(data, str): 1693*cda5da8dSAndroid Build Coastguard Worker raise TypeError("node contents must be a string") 1694*cda5da8dSAndroid Build Coastguard Worker c = CDATASection() 1695*cda5da8dSAndroid Build Coastguard Worker c.data = data 1696*cda5da8dSAndroid Build Coastguard Worker c.ownerDocument = self 1697*cda5da8dSAndroid Build Coastguard Worker return c 1698*cda5da8dSAndroid Build Coastguard Worker 1699*cda5da8dSAndroid Build Coastguard Worker def createComment(self, data): 1700*cda5da8dSAndroid Build Coastguard Worker c = Comment(data) 1701*cda5da8dSAndroid Build Coastguard Worker c.ownerDocument = self 1702*cda5da8dSAndroid Build Coastguard Worker return c 1703*cda5da8dSAndroid Build Coastguard Worker 1704*cda5da8dSAndroid Build Coastguard Worker def createProcessingInstruction(self, target, data): 1705*cda5da8dSAndroid Build Coastguard Worker p = ProcessingInstruction(target, data) 1706*cda5da8dSAndroid Build Coastguard Worker p.ownerDocument = self 1707*cda5da8dSAndroid Build Coastguard Worker return p 1708*cda5da8dSAndroid Build Coastguard Worker 1709*cda5da8dSAndroid Build Coastguard Worker def createAttribute(self, qName): 1710*cda5da8dSAndroid Build Coastguard Worker a = Attr(qName) 1711*cda5da8dSAndroid Build Coastguard Worker a.ownerDocument = self 1712*cda5da8dSAndroid Build Coastguard Worker a.value = "" 1713*cda5da8dSAndroid Build Coastguard Worker return a 1714*cda5da8dSAndroid Build Coastguard Worker 1715*cda5da8dSAndroid Build Coastguard Worker def createElementNS(self, namespaceURI, qualifiedName): 1716*cda5da8dSAndroid Build Coastguard Worker prefix, localName = _nssplit(qualifiedName) 1717*cda5da8dSAndroid Build Coastguard Worker e = Element(qualifiedName, namespaceURI, prefix) 1718*cda5da8dSAndroid Build Coastguard Worker e.ownerDocument = self 1719*cda5da8dSAndroid Build Coastguard Worker return e 1720*cda5da8dSAndroid Build Coastguard Worker 1721*cda5da8dSAndroid Build Coastguard Worker def createAttributeNS(self, namespaceURI, qualifiedName): 1722*cda5da8dSAndroid Build Coastguard Worker prefix, localName = _nssplit(qualifiedName) 1723*cda5da8dSAndroid Build Coastguard Worker a = Attr(qualifiedName, namespaceURI, localName, prefix) 1724*cda5da8dSAndroid Build Coastguard Worker a.ownerDocument = self 1725*cda5da8dSAndroid Build Coastguard Worker a.value = "" 1726*cda5da8dSAndroid Build Coastguard Worker return a 1727*cda5da8dSAndroid Build Coastguard Worker 1728*cda5da8dSAndroid Build Coastguard Worker # A couple of implementation-specific helpers to create node types 1729*cda5da8dSAndroid Build Coastguard Worker # not supported by the W3C DOM specs: 1730*cda5da8dSAndroid Build Coastguard Worker 1731*cda5da8dSAndroid Build Coastguard Worker def _create_entity(self, name, publicId, systemId, notationName): 1732*cda5da8dSAndroid Build Coastguard Worker e = Entity(name, publicId, systemId, notationName) 1733*cda5da8dSAndroid Build Coastguard Worker e.ownerDocument = self 1734*cda5da8dSAndroid Build Coastguard Worker return e 1735*cda5da8dSAndroid Build Coastguard Worker 1736*cda5da8dSAndroid Build Coastguard Worker def _create_notation(self, name, publicId, systemId): 1737*cda5da8dSAndroid Build Coastguard Worker n = Notation(name, publicId, systemId) 1738*cda5da8dSAndroid Build Coastguard Worker n.ownerDocument = self 1739*cda5da8dSAndroid Build Coastguard Worker return n 1740*cda5da8dSAndroid Build Coastguard Worker 1741*cda5da8dSAndroid Build Coastguard Worker def getElementById(self, id): 1742*cda5da8dSAndroid Build Coastguard Worker if id in self._id_cache: 1743*cda5da8dSAndroid Build Coastguard Worker return self._id_cache[id] 1744*cda5da8dSAndroid Build Coastguard Worker if not (self._elem_info or self._magic_id_count): 1745*cda5da8dSAndroid Build Coastguard Worker return None 1746*cda5da8dSAndroid Build Coastguard Worker 1747*cda5da8dSAndroid Build Coastguard Worker stack = self._id_search_stack 1748*cda5da8dSAndroid Build Coastguard Worker if stack is None: 1749*cda5da8dSAndroid Build Coastguard Worker # we never searched before, or the cache has been cleared 1750*cda5da8dSAndroid Build Coastguard Worker stack = [self.documentElement] 1751*cda5da8dSAndroid Build Coastguard Worker self._id_search_stack = stack 1752*cda5da8dSAndroid Build Coastguard Worker elif not stack: 1753*cda5da8dSAndroid Build Coastguard Worker # Previous search was completed and cache is still valid; 1754*cda5da8dSAndroid Build Coastguard Worker # no matching node. 1755*cda5da8dSAndroid Build Coastguard Worker return None 1756*cda5da8dSAndroid Build Coastguard Worker 1757*cda5da8dSAndroid Build Coastguard Worker result = None 1758*cda5da8dSAndroid Build Coastguard Worker while stack: 1759*cda5da8dSAndroid Build Coastguard Worker node = stack.pop() 1760*cda5da8dSAndroid Build Coastguard Worker # add child elements to stack for continued searching 1761*cda5da8dSAndroid Build Coastguard Worker stack.extend([child for child in node.childNodes 1762*cda5da8dSAndroid Build Coastguard Worker if child.nodeType in _nodeTypes_with_children]) 1763*cda5da8dSAndroid Build Coastguard Worker # check this node 1764*cda5da8dSAndroid Build Coastguard Worker info = self._get_elem_info(node) 1765*cda5da8dSAndroid Build Coastguard Worker if info: 1766*cda5da8dSAndroid Build Coastguard Worker # We have to process all ID attributes before 1767*cda5da8dSAndroid Build Coastguard Worker # returning in order to get all the attributes set to 1768*cda5da8dSAndroid Build Coastguard Worker # be IDs using Element.setIdAttribute*(). 1769*cda5da8dSAndroid Build Coastguard Worker for attr in node.attributes.values(): 1770*cda5da8dSAndroid Build Coastguard Worker if attr.namespaceURI: 1771*cda5da8dSAndroid Build Coastguard Worker if info.isIdNS(attr.namespaceURI, attr.localName): 1772*cda5da8dSAndroid Build Coastguard Worker self._id_cache[attr.value] = node 1773*cda5da8dSAndroid Build Coastguard Worker if attr.value == id: 1774*cda5da8dSAndroid Build Coastguard Worker result = node 1775*cda5da8dSAndroid Build Coastguard Worker elif not node._magic_id_nodes: 1776*cda5da8dSAndroid Build Coastguard Worker break 1777*cda5da8dSAndroid Build Coastguard Worker elif info.isId(attr.name): 1778*cda5da8dSAndroid Build Coastguard Worker self._id_cache[attr.value] = node 1779*cda5da8dSAndroid Build Coastguard Worker if attr.value == id: 1780*cda5da8dSAndroid Build Coastguard Worker result = node 1781*cda5da8dSAndroid Build Coastguard Worker elif not node._magic_id_nodes: 1782*cda5da8dSAndroid Build Coastguard Worker break 1783*cda5da8dSAndroid Build Coastguard Worker elif attr._is_id: 1784*cda5da8dSAndroid Build Coastguard Worker self._id_cache[attr.value] = node 1785*cda5da8dSAndroid Build Coastguard Worker if attr.value == id: 1786*cda5da8dSAndroid Build Coastguard Worker result = node 1787*cda5da8dSAndroid Build Coastguard Worker elif node._magic_id_nodes == 1: 1788*cda5da8dSAndroid Build Coastguard Worker break 1789*cda5da8dSAndroid Build Coastguard Worker elif node._magic_id_nodes: 1790*cda5da8dSAndroid Build Coastguard Worker for attr in node.attributes.values(): 1791*cda5da8dSAndroid Build Coastguard Worker if attr._is_id: 1792*cda5da8dSAndroid Build Coastguard Worker self._id_cache[attr.value] = node 1793*cda5da8dSAndroid Build Coastguard Worker if attr.value == id: 1794*cda5da8dSAndroid Build Coastguard Worker result = node 1795*cda5da8dSAndroid Build Coastguard Worker if result is not None: 1796*cda5da8dSAndroid Build Coastguard Worker break 1797*cda5da8dSAndroid Build Coastguard Worker return result 1798*cda5da8dSAndroid Build Coastguard Worker 1799*cda5da8dSAndroid Build Coastguard Worker def getElementsByTagName(self, name): 1800*cda5da8dSAndroid Build Coastguard Worker return _get_elements_by_tagName_helper(self, name, NodeList()) 1801*cda5da8dSAndroid Build Coastguard Worker 1802*cda5da8dSAndroid Build Coastguard Worker def getElementsByTagNameNS(self, namespaceURI, localName): 1803*cda5da8dSAndroid Build Coastguard Worker return _get_elements_by_tagName_ns_helper( 1804*cda5da8dSAndroid Build Coastguard Worker self, namespaceURI, localName, NodeList()) 1805*cda5da8dSAndroid Build Coastguard Worker 1806*cda5da8dSAndroid Build Coastguard Worker def isSupported(self, feature, version): 1807*cda5da8dSAndroid Build Coastguard Worker return self.implementation.hasFeature(feature, version) 1808*cda5da8dSAndroid Build Coastguard Worker 1809*cda5da8dSAndroid Build Coastguard Worker def importNode(self, node, deep): 1810*cda5da8dSAndroid Build Coastguard Worker if node.nodeType == Node.DOCUMENT_NODE: 1811*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotSupportedErr("cannot import document nodes") 1812*cda5da8dSAndroid Build Coastguard Worker elif node.nodeType == Node.DOCUMENT_TYPE_NODE: 1813*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotSupportedErr("cannot import document type nodes") 1814*cda5da8dSAndroid Build Coastguard Worker return _clone_node(node, deep, self) 1815*cda5da8dSAndroid Build Coastguard Worker 1816*cda5da8dSAndroid Build Coastguard Worker def writexml(self, writer, indent="", addindent="", newl="", encoding=None, 1817*cda5da8dSAndroid Build Coastguard Worker standalone=None): 1818*cda5da8dSAndroid Build Coastguard Worker declarations = [] 1819*cda5da8dSAndroid Build Coastguard Worker 1820*cda5da8dSAndroid Build Coastguard Worker if encoding: 1821*cda5da8dSAndroid Build Coastguard Worker declarations.append(f'encoding="{encoding}"') 1822*cda5da8dSAndroid Build Coastguard Worker if standalone is not None: 1823*cda5da8dSAndroid Build Coastguard Worker declarations.append(f'standalone="{"yes" if standalone else "no"}"') 1824*cda5da8dSAndroid Build Coastguard Worker 1825*cda5da8dSAndroid Build Coastguard Worker writer.write(f'<?xml version="1.0" {" ".join(declarations)}?>{newl}') 1826*cda5da8dSAndroid Build Coastguard Worker 1827*cda5da8dSAndroid Build Coastguard Worker for node in self.childNodes: 1828*cda5da8dSAndroid Build Coastguard Worker node.writexml(writer, indent, addindent, newl) 1829*cda5da8dSAndroid Build Coastguard Worker 1830*cda5da8dSAndroid Build Coastguard Worker # DOM Level 3 (WD 9 April 2002) 1831*cda5da8dSAndroid Build Coastguard Worker 1832*cda5da8dSAndroid Build Coastguard Worker def renameNode(self, n, namespaceURI, name): 1833*cda5da8dSAndroid Build Coastguard Worker if n.ownerDocument is not self: 1834*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.WrongDocumentErr( 1835*cda5da8dSAndroid Build Coastguard Worker "cannot rename nodes from other documents;\n" 1836*cda5da8dSAndroid Build Coastguard Worker "expected %s,\nfound %s" % (self, n.ownerDocument)) 1837*cda5da8dSAndroid Build Coastguard Worker if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE): 1838*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotSupportedErr( 1839*cda5da8dSAndroid Build Coastguard Worker "renameNode() only applies to element and attribute nodes") 1840*cda5da8dSAndroid Build Coastguard Worker if namespaceURI != EMPTY_NAMESPACE: 1841*cda5da8dSAndroid Build Coastguard Worker if ':' in name: 1842*cda5da8dSAndroid Build Coastguard Worker prefix, localName = name.split(':', 1) 1843*cda5da8dSAndroid Build Coastguard Worker if ( prefix == "xmlns" 1844*cda5da8dSAndroid Build Coastguard Worker and namespaceURI != xml.dom.XMLNS_NAMESPACE): 1845*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NamespaceErr( 1846*cda5da8dSAndroid Build Coastguard Worker "illegal use of 'xmlns' prefix") 1847*cda5da8dSAndroid Build Coastguard Worker else: 1848*cda5da8dSAndroid Build Coastguard Worker if ( name == "xmlns" 1849*cda5da8dSAndroid Build Coastguard Worker and namespaceURI != xml.dom.XMLNS_NAMESPACE 1850*cda5da8dSAndroid Build Coastguard Worker and n.nodeType == Node.ATTRIBUTE_NODE): 1851*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NamespaceErr( 1852*cda5da8dSAndroid Build Coastguard Worker "illegal use of the 'xmlns' attribute") 1853*cda5da8dSAndroid Build Coastguard Worker prefix = None 1854*cda5da8dSAndroid Build Coastguard Worker localName = name 1855*cda5da8dSAndroid Build Coastguard Worker else: 1856*cda5da8dSAndroid Build Coastguard Worker prefix = None 1857*cda5da8dSAndroid Build Coastguard Worker localName = None 1858*cda5da8dSAndroid Build Coastguard Worker if n.nodeType == Node.ATTRIBUTE_NODE: 1859*cda5da8dSAndroid Build Coastguard Worker element = n.ownerElement 1860*cda5da8dSAndroid Build Coastguard Worker if element is not None: 1861*cda5da8dSAndroid Build Coastguard Worker is_id = n._is_id 1862*cda5da8dSAndroid Build Coastguard Worker element.removeAttributeNode(n) 1863*cda5da8dSAndroid Build Coastguard Worker else: 1864*cda5da8dSAndroid Build Coastguard Worker element = None 1865*cda5da8dSAndroid Build Coastguard Worker n.prefix = prefix 1866*cda5da8dSAndroid Build Coastguard Worker n._localName = localName 1867*cda5da8dSAndroid Build Coastguard Worker n.namespaceURI = namespaceURI 1868*cda5da8dSAndroid Build Coastguard Worker n.nodeName = name 1869*cda5da8dSAndroid Build Coastguard Worker if n.nodeType == Node.ELEMENT_NODE: 1870*cda5da8dSAndroid Build Coastguard Worker n.tagName = name 1871*cda5da8dSAndroid Build Coastguard Worker else: 1872*cda5da8dSAndroid Build Coastguard Worker # attribute node 1873*cda5da8dSAndroid Build Coastguard Worker n.name = name 1874*cda5da8dSAndroid Build Coastguard Worker if element is not None: 1875*cda5da8dSAndroid Build Coastguard Worker element.setAttributeNode(n) 1876*cda5da8dSAndroid Build Coastguard Worker if is_id: 1877*cda5da8dSAndroid Build Coastguard Worker element.setIdAttributeNode(n) 1878*cda5da8dSAndroid Build Coastguard Worker # It's not clear from a semantic perspective whether we should 1879*cda5da8dSAndroid Build Coastguard Worker # call the user data handlers for the NODE_RENAMED event since 1880*cda5da8dSAndroid Build Coastguard Worker # we're re-using the existing node. The draft spec has been 1881*cda5da8dSAndroid Build Coastguard Worker # interpreted as meaning "no, don't call the handler unless a 1882*cda5da8dSAndroid Build Coastguard Worker # new node is created." 1883*cda5da8dSAndroid Build Coastguard Worker return n 1884*cda5da8dSAndroid Build Coastguard Worker 1885*cda5da8dSAndroid Build Coastguard Workerdefproperty(Document, "documentElement", 1886*cda5da8dSAndroid Build Coastguard Worker doc="Top-level element of this document.") 1887*cda5da8dSAndroid Build Coastguard Worker 1888*cda5da8dSAndroid Build Coastguard Worker 1889*cda5da8dSAndroid Build Coastguard Workerdef _clone_node(node, deep, newOwnerDocument): 1890*cda5da8dSAndroid Build Coastguard Worker """ 1891*cda5da8dSAndroid Build Coastguard Worker Clone a node and give it the new owner document. 1892*cda5da8dSAndroid Build Coastguard Worker Called by Node.cloneNode and Document.importNode 1893*cda5da8dSAndroid Build Coastguard Worker """ 1894*cda5da8dSAndroid Build Coastguard Worker if node.ownerDocument.isSameNode(newOwnerDocument): 1895*cda5da8dSAndroid Build Coastguard Worker operation = xml.dom.UserDataHandler.NODE_CLONED 1896*cda5da8dSAndroid Build Coastguard Worker else: 1897*cda5da8dSAndroid Build Coastguard Worker operation = xml.dom.UserDataHandler.NODE_IMPORTED 1898*cda5da8dSAndroid Build Coastguard Worker if node.nodeType == Node.ELEMENT_NODE: 1899*cda5da8dSAndroid Build Coastguard Worker clone = newOwnerDocument.createElementNS(node.namespaceURI, 1900*cda5da8dSAndroid Build Coastguard Worker node.nodeName) 1901*cda5da8dSAndroid Build Coastguard Worker for attr in node.attributes.values(): 1902*cda5da8dSAndroid Build Coastguard Worker clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value) 1903*cda5da8dSAndroid Build Coastguard Worker a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName) 1904*cda5da8dSAndroid Build Coastguard Worker a.specified = attr.specified 1905*cda5da8dSAndroid Build Coastguard Worker 1906*cda5da8dSAndroid Build Coastguard Worker if deep: 1907*cda5da8dSAndroid Build Coastguard Worker for child in node.childNodes: 1908*cda5da8dSAndroid Build Coastguard Worker c = _clone_node(child, deep, newOwnerDocument) 1909*cda5da8dSAndroid Build Coastguard Worker clone.appendChild(c) 1910*cda5da8dSAndroid Build Coastguard Worker 1911*cda5da8dSAndroid Build Coastguard Worker elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE: 1912*cda5da8dSAndroid Build Coastguard Worker clone = newOwnerDocument.createDocumentFragment() 1913*cda5da8dSAndroid Build Coastguard Worker if deep: 1914*cda5da8dSAndroid Build Coastguard Worker for child in node.childNodes: 1915*cda5da8dSAndroid Build Coastguard Worker c = _clone_node(child, deep, newOwnerDocument) 1916*cda5da8dSAndroid Build Coastguard Worker clone.appendChild(c) 1917*cda5da8dSAndroid Build Coastguard Worker 1918*cda5da8dSAndroid Build Coastguard Worker elif node.nodeType == Node.TEXT_NODE: 1919*cda5da8dSAndroid Build Coastguard Worker clone = newOwnerDocument.createTextNode(node.data) 1920*cda5da8dSAndroid Build Coastguard Worker elif node.nodeType == Node.CDATA_SECTION_NODE: 1921*cda5da8dSAndroid Build Coastguard Worker clone = newOwnerDocument.createCDATASection(node.data) 1922*cda5da8dSAndroid Build Coastguard Worker elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: 1923*cda5da8dSAndroid Build Coastguard Worker clone = newOwnerDocument.createProcessingInstruction(node.target, 1924*cda5da8dSAndroid Build Coastguard Worker node.data) 1925*cda5da8dSAndroid Build Coastguard Worker elif node.nodeType == Node.COMMENT_NODE: 1926*cda5da8dSAndroid Build Coastguard Worker clone = newOwnerDocument.createComment(node.data) 1927*cda5da8dSAndroid Build Coastguard Worker elif node.nodeType == Node.ATTRIBUTE_NODE: 1928*cda5da8dSAndroid Build Coastguard Worker clone = newOwnerDocument.createAttributeNS(node.namespaceURI, 1929*cda5da8dSAndroid Build Coastguard Worker node.nodeName) 1930*cda5da8dSAndroid Build Coastguard Worker clone.specified = True 1931*cda5da8dSAndroid Build Coastguard Worker clone.value = node.value 1932*cda5da8dSAndroid Build Coastguard Worker elif node.nodeType == Node.DOCUMENT_TYPE_NODE: 1933*cda5da8dSAndroid Build Coastguard Worker assert node.ownerDocument is not newOwnerDocument 1934*cda5da8dSAndroid Build Coastguard Worker operation = xml.dom.UserDataHandler.NODE_IMPORTED 1935*cda5da8dSAndroid Build Coastguard Worker clone = newOwnerDocument.implementation.createDocumentType( 1936*cda5da8dSAndroid Build Coastguard Worker node.name, node.publicId, node.systemId) 1937*cda5da8dSAndroid Build Coastguard Worker clone.ownerDocument = newOwnerDocument 1938*cda5da8dSAndroid Build Coastguard Worker if deep: 1939*cda5da8dSAndroid Build Coastguard Worker clone.entities._seq = [] 1940*cda5da8dSAndroid Build Coastguard Worker clone.notations._seq = [] 1941*cda5da8dSAndroid Build Coastguard Worker for n in node.notations._seq: 1942*cda5da8dSAndroid Build Coastguard Worker notation = Notation(n.nodeName, n.publicId, n.systemId) 1943*cda5da8dSAndroid Build Coastguard Worker notation.ownerDocument = newOwnerDocument 1944*cda5da8dSAndroid Build Coastguard Worker clone.notations._seq.append(notation) 1945*cda5da8dSAndroid Build Coastguard Worker if hasattr(n, '_call_user_data_handler'): 1946*cda5da8dSAndroid Build Coastguard Worker n._call_user_data_handler(operation, n, notation) 1947*cda5da8dSAndroid Build Coastguard Worker for e in node.entities._seq: 1948*cda5da8dSAndroid Build Coastguard Worker entity = Entity(e.nodeName, e.publicId, e.systemId, 1949*cda5da8dSAndroid Build Coastguard Worker e.notationName) 1950*cda5da8dSAndroid Build Coastguard Worker entity.actualEncoding = e.actualEncoding 1951*cda5da8dSAndroid Build Coastguard Worker entity.encoding = e.encoding 1952*cda5da8dSAndroid Build Coastguard Worker entity.version = e.version 1953*cda5da8dSAndroid Build Coastguard Worker entity.ownerDocument = newOwnerDocument 1954*cda5da8dSAndroid Build Coastguard Worker clone.entities._seq.append(entity) 1955*cda5da8dSAndroid Build Coastguard Worker if hasattr(e, '_call_user_data_handler'): 1956*cda5da8dSAndroid Build Coastguard Worker e._call_user_data_handler(operation, e, entity) 1957*cda5da8dSAndroid Build Coastguard Worker else: 1958*cda5da8dSAndroid Build Coastguard Worker # Note the cloning of Document and DocumentType nodes is 1959*cda5da8dSAndroid Build Coastguard Worker # implementation specific. minidom handles those cases 1960*cda5da8dSAndroid Build Coastguard Worker # directly in the cloneNode() methods. 1961*cda5da8dSAndroid Build Coastguard Worker raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node)) 1962*cda5da8dSAndroid Build Coastguard Worker 1963*cda5da8dSAndroid Build Coastguard Worker # Check for _call_user_data_handler() since this could conceivably 1964*cda5da8dSAndroid Build Coastguard Worker # used with other DOM implementations (one of the FourThought 1965*cda5da8dSAndroid Build Coastguard Worker # DOMs, perhaps?). 1966*cda5da8dSAndroid Build Coastguard Worker if hasattr(node, '_call_user_data_handler'): 1967*cda5da8dSAndroid Build Coastguard Worker node._call_user_data_handler(operation, node, clone) 1968*cda5da8dSAndroid Build Coastguard Worker return clone 1969*cda5da8dSAndroid Build Coastguard Worker 1970*cda5da8dSAndroid Build Coastguard Worker 1971*cda5da8dSAndroid Build Coastguard Workerdef _nssplit(qualifiedName): 1972*cda5da8dSAndroid Build Coastguard Worker fields = qualifiedName.split(':', 1) 1973*cda5da8dSAndroid Build Coastguard Worker if len(fields) == 2: 1974*cda5da8dSAndroid Build Coastguard Worker return fields 1975*cda5da8dSAndroid Build Coastguard Worker else: 1976*cda5da8dSAndroid Build Coastguard Worker return (None, fields[0]) 1977*cda5da8dSAndroid Build Coastguard Worker 1978*cda5da8dSAndroid Build Coastguard Worker 1979*cda5da8dSAndroid Build Coastguard Workerdef _do_pulldom_parse(func, args, kwargs): 1980*cda5da8dSAndroid Build Coastguard Worker events = func(*args, **kwargs) 1981*cda5da8dSAndroid Build Coastguard Worker toktype, rootNode = events.getEvent() 1982*cda5da8dSAndroid Build Coastguard Worker events.expandNode(rootNode) 1983*cda5da8dSAndroid Build Coastguard Worker events.clear() 1984*cda5da8dSAndroid Build Coastguard Worker return rootNode 1985*cda5da8dSAndroid Build Coastguard Worker 1986*cda5da8dSAndroid Build Coastguard Workerdef parse(file, parser=None, bufsize=None): 1987*cda5da8dSAndroid Build Coastguard Worker """Parse a file into a DOM by filename or file object.""" 1988*cda5da8dSAndroid Build Coastguard Worker if parser is None and not bufsize: 1989*cda5da8dSAndroid Build Coastguard Worker from xml.dom import expatbuilder 1990*cda5da8dSAndroid Build Coastguard Worker return expatbuilder.parse(file) 1991*cda5da8dSAndroid Build Coastguard Worker else: 1992*cda5da8dSAndroid Build Coastguard Worker from xml.dom import pulldom 1993*cda5da8dSAndroid Build Coastguard Worker return _do_pulldom_parse(pulldom.parse, (file,), 1994*cda5da8dSAndroid Build Coastguard Worker {'parser': parser, 'bufsize': bufsize}) 1995*cda5da8dSAndroid Build Coastguard Worker 1996*cda5da8dSAndroid Build Coastguard Workerdef parseString(string, parser=None): 1997*cda5da8dSAndroid Build Coastguard Worker """Parse a file into a DOM from a string.""" 1998*cda5da8dSAndroid Build Coastguard Worker if parser is None: 1999*cda5da8dSAndroid Build Coastguard Worker from xml.dom import expatbuilder 2000*cda5da8dSAndroid Build Coastguard Worker return expatbuilder.parseString(string) 2001*cda5da8dSAndroid Build Coastguard Worker else: 2002*cda5da8dSAndroid Build Coastguard Worker from xml.dom import pulldom 2003*cda5da8dSAndroid Build Coastguard Worker return _do_pulldom_parse(pulldom.parseString, (string,), 2004*cda5da8dSAndroid Build Coastguard Worker {'parser': parser}) 2005*cda5da8dSAndroid Build Coastguard Worker 2006*cda5da8dSAndroid Build Coastguard Workerdef getDOMImplementation(features=None): 2007*cda5da8dSAndroid Build Coastguard Worker if features: 2008*cda5da8dSAndroid Build Coastguard Worker if isinstance(features, str): 2009*cda5da8dSAndroid Build Coastguard Worker features = domreg._parse_feature_string(features) 2010*cda5da8dSAndroid Build Coastguard Worker for f, v in features: 2011*cda5da8dSAndroid Build Coastguard Worker if not Document.implementation.hasFeature(f, v): 2012*cda5da8dSAndroid Build Coastguard Worker return None 2013*cda5da8dSAndroid Build Coastguard Worker return Document.implementation 2014