blob: 03862882aa2a0ecdc5ea036c0aa1fee950f62cf3 [file] [log] [blame]
Fred Drake1f549022000-09-24 05:21:58 +00001"""\
Fred Drakef7cf40d2000-12-14 18:16:11 +00002minidom.py -- a lightweight DOM implementation.
Fred Drake55c38192000-06-29 19:39:57 +00003
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00004parse("foo.xml")
Paul Prescod623511b2000-07-21 22:05:49 +00005
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00006parseString("<foo><bar/></foo>")
Paul Prescod623511b2000-07-21 22:05:49 +00007
Fred Drake55c38192000-06-29 19:39:57 +00008Todo:
9=====
10 * convenience methods for getting elements and text.
11 * more testing
12 * bring some of the writer and linearizer code into conformance with this
13 interface
14 * SAX 2 namespaces
15"""
16
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000017import io
Thomas Wouters0e3f5912006-08-11 14:57:12 +000018import xml.dom
Fred Drake55c38192000-06-29 19:39:57 +000019
Thomas Wouters0e3f5912006-08-11 14:57:12 +000020from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
21from xml.dom.minicompat import *
22from xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS
Fred Drake3ac6a092001-09-28 04:33:06 +000023
Martin v. Löwis787354c2003-01-25 15:28:29 +000024# This is used by the ID-cache invalidation checks; the list isn't
25# actually complete, since the nodes being checked will never be the
26# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE. (The node being checked is
27# the node being added or removed, not the node being modified.)
28#
Thomas Wouters0e3f5912006-08-11 14:57:12 +000029_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE,
30 xml.dom.Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis95700f72002-03-15 13:51:59 +000031
Fred Drake3ac6a092001-09-28 04:33:06 +000032
Thomas Wouters0e3f5912006-08-11 14:57:12 +000033class Node(xml.dom.Node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000034 namespaceURI = None # this is non-null only for elements and attributes
Fred Drake575712e2001-09-28 20:25:45 +000035 parentNode = None
36 ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +000037 nextSibling = None
38 previousSibling = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +000039
Martin v. Löwis787354c2003-01-25 15:28:29 +000040 prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
Fred Drake55c38192000-06-29 19:39:57 +000041
Jack Diederich4dafcc42006-11-28 19:15:13 +000042 def __bool__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +000043 return True
Fred Drake55c38192000-06-29 19:39:57 +000044
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000045 def toxml(self, encoding = None):
46 return self.toprettyxml("", "", encoding)
Fred Drake55c38192000-06-29 19:39:57 +000047
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000048 def toprettyxml(self, indent="\t", newl="\n", encoding=None):
Martin v. Löwiscb67ea12001-03-31 16:30:40 +000049 # indent = the indentation string to prepend, per level
50 # newl = the newline string to append
Guido van Rossum55b15c92007-08-07 23:03:33 +000051 use_encoding = "utf-8" if encoding is None else encoding
52 writer = io.StringIO(encoding=use_encoding)
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000053 if self.nodeType == Node.DOCUMENT_NODE:
54 # Can pass encoding only to document, to put it into XML header
55 self.writexml(writer, "", indent, newl, encoding)
56 else:
57 self.writexml(writer, "", indent, newl)
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000058 if encoding is None:
59 return writer.getvalue()
60 else:
61 return writer.buffer.getvalue()
Martin v. Löwis46fa39a2001-02-06 00:14:08 +000062
Fred Drake1f549022000-09-24 05:21:58 +000063 def hasChildNodes(self):
64 if self.childNodes:
Martin v. Löwis787354c2003-01-25 15:28:29 +000065 return True
Fred Drake1f549022000-09-24 05:21:58 +000066 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +000067 return False
68
69 def _get_childNodes(self):
70 return self.childNodes
Fred Drake55c38192000-06-29 19:39:57 +000071
Fred Drake1f549022000-09-24 05:21:58 +000072 def _get_firstChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000073 if self.childNodes:
74 return self.childNodes[0]
Paul Prescod73678da2000-07-01 04:58:47 +000075
Fred Drake1f549022000-09-24 05:21:58 +000076 def _get_lastChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000077 if self.childNodes:
78 return self.childNodes[-1]
Paul Prescod73678da2000-07-01 04:58:47 +000079
Fred Drake1f549022000-09-24 05:21:58 +000080 def insertBefore(self, newChild, refChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000081 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +000082 for c in tuple(newChild.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000083 self.insertBefore(c, refChild)
84 ### The DOM does not clearly specify what to return in this case
85 return newChild
Martin v. Löwis787354c2003-01-25 15:28:29 +000086 if newChild.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000087 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +000088 "%s cannot be child of %s" % (repr(newChild), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +000089 if newChild.parentNode is not None:
90 newChild.parentNode.removeChild(newChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +000091 if refChild is None:
92 self.appendChild(newChild)
93 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +000094 try:
95 index = self.childNodes.index(refChild)
96 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000097 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +000098 if newChild.nodeType in _nodeTypes_with_children:
99 _clear_id_cache(self)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000100 self.childNodes.insert(index, newChild)
101 newChild.nextSibling = refChild
102 refChild.previousSibling = newChild
103 if index:
104 node = self.childNodes[index-1]
105 node.nextSibling = newChild
106 newChild.previousSibling = node
107 else:
108 newChild.previousSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000109 newChild.parentNode = self
Fred Drake4ccf4a12000-11-21 22:02:22 +0000110 return newChild
Fred Drake55c38192000-06-29 19:39:57 +0000111
Fred Drake1f549022000-09-24 05:21:58 +0000112 def appendChild(self, node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000113 if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +0000114 for c in tuple(node.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000115 self.appendChild(c)
116 ### The DOM does not clearly specify what to return in this case
117 return node
Martin v. Löwis787354c2003-01-25 15:28:29 +0000118 if node.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000119 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000120 "%s cannot be child of %s" % (repr(node), repr(self)))
121 elif node.nodeType in _nodeTypes_with_children:
122 _clear_id_cache(self)
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000123 if node.parentNode is not None:
124 node.parentNode.removeChild(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000125 _append_child(self, node)
Fred Drake13a30692000-10-09 20:04:16 +0000126 node.nextSibling = None
Paul Prescod73678da2000-07-01 04:58:47 +0000127 return node
128
Fred Drake1f549022000-09-24 05:21:58 +0000129 def replaceChild(self, newChild, oldChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000130 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
131 refChild = oldChild.nextSibling
132 self.removeChild(oldChild)
133 return self.insertBefore(newChild, refChild)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000134 if newChild.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000135 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000136 "%s cannot be child of %s" % (repr(newChild), repr(self)))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000137 if newChild is oldChild:
138 return
Andrew M. Kuchling841d25e2005-11-22 19:03:16 +0000139 if newChild.parentNode is not None:
140 newChild.parentNode.removeChild(newChild)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000141 try:
142 index = self.childNodes.index(oldChild)
143 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000144 raise xml.dom.NotFoundErr()
Fred Drake4ccf4a12000-11-21 22:02:22 +0000145 self.childNodes[index] = newChild
Martin v. Löwis787354c2003-01-25 15:28:29 +0000146 newChild.parentNode = self
147 oldChild.parentNode = None
148 if (newChild.nodeType in _nodeTypes_with_children
149 or oldChild.nodeType in _nodeTypes_with_children):
150 _clear_id_cache(self)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000151 newChild.nextSibling = oldChild.nextSibling
152 newChild.previousSibling = oldChild.previousSibling
Martin v. Löwis156c3372000-12-28 18:40:56 +0000153 oldChild.nextSibling = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000154 oldChild.previousSibling = None
Martin v. Löwis156c3372000-12-28 18:40:56 +0000155 if newChild.previousSibling:
156 newChild.previousSibling.nextSibling = newChild
157 if newChild.nextSibling:
158 newChild.nextSibling.previousSibling = newChild
Fred Drake4ccf4a12000-11-21 22:02:22 +0000159 return oldChild
Paul Prescod73678da2000-07-01 04:58:47 +0000160
Fred Drake1f549022000-09-24 05:21:58 +0000161 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000162 try:
163 self.childNodes.remove(oldChild)
164 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000165 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000166 if oldChild.nextSibling is not None:
167 oldChild.nextSibling.previousSibling = oldChild.previousSibling
168 if oldChild.previousSibling is not None:
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000169 oldChild.previousSibling.nextSibling = oldChild.nextSibling
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000170 oldChild.nextSibling = oldChild.previousSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000171 if oldChild.nodeType in _nodeTypes_with_children:
172 _clear_id_cache(self)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000173
Martin v. Löwis787354c2003-01-25 15:28:29 +0000174 oldChild.parentNode = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000175 return oldChild
176
177 def normalize(self):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000178 L = []
179 for child in self.childNodes:
180 if child.nodeType == Node.TEXT_NODE:
181 data = child.data
182 if data and L and L[-1].nodeType == child.nodeType:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000183 # collapse text node
184 node = L[-1]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000185 node.data = node.data + child.data
Fred Drake4ccf4a12000-11-21 22:02:22 +0000186 node.nextSibling = child.nextSibling
187 child.unlink()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000188 elif data:
189 if L:
190 L[-1].nextSibling = child
191 child.previousSibling = L[-1]
192 else:
193 child.previousSibling = None
194 L.append(child)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000195 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000196 # empty text node; discard
197 child.unlink()
198 else:
199 if L:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000200 L[-1].nextSibling = child
201 child.previousSibling = L[-1]
Fred Drakef7cf40d2000-12-14 18:16:11 +0000202 else:
203 child.previousSibling = None
204 L.append(child)
205 if child.nodeType == Node.ELEMENT_NODE:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000206 child.normalize()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000207 self.childNodes[:] = L
Paul Prescod73678da2000-07-01 04:58:47 +0000208
Fred Drake1f549022000-09-24 05:21:58 +0000209 def cloneNode(self, deep):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000210 return _clone_node(self, deep, self.ownerDocument or self)
Fred Drake55c38192000-06-29 19:39:57 +0000211
Martin v. Löwis787354c2003-01-25 15:28:29 +0000212 def isSupported(self, feature, version):
213 return self.ownerDocument.implementation.hasFeature(feature, version)
214
215 def _get_localName(self):
216 # Overridden in Element and Attr where localName can be Non-Null
217 return None
218
219 # Node interfaces from Level 3 (WD 9 April 2002)
Fred Drake25239772001-02-02 19:40:19 +0000220
221 def isSameNode(self, other):
222 return self is other
223
Martin v. Löwis787354c2003-01-25 15:28:29 +0000224 def getInterface(self, feature):
225 if self.isSupported(feature, None):
226 return self
227 else:
228 return None
229
230 # The "user data" functions use a dictionary that is only present
231 # if some user data has been set, so be careful not to assume it
232 # exists.
233
234 def getUserData(self, key):
235 try:
236 return self._user_data[key][0]
237 except (AttributeError, KeyError):
238 return None
239
240 def setUserData(self, key, data, handler):
241 old = None
242 try:
243 d = self._user_data
244 except AttributeError:
245 d = {}
246 self._user_data = d
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000247 if key in d:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000248 old = d[key][0]
249 if data is None:
250 # ignore handlers passed for None
251 handler = None
252 if old is not None:
253 del d[key]
254 else:
255 d[key] = (data, handler)
256 return old
257
258 def _call_user_data_handler(self, operation, src, dst):
259 if hasattr(self, "_user_data"):
Brett Cannon861fd6f2007-02-21 22:05:37 +0000260 for key, (data, handler) in list(self._user_data.items()):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000261 if handler is not None:
262 handler.handle(operation, key, data, src, dst)
263
Fred Drake25239772001-02-02 19:40:19 +0000264 # minidom-specific API:
265
Fred Drake1f549022000-09-24 05:21:58 +0000266 def unlink(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000267 self.parentNode = self.ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000268 if self.childNodes:
269 for child in self.childNodes:
270 child.unlink()
271 self.childNodes = NodeList()
Paul Prescod4221ff02000-10-13 20:11:42 +0000272 self.previousSibling = None
273 self.nextSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000274
275defproperty(Node, "firstChild", doc="First child node, or None.")
276defproperty(Node, "lastChild", doc="Last child node, or None.")
277defproperty(Node, "localName", doc="Namespace-local name of this node.")
278
279
280def _append_child(self, node):
281 # fast path with less checks; usable by DOM builders if careful
282 childNodes = self.childNodes
283 if childNodes:
284 last = childNodes[-1]
285 node.__dict__["previousSibling"] = last
286 last.__dict__["nextSibling"] = node
287 childNodes.append(node)
288 node.__dict__["parentNode"] = self
289
290def _in_document(node):
291 # return True iff node is part of a document tree
292 while node is not None:
293 if node.nodeType == Node.DOCUMENT_NODE:
294 return True
295 node = node.parentNode
296 return False
Fred Drake55c38192000-06-29 19:39:57 +0000297
Fred Drake1f549022000-09-24 05:21:58 +0000298def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000299 "Writes datachars to writer."
Martin v. Löwis787354c2003-01-25 15:28:29 +0000300 data = data.replace("&", "&amp;").replace("<", "&lt;")
301 data = data.replace("\"", "&quot;").replace(">", "&gt;")
Fred Drake55c38192000-06-29 19:39:57 +0000302 writer.write(data)
303
Martin v. Löwis787354c2003-01-25 15:28:29 +0000304def _get_elements_by_tagName_helper(parent, name, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000305 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000306 if node.nodeType == Node.ELEMENT_NODE and \
307 (name == "*" or node.tagName == name):
308 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000309 _get_elements_by_tagName_helper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000310 return rc
311
Martin v. Löwis787354c2003-01-25 15:28:29 +0000312def _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000313 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000314 if node.nodeType == Node.ELEMENT_NODE:
Martin v. Löwised525fb2001-06-03 14:06:42 +0000315 if ((localName == "*" or node.localName == localName) and
Fred Drake1f549022000-09-24 05:21:58 +0000316 (nsURI == "*" or node.namespaceURI == nsURI)):
317 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000318 _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000319 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000320
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000321class DocumentFragment(Node):
322 nodeType = Node.DOCUMENT_FRAGMENT_NODE
323 nodeName = "#document-fragment"
324 nodeValue = None
325 attributes = None
326 parentNode = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000327 _child_node_types = (Node.ELEMENT_NODE,
328 Node.TEXT_NODE,
329 Node.CDATA_SECTION_NODE,
330 Node.ENTITY_REFERENCE_NODE,
331 Node.PROCESSING_INSTRUCTION_NODE,
332 Node.COMMENT_NODE,
333 Node.NOTATION_NODE)
334
335 def __init__(self):
336 self.childNodes = NodeList()
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000337
338
Fred Drake55c38192000-06-29 19:39:57 +0000339class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000340 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000341 attributes = None
342 ownerElement = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000343 specified = False
344 _is_id = False
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000345
Martin v. Löwis787354c2003-01-25 15:28:29 +0000346 _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
347
348 def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
349 prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000350 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000351 d = self.__dict__
Fred Drake4ccf4a12000-11-21 22:02:22 +0000352 d["nodeName"] = d["name"] = qName
353 d["namespaceURI"] = namespaceURI
354 d["prefix"] = prefix
Martin v. Löwis787354c2003-01-25 15:28:29 +0000355 d['childNodes'] = NodeList()
356
357 # Add the single child node that represents the value of the attr
358 self.childNodes.append(Text())
359
Paul Prescod73678da2000-07-01 04:58:47 +0000360 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000361
Martin v. Löwis787354c2003-01-25 15:28:29 +0000362 def _get_localName(self):
Alex Martelli0ee43512006-08-21 19:53:20 +0000363 if 'localName' in self.__dict__:
Guido van Rossum3e1f85e2007-07-27 18:03:11 +0000364 return self.__dict__['localName']
Martin v. Löwis787354c2003-01-25 15:28:29 +0000365 return self.nodeName.split(":", 1)[-1]
366
367 def _get_name(self):
368 return self.name
369
370 def _get_specified(self):
371 return self.specified
372
Fred Drake1f549022000-09-24 05:21:58 +0000373 def __setattr__(self, name, value):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000374 d = self.__dict__
Fred Drake1f549022000-09-24 05:21:58 +0000375 if name in ("value", "nodeValue"):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000376 d["value"] = d["nodeValue"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000377 d2 = self.childNodes[0].__dict__
378 d2["data"] = d2["nodeValue"] = value
379 if self.ownerElement is not None:
380 _clear_id_cache(self.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000381 elif name in ("name", "nodeName"):
382 d["name"] = d["nodeName"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000383 if self.ownerElement is not None:
384 _clear_id_cache(self.ownerElement)
Fred Drake55c38192000-06-29 19:39:57 +0000385 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000386 d[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000387
Martin v. Löwis995359c2003-01-26 08:59:32 +0000388 def _set_prefix(self, prefix):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000389 nsuri = self.namespaceURI
Martin v. Löwis995359c2003-01-26 08:59:32 +0000390 if prefix == "xmlns":
391 if nsuri and nsuri != XMLNS_NAMESPACE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000392 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000393 "illegal use of 'xmlns' prefix for the wrong namespace")
394 d = self.__dict__
395 d['prefix'] = prefix
396 if prefix is None:
397 newName = self.localName
398 else:
Martin v. Löwis995359c2003-01-26 08:59:32 +0000399 newName = "%s:%s" % (prefix, self.localName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000400 if self.ownerElement:
401 _clear_id_cache(self.ownerElement)
402 d['nodeName'] = d['name'] = newName
403
404 def _set_value(self, value):
405 d = self.__dict__
406 d['value'] = d['nodeValue'] = value
407 if self.ownerElement:
408 _clear_id_cache(self.ownerElement)
409 self.childNodes[0].data = value
410
411 def unlink(self):
412 # This implementation does not call the base implementation
413 # since most of that is not needed, and the expense of the
414 # method call is not warranted. We duplicate the removal of
415 # children, but that's all we needed from the base class.
416 elem = self.ownerElement
417 if elem is not None:
418 del elem._attrs[self.nodeName]
419 del elem._attrsNS[(self.namespaceURI, self.localName)]
420 if self._is_id:
421 self._is_id = False
422 elem._magic_id_nodes -= 1
423 self.ownerDocument._magic_id_count -= 1
424 for child in self.childNodes:
425 child.unlink()
426 del self.childNodes[:]
427
428 def _get_isId(self):
429 if self._is_id:
430 return True
431 doc = self.ownerDocument
432 elem = self.ownerElement
433 if doc is None or elem is None:
434 return False
435
436 info = doc._get_elem_info(elem)
437 if info is None:
438 return False
439 if self.namespaceURI:
440 return info.isIdNS(self.namespaceURI, self.localName)
441 else:
442 return info.isId(self.nodeName)
443
444 def _get_schemaType(self):
445 doc = self.ownerDocument
446 elem = self.ownerElement
447 if doc is None or elem is None:
448 return _no_type
449
450 info = doc._get_elem_info(elem)
451 if info is None:
452 return _no_type
453 if self.namespaceURI:
454 return info.getAttributeTypeNS(self.namespaceURI, self.localName)
455 else:
456 return info.getAttributeType(self.nodeName)
457
458defproperty(Attr, "isId", doc="True if this attribute is an ID.")
459defproperty(Attr, "localName", doc="Namespace-local name of this attribute.")
460defproperty(Attr, "schemaType", doc="Schema type for this attribute.")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000461
Fred Drakef7cf40d2000-12-14 18:16:11 +0000462
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000463class NamedNodeMap(object):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000464 """The attribute list is a transient interface to the underlying
465 dictionaries. Mutations here will change the underlying element's
Fred Drakef7cf40d2000-12-14 18:16:11 +0000466 dictionary.
467
468 Ordering is imposed artificially and does not reflect the order of
469 attributes as found in an input document.
470 """
Fred Drake4ccf4a12000-11-21 22:02:22 +0000471
Martin v. Löwis787354c2003-01-25 15:28:29 +0000472 __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
473
Fred Drake2998a552001-12-06 18:27:48 +0000474 def __init__(self, attrs, attrsNS, ownerElement):
Fred Drake1f549022000-09-24 05:21:58 +0000475 self._attrs = attrs
476 self._attrsNS = attrsNS
Fred Drake2998a552001-12-06 18:27:48 +0000477 self._ownerElement = ownerElement
Fred Drakef7cf40d2000-12-14 18:16:11 +0000478
Martin v. Löwis787354c2003-01-25 15:28:29 +0000479 def _get_length(self):
480 return len(self._attrs)
Fred Drake55c38192000-06-29 19:39:57 +0000481
Fred Drake1f549022000-09-24 05:21:58 +0000482 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000483 try:
Brett Cannon861fd6f2007-02-21 22:05:37 +0000484 return self[list(self._attrs.keys())[index]]
Fred Drake55c38192000-06-29 19:39:57 +0000485 except IndexError:
486 return None
Fred Drake55c38192000-06-29 19:39:57 +0000487
Fred Drake1f549022000-09-24 05:21:58 +0000488 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000489 L = []
490 for node in self._attrs.values():
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000491 L.append((node.nodeName, node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000492 return L
Fred Drake1f549022000-09-24 05:21:58 +0000493
494 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000495 L = []
496 for node in self._attrs.values():
Fred Drake49a5d032001-11-30 22:21:58 +0000497 L.append(((node.namespaceURI, node.localName), node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000498 return L
Fred Drake16f63292000-10-23 18:09:50 +0000499
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000500 def __contains__(self, key):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000501 if isinstance(key, StringTypes):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000502 return key in self._attrs
Martin v. Löwis787354c2003-01-25 15:28:29 +0000503 else:
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000504 return key in self._attrsNS
Martin v. Löwis787354c2003-01-25 15:28:29 +0000505
Fred Drake1f549022000-09-24 05:21:58 +0000506 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000507 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000508
Fred Drake1f549022000-09-24 05:21:58 +0000509 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000510 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000511
Fred Drake1f549022000-09-24 05:21:58 +0000512 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000513 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000514
Martin v. Löwis787354c2003-01-25 15:28:29 +0000515 def get(self, name, value=None):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000516 return self._attrs.get(name, value)
517
Martin v. Löwis787354c2003-01-25 15:28:29 +0000518 __len__ = _get_length
Fred Drake55c38192000-06-29 19:39:57 +0000519
Fred Drake1f549022000-09-24 05:21:58 +0000520 def __cmp__(self, other):
521 if self._attrs is getattr(other, "_attrs", None):
Fred Drake55c38192000-06-29 19:39:57 +0000522 return 0
Fred Drake16f63292000-10-23 18:09:50 +0000523 else:
Fred Drake1f549022000-09-24 05:21:58 +0000524 return cmp(id(self), id(other))
Fred Drake55c38192000-06-29 19:39:57 +0000525
Fred Drake1f549022000-09-24 05:21:58 +0000526 def __getitem__(self, attname_or_tuple):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000527 if isinstance(attname_or_tuple, tuple):
Paul Prescod73678da2000-07-01 04:58:47 +0000528 return self._attrsNS[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000529 else:
Paul Prescod73678da2000-07-01 04:58:47 +0000530 return self._attrs[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000531
Paul Prescod1e688272000-07-01 19:21:47 +0000532 # same as set
Fred Drake1f549022000-09-24 05:21:58 +0000533 def __setitem__(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000534 if isinstance(value, StringTypes):
535 try:
536 node = self._attrs[attname]
537 except KeyError:
538 node = Attr(attname)
539 node.ownerDocument = self._ownerElement.ownerDocument
Martin v. Löwis995359c2003-01-26 08:59:32 +0000540 self.setNamedItem(node)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000541 node.value = value
Paul Prescod1e688272000-07-01 19:21:47 +0000542 else:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000543 if not isinstance(value, Attr):
Collin Winter70e79802007-08-24 18:57:22 +0000544 raise TypeError("value must be a string or Attr object")
Fred Drake1f549022000-09-24 05:21:58 +0000545 node = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000546 self.setNamedItem(node)
547
548 def getNamedItem(self, name):
549 try:
550 return self._attrs[name]
551 except KeyError:
552 return None
553
554 def getNamedItemNS(self, namespaceURI, localName):
555 try:
556 return self._attrsNS[(namespaceURI, localName)]
557 except KeyError:
558 return None
559
560 def removeNamedItem(self, name):
561 n = self.getNamedItem(name)
562 if n is not None:
563 _clear_id_cache(self._ownerElement)
564 del self._attrs[n.nodeName]
565 del self._attrsNS[(n.namespaceURI, n.localName)]
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000566 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000567 n.__dict__['ownerElement'] = None
568 return n
569 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000570 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000571
572 def removeNamedItemNS(self, namespaceURI, localName):
573 n = self.getNamedItemNS(namespaceURI, localName)
574 if n is not None:
575 _clear_id_cache(self._ownerElement)
576 del self._attrsNS[(n.namespaceURI, n.localName)]
577 del self._attrs[n.nodeName]
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000578 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000579 n.__dict__['ownerElement'] = None
580 return n
581 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000582 raise xml.dom.NotFoundErr()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000583
584 def setNamedItem(self, node):
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000585 if not isinstance(node, Attr):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000586 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000587 "%s cannot be child of %s" % (repr(node), repr(self)))
Fred Drakef7cf40d2000-12-14 18:16:11 +0000588 old = self._attrs.get(node.name)
Paul Prescod1e688272000-07-01 19:21:47 +0000589 if old:
590 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000591 self._attrs[node.name] = node
592 self._attrsNS[(node.namespaceURI, node.localName)] = node
Fred Drake2998a552001-12-06 18:27:48 +0000593 node.ownerElement = self._ownerElement
Martin v. Löwis787354c2003-01-25 15:28:29 +0000594 _clear_id_cache(node.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000595 return old
596
597 def setNamedItemNS(self, node):
598 return self.setNamedItem(node)
Paul Prescod73678da2000-07-01 04:58:47 +0000599
Fred Drake1f549022000-09-24 05:21:58 +0000600 def __delitem__(self, attname_or_tuple):
601 node = self[attname_or_tuple]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000602 _clear_id_cache(node.ownerElement)
Paul Prescod73678da2000-07-01 04:58:47 +0000603 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000604
605 def __getstate__(self):
606 return self._attrs, self._attrsNS, self._ownerElement
607
608 def __setstate__(self, state):
609 self._attrs, self._attrsNS, self._ownerElement = state
610
611defproperty(NamedNodeMap, "length",
612 doc="Number of nodes in the NamedNodeMap.")
Fred Drakef7cf40d2000-12-14 18:16:11 +0000613
614AttributeList = NamedNodeMap
615
Fred Drake1f549022000-09-24 05:21:58 +0000616
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000617class TypeInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000618 __slots__ = 'namespace', 'name'
619
620 def __init__(self, namespace, name):
621 self.namespace = namespace
622 self.name = name
623
624 def __repr__(self):
625 if self.namespace:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000626 return "<TypeInfo %r (from %r)>" % (self.name, self.namespace)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000627 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000628 return "<TypeInfo %r>" % self.name
Martin v. Löwis787354c2003-01-25 15:28:29 +0000629
630 def _get_name(self):
631 return self.name
632
633 def _get_namespace(self):
634 return self.namespace
635
636_no_type = TypeInfo(None, None)
637
Martin v. Löwisa2fda0d2000-10-07 12:10:28 +0000638class Element(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000639 nodeType = Node.ELEMENT_NODE
Martin v. Löwis787354c2003-01-25 15:28:29 +0000640 nodeValue = None
641 schemaType = _no_type
642
643 _magic_id_nodes = 0
644
645 _child_node_types = (Node.ELEMENT_NODE,
646 Node.PROCESSING_INSTRUCTION_NODE,
647 Node.COMMENT_NODE,
648 Node.TEXT_NODE,
649 Node.CDATA_SECTION_NODE,
650 Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000651
Fred Drake49a5d032001-11-30 22:21:58 +0000652 def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
Fred Drake1f549022000-09-24 05:21:58 +0000653 localName=None):
Fred Drake55c38192000-06-29 19:39:57 +0000654 self.tagName = self.nodeName = tagName
Fred Drake1f549022000-09-24 05:21:58 +0000655 self.prefix = prefix
656 self.namespaceURI = namespaceURI
Martin v. Löwis787354c2003-01-25 15:28:29 +0000657 self.childNodes = NodeList()
Fred Drake55c38192000-06-29 19:39:57 +0000658
Fred Drake4ccf4a12000-11-21 22:02:22 +0000659 self._attrs = {} # attributes are double-indexed:
660 self._attrsNS = {} # tagName -> Attribute
661 # URI,localName -> Attribute
662 # in the future: consider lazy generation
663 # of attribute objects this is too tricky
664 # for now because of headaches with
665 # namespaces.
666
Martin v. Löwis787354c2003-01-25 15:28:29 +0000667 def _get_localName(self):
Alex Martelli0ee43512006-08-21 19:53:20 +0000668 if 'localName' in self.__dict__:
Guido van Rossum3e1f85e2007-07-27 18:03:11 +0000669 return self.__dict__['localName']
Martin v. Löwis787354c2003-01-25 15:28:29 +0000670 return self.tagName.split(":", 1)[-1]
671
672 def _get_tagName(self):
673 return self.tagName
Fred Drake4ccf4a12000-11-21 22:02:22 +0000674
675 def unlink(self):
Brett Cannon861fd6f2007-02-21 22:05:37 +0000676 for attr in list(self._attrs.values()):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000677 attr.unlink()
678 self._attrs = None
679 self._attrsNS = None
680 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000681
Fred Drake1f549022000-09-24 05:21:58 +0000682 def getAttribute(self, attname):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000683 try:
684 return self._attrs[attname].value
685 except KeyError:
686 return ""
Fred Drake55c38192000-06-29 19:39:57 +0000687
Fred Drake1f549022000-09-24 05:21:58 +0000688 def getAttributeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000689 try:
690 return self._attrsNS[(namespaceURI, localName)].value
691 except KeyError:
692 return ""
Fred Drake1f549022000-09-24 05:21:58 +0000693
694 def setAttribute(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000695 attr = self.getAttributeNode(attname)
696 if attr is None:
697 attr = Attr(attname)
698 # for performance
699 d = attr.__dict__
700 d["value"] = d["nodeValue"] = value
701 d["ownerDocument"] = self.ownerDocument
702 self.setAttributeNode(attr)
703 elif value != attr.value:
704 d = attr.__dict__
705 d["value"] = d["nodeValue"] = value
706 if attr.isId:
707 _clear_id_cache(self)
Fred Drake55c38192000-06-29 19:39:57 +0000708
Fred Drake1f549022000-09-24 05:21:58 +0000709 def setAttributeNS(self, namespaceURI, qualifiedName, value):
710 prefix, localname = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000711 attr = self.getAttributeNodeNS(namespaceURI, localname)
712 if attr is None:
713 # for performance
714 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
715 d = attr.__dict__
716 d["prefix"] = prefix
717 d["nodeName"] = qualifiedName
718 d["value"] = d["nodeValue"] = value
719 d["ownerDocument"] = self.ownerDocument
720 self.setAttributeNode(attr)
721 else:
722 d = attr.__dict__
723 if value != attr.value:
724 d["value"] = d["nodeValue"] = value
725 if attr.isId:
726 _clear_id_cache(self)
727 if attr.prefix != prefix:
728 d["prefix"] = prefix
729 d["nodeName"] = qualifiedName
Fred Drake55c38192000-06-29 19:39:57 +0000730
Fred Drake1f549022000-09-24 05:21:58 +0000731 def getAttributeNode(self, attrname):
732 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000733
Fred Drake1f549022000-09-24 05:21:58 +0000734 def getAttributeNodeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000735 return self._attrsNS.get((namespaceURI, localName))
Paul Prescod73678da2000-07-01 04:58:47 +0000736
Fred Drake1f549022000-09-24 05:21:58 +0000737 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000738 if attr.ownerElement not in (None, self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000739 raise xml.dom.InuseAttributeErr("attribute node already owned")
Martin v. Löwis787354c2003-01-25 15:28:29 +0000740 old1 = self._attrs.get(attr.name, None)
741 if old1 is not None:
742 self.removeAttributeNode(old1)
743 old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
744 if old2 is not None and old2 is not old1:
745 self.removeAttributeNode(old2)
746 _set_attribute_node(self, attr)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000747
Martin v. Löwis787354c2003-01-25 15:28:29 +0000748 if old1 is not attr:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000749 # It might have already been part of this node, in which case
750 # it doesn't represent a change, and should not be returned.
Martin v. Löwis787354c2003-01-25 15:28:29 +0000751 return old1
752 if old2 is not attr:
753 return old2
Fred Drake55c38192000-06-29 19:39:57 +0000754
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000755 setAttributeNodeNS = setAttributeNode
756
Fred Drake1f549022000-09-24 05:21:58 +0000757 def removeAttribute(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000758 try:
759 attr = self._attrs[name]
760 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000761 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000762 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000763
Fred Drake1f549022000-09-24 05:21:58 +0000764 def removeAttributeNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000765 try:
766 attr = self._attrsNS[(namespaceURI, localName)]
767 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000768 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000769 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000770
Fred Drake1f549022000-09-24 05:21:58 +0000771 def removeAttributeNode(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000772 if node is None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000773 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000774 try:
775 self._attrs[node.name]
776 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000777 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000778 _clear_id_cache(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000779 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000780 # Restore this since the node is still useful and otherwise
781 # unlinked
782 node.ownerDocument = self.ownerDocument
Fred Drake16f63292000-10-23 18:09:50 +0000783
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000784 removeAttributeNodeNS = removeAttributeNode
785
Martin v. Löwis156c3372000-12-28 18:40:56 +0000786 def hasAttribute(self, name):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000787 return name in self._attrs
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000788
Martin v. Löwis156c3372000-12-28 18:40:56 +0000789 def hasAttributeNS(self, namespaceURI, localName):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000790 return (namespaceURI, localName) in self._attrsNS
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000791
Fred Drake1f549022000-09-24 05:21:58 +0000792 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000793 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000794
Fred Drake1f549022000-09-24 05:21:58 +0000795 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000796 return _get_elements_by_tagName_ns_helper(
797 self, namespaceURI, localName, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000798
Fred Drake1f549022000-09-24 05:21:58 +0000799 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000800 return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000801
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000802 def writexml(self, writer, indent="", addindent="", newl=""):
803 # indent = current indentation
804 # addindent = indentation to add to higher levels
805 # newl = newline string
806 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000807
Fred Drake4ccf4a12000-11-21 22:02:22 +0000808 attrs = self._get_attributes()
Brett Cannon861fd6f2007-02-21 22:05:37 +0000809 a_names = sorted(attrs.keys())
Fred Drake55c38192000-06-29 19:39:57 +0000810
811 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000812 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000813 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000814 writer.write("\"")
815 if self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000816 writer.write(">%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000817 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000818 node.writexml(writer,indent+addindent,addindent,newl)
819 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
Fred Drake55c38192000-06-29 19:39:57 +0000820 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000821 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000822
Fred Drake1f549022000-09-24 05:21:58 +0000823 def _get_attributes(self):
Fred Drake2998a552001-12-06 18:27:48 +0000824 return NamedNodeMap(self._attrs, self._attrsNS, self)
Fred Drake55c38192000-06-29 19:39:57 +0000825
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000826 def hasAttributes(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000827 if self._attrs:
828 return True
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000829 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000830 return False
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000831
Martin v. Löwis787354c2003-01-25 15:28:29 +0000832 # DOM Level 3 attributes, based on the 22 Oct 2002 draft
833
834 def setIdAttribute(self, name):
835 idAttr = self.getAttributeNode(name)
836 self.setIdAttributeNode(idAttr)
837
838 def setIdAttributeNS(self, namespaceURI, localName):
839 idAttr = self.getAttributeNodeNS(namespaceURI, localName)
840 self.setIdAttributeNode(idAttr)
841
842 def setIdAttributeNode(self, idAttr):
843 if idAttr is None or not self.isSameNode(idAttr.ownerElement):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000844 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000845 if _get_containing_entref(self) is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000846 raise xml.dom.NoModificationAllowedErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000847 if not idAttr._is_id:
848 idAttr.__dict__['_is_id'] = True
849 self._magic_id_nodes += 1
850 self.ownerDocument._magic_id_count += 1
851 _clear_id_cache(self)
852
853defproperty(Element, "attributes",
854 doc="NamedNodeMap of attributes on the element.")
855defproperty(Element, "localName",
856 doc="Namespace-local name of this element.")
857
858
859def _set_attribute_node(element, attr):
860 _clear_id_cache(element)
861 element._attrs[attr.name] = attr
862 element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
863
864 # This creates a circular reference, but Element.unlink()
865 # breaks the cycle since the references to the attribute
866 # dictionaries are tossed.
867 attr.__dict__['ownerElement'] = element
868
869
870class Childless:
871 """Mixin that makes childless-ness easy to implement and avoids
872 the complexity of the Node methods that deal with children.
873 """
874
Fred Drake4ccf4a12000-11-21 22:02:22 +0000875 attributes = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000876 childNodes = EmptyNodeList()
877 firstChild = None
878 lastChild = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000879
Martin v. Löwis787354c2003-01-25 15:28:29 +0000880 def _get_firstChild(self):
881 return None
Fred Drake55c38192000-06-29 19:39:57 +0000882
Martin v. Löwis787354c2003-01-25 15:28:29 +0000883 def _get_lastChild(self):
884 return None
Fred Drake1f549022000-09-24 05:21:58 +0000885
Martin v. Löwis787354c2003-01-25 15:28:29 +0000886 def appendChild(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000887 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000888 self.nodeName + " nodes cannot have children")
889
890 def hasChildNodes(self):
891 return False
892
893 def insertBefore(self, newChild, refChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000894 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000895 self.nodeName + " nodes do not have children")
896
897 def removeChild(self, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000898 raise xml.dom.NotFoundErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000899 self.nodeName + " nodes do not have children")
900
901 def replaceChild(self, newChild, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000902 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000903 self.nodeName + " nodes do not have children")
904
905
906class ProcessingInstruction(Childless, Node):
Fred Drake1f549022000-09-24 05:21:58 +0000907 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000908
Fred Drake1f549022000-09-24 05:21:58 +0000909 def __init__(self, target, data):
Fred Drake55c38192000-06-29 19:39:57 +0000910 self.target = self.nodeName = target
911 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000912
Martin v. Löwis787354c2003-01-25 15:28:29 +0000913 def _get_data(self):
914 return self.data
915 def _set_data(self, value):
916 d = self.__dict__
917 d['data'] = d['nodeValue'] = value
918
919 def _get_target(self):
920 return self.target
921 def _set_target(self, value):
922 d = self.__dict__
923 d['target'] = d['nodeName'] = value
924
925 def __setattr__(self, name, value):
926 if name == "data" or name == "nodeValue":
927 self.__dict__['data'] = self.__dict__['nodeValue'] = value
928 elif name == "target" or name == "nodeName":
929 self.__dict__['target'] = self.__dict__['nodeName'] = value
930 else:
931 self.__dict__[name] = value
932
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000933 def writexml(self, writer, indent="", addindent="", newl=""):
934 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000935
Martin v. Löwis787354c2003-01-25 15:28:29 +0000936
937class CharacterData(Childless, Node):
938 def _get_length(self):
939 return len(self.data)
940 __len__ = _get_length
941
942 def _get_data(self):
943 return self.__dict__['data']
944 def _set_data(self, data):
945 d = self.__dict__
946 d['data'] = d['nodeValue'] = data
947
948 _get_nodeValue = _get_data
949 _set_nodeValue = _set_data
950
951 def __setattr__(self, name, value):
952 if name == "data" or name == "nodeValue":
953 self.__dict__['data'] = self.__dict__['nodeValue'] = value
954 else:
955 self.__dict__[name] = value
Fred Drake87432f42001-04-04 14:09:46 +0000956
Fred Drake55c38192000-06-29 19:39:57 +0000957 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000958 data = self.data
959 if len(data) > 10:
Fred Drake1f549022000-09-24 05:21:58 +0000960 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000961 else:
Fred Drake1f549022000-09-24 05:21:58 +0000962 dotdotdot = ""
Fred Drake87432f42001-04-04 14:09:46 +0000963 return "<DOM %s node \"%s%s\">" % (
Martin v. Löwis787354c2003-01-25 15:28:29 +0000964 self.__class__.__name__, data[0:10], dotdotdot)
Fred Drake87432f42001-04-04 14:09:46 +0000965
966 def substringData(self, offset, count):
967 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000968 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000969 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000970 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000971 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000972 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000973 return self.data[offset:offset+count]
974
975 def appendData(self, arg):
976 self.data = self.data + arg
Fred Drake87432f42001-04-04 14:09:46 +0000977
978 def insertData(self, offset, arg):
979 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000980 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000981 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000982 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000983 if arg:
984 self.data = "%s%s%s" % (
985 self.data[:offset], arg, self.data[offset:])
Fred Drake87432f42001-04-04 14:09:46 +0000986
987 def deleteData(self, offset, count):
988 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000989 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000990 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000991 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000992 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000993 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000994 if count:
995 self.data = self.data[:offset] + self.data[offset+count:]
Fred Drake87432f42001-04-04 14:09:46 +0000996
997 def replaceData(self, offset, count, arg):
998 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000999 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001000 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001001 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +00001002 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001003 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001004 if count:
1005 self.data = "%s%s%s" % (
1006 self.data[:offset], arg, self.data[offset+count:])
Martin v. Löwis787354c2003-01-25 15:28:29 +00001007
1008defproperty(CharacterData, "length", doc="Length of the string data.")
1009
Fred Drake87432f42001-04-04 14:09:46 +00001010
1011class Text(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001012 # Make sure we don't add an instance __dict__ if we don't already
1013 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001014 # XXX this does not work, CharacterData is an old-style class
1015 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001016
Fred Drake87432f42001-04-04 14:09:46 +00001017 nodeType = Node.TEXT_NODE
1018 nodeName = "#text"
1019 attributes = None
Fred Drake55c38192000-06-29 19:39:57 +00001020
Fred Drakef7cf40d2000-12-14 18:16:11 +00001021 def splitText(self, offset):
1022 if offset < 0 or offset > len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001023 raise xml.dom.IndexSizeErr("illegal offset value")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001024 newText = self.__class__()
1025 newText.data = self.data[offset:]
1026 newText.ownerDocument = self.ownerDocument
Fred Drakef7cf40d2000-12-14 18:16:11 +00001027 next = self.nextSibling
1028 if self.parentNode and self in self.parentNode.childNodes:
1029 if next is None:
1030 self.parentNode.appendChild(newText)
1031 else:
1032 self.parentNode.insertBefore(newText, next)
1033 self.data = self.data[:offset]
1034 return newText
1035
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001036 def writexml(self, writer, indent="", addindent="", newl=""):
1037 _write_data(writer, "%s%s%s"%(indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001038
Martin v. Löwis787354c2003-01-25 15:28:29 +00001039 # DOM Level 3 (WD 9 April 2002)
1040
1041 def _get_wholeText(self):
1042 L = [self.data]
1043 n = self.previousSibling
1044 while n is not None:
1045 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1046 L.insert(0, n.data)
1047 n = n.previousSibling
1048 else:
1049 break
1050 n = self.nextSibling
1051 while n is not None:
1052 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1053 L.append(n.data)
1054 n = n.nextSibling
1055 else:
1056 break
1057 return ''.join(L)
1058
1059 def replaceWholeText(self, content):
1060 # XXX This needs to be seriously changed if minidom ever
1061 # supports EntityReference nodes.
1062 parent = self.parentNode
1063 n = self.previousSibling
1064 while n is not None:
1065 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1066 next = n.previousSibling
1067 parent.removeChild(n)
1068 n = next
1069 else:
1070 break
1071 n = self.nextSibling
1072 if not content:
1073 parent.removeChild(self)
1074 while n is not None:
1075 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1076 next = n.nextSibling
1077 parent.removeChild(n)
1078 n = next
1079 else:
1080 break
1081 if content:
1082 d = self.__dict__
1083 d['data'] = content
1084 d['nodeValue'] = content
1085 return self
1086 else:
1087 return None
1088
1089 def _get_isWhitespaceInElementContent(self):
1090 if self.data.strip():
1091 return False
1092 elem = _get_containing_element(self)
1093 if elem is None:
1094 return False
1095 info = self.ownerDocument._get_elem_info(elem)
1096 if info is None:
1097 return False
1098 else:
1099 return info.isElementContent()
1100
1101defproperty(Text, "isWhitespaceInElementContent",
1102 doc="True iff this text node contains only whitespace"
1103 " and is in element content.")
1104defproperty(Text, "wholeText",
1105 doc="The text of all logically-adjacent text nodes.")
1106
1107
1108def _get_containing_element(node):
1109 c = node.parentNode
1110 while c is not None:
1111 if c.nodeType == Node.ELEMENT_NODE:
1112 return c
1113 c = c.parentNode
1114 return None
1115
1116def _get_containing_entref(node):
1117 c = node.parentNode
1118 while c is not None:
1119 if c.nodeType == Node.ENTITY_REFERENCE_NODE:
1120 return c
1121 c = c.parentNode
1122 return None
1123
1124
Alex Martelli0ee43512006-08-21 19:53:20 +00001125class Comment(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001126 nodeType = Node.COMMENT_NODE
1127 nodeName = "#comment"
1128
1129 def __init__(self, data):
1130 self.data = self.nodeValue = data
1131
1132 def writexml(self, writer, indent="", addindent="", newl=""):
1133 writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
1134
Fred Drake87432f42001-04-04 14:09:46 +00001135
1136class CDATASection(Text):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001137 # Make sure we don't add an instance __dict__ if we don't already
1138 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001139 # XXX this does not work, Text is an old-style class
1140 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001141
Fred Drake87432f42001-04-04 14:09:46 +00001142 nodeType = Node.CDATA_SECTION_NODE
1143 nodeName = "#cdata-section"
1144
1145 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001146 if self.data.find("]]>") >= 0:
1147 raise ValueError("']]>' not allowed in a CDATA section")
Guido van Rossum5b5e0b92001-09-19 13:28:25 +00001148 writer.write("<![CDATA[%s]]>" % self.data)
Fred Drake87432f42001-04-04 14:09:46 +00001149
1150
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001151class ReadOnlySequentialNamedNodeMap(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001152 __slots__ = '_seq',
1153
1154 def __init__(self, seq=()):
1155 # seq should be a list or tuple
1156 self._seq = seq
1157
1158 def __len__(self):
1159 return len(self._seq)
1160
1161 def _get_length(self):
1162 return len(self._seq)
1163
1164 def getNamedItem(self, name):
1165 for n in self._seq:
1166 if n.nodeName == name:
1167 return n
1168
1169 def getNamedItemNS(self, namespaceURI, localName):
1170 for n in self._seq:
1171 if n.namespaceURI == namespaceURI and n.localName == localName:
1172 return n
1173
1174 def __getitem__(self, name_or_tuple):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001175 if isinstance(name_or_tuple, tuple):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001176 node = self.getNamedItemNS(*name_or_tuple)
1177 else:
1178 node = self.getNamedItem(name_or_tuple)
1179 if node is None:
Collin Winter70e79802007-08-24 18:57:22 +00001180 raise KeyError(name_or_tuple)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001181 return node
1182
1183 def item(self, index):
1184 if index < 0:
1185 return None
1186 try:
1187 return self._seq[index]
1188 except IndexError:
1189 return None
1190
1191 def removeNamedItem(self, name):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001192 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001193 "NamedNodeMap instance is read-only")
1194
1195 def removeNamedItemNS(self, namespaceURI, localName):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001196 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001197 "NamedNodeMap instance is read-only")
1198
1199 def setNamedItem(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001200 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001201 "NamedNodeMap instance is read-only")
1202
1203 def setNamedItemNS(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001204 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001205 "NamedNodeMap instance is read-only")
1206
1207 def __getstate__(self):
1208 return [self._seq]
1209
1210 def __setstate__(self, state):
1211 self._seq = state[0]
1212
1213defproperty(ReadOnlySequentialNamedNodeMap, "length",
1214 doc="Number of entries in the NamedNodeMap.")
Paul Prescod73678da2000-07-01 04:58:47 +00001215
Fred Drakef7cf40d2000-12-14 18:16:11 +00001216
Martin v. Löwis787354c2003-01-25 15:28:29 +00001217class Identified:
1218 """Mix-in class that supports the publicId and systemId attributes."""
1219
Martin v. Löwis995359c2003-01-26 08:59:32 +00001220 # XXX this does not work, this is an old-style class
1221 # __slots__ = 'publicId', 'systemId'
Martin v. Löwis787354c2003-01-25 15:28:29 +00001222
1223 def _identified_mixin_init(self, publicId, systemId):
1224 self.publicId = publicId
1225 self.systemId = systemId
1226
1227 def _get_publicId(self):
1228 return self.publicId
1229
1230 def _get_systemId(self):
1231 return self.systemId
1232
1233class DocumentType(Identified, Childless, Node):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001234 nodeType = Node.DOCUMENT_TYPE_NODE
1235 nodeValue = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001236 name = None
1237 publicId = None
1238 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +00001239 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001240
1241 def __init__(self, qualifiedName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001242 self.entities = ReadOnlySequentialNamedNodeMap()
1243 self.notations = ReadOnlySequentialNamedNodeMap()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001244 if qualifiedName:
1245 prefix, localname = _nssplit(qualifiedName)
1246 self.name = localname
Martin v. Löwis787354c2003-01-25 15:28:29 +00001247 self.nodeName = self.name
1248
1249 def _get_internalSubset(self):
1250 return self.internalSubset
1251
1252 def cloneNode(self, deep):
1253 if self.ownerDocument is None:
1254 # it's ok
1255 clone = DocumentType(None)
1256 clone.name = self.name
1257 clone.nodeName = self.name
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001258 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001259 if deep:
1260 clone.entities._seq = []
1261 clone.notations._seq = []
1262 for n in self.notations._seq:
1263 notation = Notation(n.nodeName, n.publicId, n.systemId)
1264 clone.notations._seq.append(notation)
1265 n._call_user_data_handler(operation, n, notation)
1266 for e in self.entities._seq:
1267 entity = Entity(e.nodeName, e.publicId, e.systemId,
1268 e.notationName)
1269 entity.actualEncoding = e.actualEncoding
1270 entity.encoding = e.encoding
1271 entity.version = e.version
1272 clone.entities._seq.append(entity)
1273 e._call_user_data_handler(operation, n, entity)
1274 self._call_user_data_handler(operation, self, clone)
1275 return clone
1276 else:
1277 return None
1278
1279 def writexml(self, writer, indent="", addindent="", newl=""):
1280 writer.write("<!DOCTYPE ")
1281 writer.write(self.name)
1282 if self.publicId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001283 writer.write("%s PUBLIC '%s'%s '%s'"
1284 % (newl, self.publicId, newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001285 elif self.systemId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001286 writer.write("%s SYSTEM '%s'" % (newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001287 if self.internalSubset is not None:
1288 writer.write(" [")
1289 writer.write(self.internalSubset)
1290 writer.write("]")
Georg Brandl175a7dc2005-08-25 22:02:43 +00001291 writer.write(">"+newl)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001292
1293class Entity(Identified, Node):
1294 attributes = None
1295 nodeType = Node.ENTITY_NODE
1296 nodeValue = None
1297
1298 actualEncoding = None
1299 encoding = None
1300 version = None
1301
1302 def __init__(self, name, publicId, systemId, notation):
1303 self.nodeName = name
1304 self.notationName = notation
1305 self.childNodes = NodeList()
1306 self._identified_mixin_init(publicId, systemId)
1307
1308 def _get_actualEncoding(self):
1309 return self.actualEncoding
1310
1311 def _get_encoding(self):
1312 return self.encoding
1313
1314 def _get_version(self):
1315 return self.version
1316
1317 def appendChild(self, newChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001318 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001319 "cannot append children to an entity node")
1320
1321 def insertBefore(self, newChild, refChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001322 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001323 "cannot insert children below an entity node")
1324
1325 def removeChild(self, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001326 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001327 "cannot remove children from an entity node")
1328
1329 def replaceChild(self, newChild, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001330 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001331 "cannot replace children of an entity node")
1332
1333class Notation(Identified, Childless, Node):
1334 nodeType = Node.NOTATION_NODE
1335 nodeValue = None
1336
1337 def __init__(self, name, publicId, systemId):
1338 self.nodeName = name
1339 self._identified_mixin_init(publicId, systemId)
Fred Drakef7cf40d2000-12-14 18:16:11 +00001340
1341
Martin v. Löwis787354c2003-01-25 15:28:29 +00001342class DOMImplementation(DOMImplementationLS):
1343 _features = [("core", "1.0"),
1344 ("core", "2.0"),
1345 ("core", "3.0"),
1346 ("core", None),
1347 ("xml", "1.0"),
1348 ("xml", "2.0"),
1349 ("xml", "3.0"),
1350 ("xml", None),
1351 ("ls-load", "3.0"),
1352 ("ls-load", None),
1353 ]
1354
Fred Drakef7cf40d2000-12-14 18:16:11 +00001355 def hasFeature(self, feature, version):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001356 if version == "":
1357 version = None
1358 return (feature.lower(), version) in self._features
Fred Drakef7cf40d2000-12-14 18:16:11 +00001359
1360 def createDocument(self, namespaceURI, qualifiedName, doctype):
1361 if doctype and doctype.parentNode is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001362 raise xml.dom.WrongDocumentErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001363 "doctype object owned by another DOM tree")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001364 doc = self._create_document()
1365
1366 add_root_element = not (namespaceURI is None
1367 and qualifiedName is None
1368 and doctype is None)
1369
1370 if not qualifiedName and add_root_element:
Martin v. Löwisb417be22001-02-06 01:16:06 +00001371 # The spec is unclear what to raise here; SyntaxErr
1372 # would be the other obvious candidate. Since Xerces raises
1373 # InvalidCharacterErr, and since SyntaxErr is not listed
1374 # for createDocument, that seems to be the better choice.
1375 # XXX: need to check for illegal characters here and in
1376 # createElement.
Martin v. Löwis787354c2003-01-25 15:28:29 +00001377
1378 # DOM Level III clears this up when talking about the return value
1379 # of this function. If namespaceURI, qName and DocType are
1380 # Null the document is returned without a document element
1381 # Otherwise if doctype or namespaceURI are not None
1382 # Then we go back to the above problem
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001383 raise xml.dom.InvalidCharacterErr("Element with no name")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001384
1385 if add_root_element:
1386 prefix, localname = _nssplit(qualifiedName)
1387 if prefix == "xml" \
1388 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001389 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001390 if prefix and not namespaceURI:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001391 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001392 "illegal use of prefix without namespaces")
1393 element = doc.createElementNS(namespaceURI, qualifiedName)
1394 if doctype:
1395 doc.appendChild(doctype)
1396 doc.appendChild(element)
1397
1398 if doctype:
1399 doctype.parentNode = doctype.ownerDocument = doc
1400
Fred Drakef7cf40d2000-12-14 18:16:11 +00001401 doc.doctype = doctype
1402 doc.implementation = self
1403 return doc
1404
1405 def createDocumentType(self, qualifiedName, publicId, systemId):
1406 doctype = DocumentType(qualifiedName)
1407 doctype.publicId = publicId
1408 doctype.systemId = systemId
1409 return doctype
1410
Martin v. Löwis787354c2003-01-25 15:28:29 +00001411 # DOM Level 3 (WD 9 April 2002)
1412
1413 def getInterface(self, feature):
1414 if self.hasFeature(feature, None):
1415 return self
1416 else:
1417 return None
1418
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001419 # internal
Martin v. Löwis787354c2003-01-25 15:28:29 +00001420 def _create_document(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001421 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001422
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001423class ElementInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001424 """Object that represents content-model information for an element.
1425
1426 This implementation is not expected to be used in practice; DOM
1427 builders should provide implementations which do the right thing
1428 using information available to it.
1429
1430 """
1431
1432 __slots__ = 'tagName',
1433
1434 def __init__(self, name):
1435 self.tagName = name
1436
1437 def getAttributeType(self, aname):
1438 return _no_type
1439
1440 def getAttributeTypeNS(self, namespaceURI, localName):
1441 return _no_type
1442
1443 def isElementContent(self):
1444 return False
1445
1446 def isEmpty(self):
1447 """Returns true iff this element is declared to have an EMPTY
1448 content model."""
1449 return False
1450
1451 def isId(self, aname):
1452 """Returns true iff the named attribte is a DTD-style ID."""
1453 return False
1454
1455 def isIdNS(self, namespaceURI, localName):
1456 """Returns true iff the identified attribute is a DTD-style ID."""
1457 return False
1458
1459 def __getstate__(self):
1460 return self.tagName
1461
1462 def __setstate__(self, state):
1463 self.tagName = state
1464
1465def _clear_id_cache(node):
1466 if node.nodeType == Node.DOCUMENT_NODE:
1467 node._id_cache.clear()
1468 node._id_search_stack = None
1469 elif _in_document(node):
1470 node.ownerDocument._id_cache.clear()
1471 node.ownerDocument._id_search_stack= None
1472
1473class Document(Node, DocumentLS):
1474 _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
1475 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
1476
Fred Drake1f549022000-09-24 05:21:58 +00001477 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +00001478 nodeName = "#document"
1479 nodeValue = None
1480 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001481 doctype = None
1482 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001483 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001484
1485 implementation = DOMImplementation()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001486
1487 # Document attributes from Level 3 (WD 9 April 2002)
1488
1489 actualEncoding = None
1490 encoding = None
1491 standalone = None
1492 version = None
1493 strictErrorChecking = False
1494 errorHandler = None
1495 documentURI = None
1496
1497 _magic_id_count = 0
1498
1499 def __init__(self):
1500 self.childNodes = NodeList()
1501 # mapping of (namespaceURI, localName) -> ElementInfo
1502 # and tagName -> ElementInfo
1503 self._elem_info = {}
1504 self._id_cache = {}
1505 self._id_search_stack = None
1506
1507 def _get_elem_info(self, element):
1508 if element.namespaceURI:
1509 key = element.namespaceURI, element.localName
1510 else:
1511 key = element.tagName
1512 return self._elem_info.get(key)
1513
1514 def _get_actualEncoding(self):
1515 return self.actualEncoding
1516
1517 def _get_doctype(self):
1518 return self.doctype
1519
1520 def _get_documentURI(self):
1521 return self.documentURI
1522
1523 def _get_encoding(self):
1524 return self.encoding
1525
1526 def _get_errorHandler(self):
1527 return self.errorHandler
1528
1529 def _get_standalone(self):
1530 return self.standalone
1531
1532 def _get_strictErrorChecking(self):
1533 return self.strictErrorChecking
1534
1535 def _get_version(self):
1536 return self.version
Fred Drake55c38192000-06-29 19:39:57 +00001537
Fred Drake1f549022000-09-24 05:21:58 +00001538 def appendChild(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001539 if node.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001540 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001541 "%s cannot be child of %s" % (repr(node), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001542 if node.parentNode is not None:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001543 # This needs to be done before the next test since this
1544 # may *be* the document element, in which case it should
1545 # end up re-ordered to the end.
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001546 node.parentNode.removeChild(node)
1547
Fred Drakef7cf40d2000-12-14 18:16:11 +00001548 if node.nodeType == Node.ELEMENT_NODE \
1549 and self._get_documentElement():
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001550 raise xml.dom.HierarchyRequestErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001551 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +00001552 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +00001553
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001554 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001555 try:
1556 self.childNodes.remove(oldChild)
1557 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001558 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001559 oldChild.nextSibling = oldChild.previousSibling = None
1560 oldChild.parentNode = None
1561 if self.documentElement is oldChild:
1562 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +00001563
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001564 return oldChild
1565
Fred Drakef7cf40d2000-12-14 18:16:11 +00001566 def _get_documentElement(self):
1567 for node in self.childNodes:
1568 if node.nodeType == Node.ELEMENT_NODE:
1569 return node
1570
1571 def unlink(self):
1572 if self.doctype is not None:
1573 self.doctype.unlink()
1574 self.doctype = None
1575 Node.unlink(self)
1576
Martin v. Löwis787354c2003-01-25 15:28:29 +00001577 def cloneNode(self, deep):
1578 if not deep:
1579 return None
1580 clone = self.implementation.createDocument(None, None, None)
1581 clone.encoding = self.encoding
1582 clone.standalone = self.standalone
1583 clone.version = self.version
1584 for n in self.childNodes:
1585 childclone = _clone_node(n, deep, clone)
1586 assert childclone.ownerDocument.isSameNode(clone)
1587 clone.childNodes.append(childclone)
1588 if childclone.nodeType == Node.DOCUMENT_NODE:
1589 assert clone.documentElement is None
1590 elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
1591 assert clone.doctype is None
1592 clone.doctype = childclone
1593 childclone.parentNode = clone
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001594 self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
Martin v. Löwis787354c2003-01-25 15:28:29 +00001595 self, clone)
1596 return clone
1597
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001598 def createDocumentFragment(self):
1599 d = DocumentFragment()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001600 d.ownerDocument = self
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001601 return d
Fred Drake55c38192000-06-29 19:39:57 +00001602
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001603 def createElement(self, tagName):
1604 e = Element(tagName)
1605 e.ownerDocument = self
1606 return e
Fred Drake55c38192000-06-29 19:39:57 +00001607
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001608 def createTextNode(self, data):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001609 if not isinstance(data, StringTypes):
Collin Winter70e79802007-08-24 18:57:22 +00001610 raise TypeError("node contents must be a string")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001611 t = Text()
1612 t.data = data
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001613 t.ownerDocument = self
1614 return t
Fred Drake55c38192000-06-29 19:39:57 +00001615
Fred Drake87432f42001-04-04 14:09:46 +00001616 def createCDATASection(self, data):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001617 if not isinstance(data, StringTypes):
Collin Winter70e79802007-08-24 18:57:22 +00001618 raise TypeError("node contents must be a string")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001619 c = CDATASection()
1620 c.data = data
Fred Drake87432f42001-04-04 14:09:46 +00001621 c.ownerDocument = self
1622 return c
1623
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001624 def createComment(self, data):
1625 c = Comment(data)
1626 c.ownerDocument = self
1627 return c
Fred Drake55c38192000-06-29 19:39:57 +00001628
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001629 def createProcessingInstruction(self, target, data):
1630 p = ProcessingInstruction(target, data)
1631 p.ownerDocument = self
1632 return p
1633
1634 def createAttribute(self, qName):
1635 a = Attr(qName)
1636 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001637 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001638 return a
Fred Drake55c38192000-06-29 19:39:57 +00001639
1640 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001641 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001642 e = Element(qualifiedName, namespaceURI, prefix)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001643 e.ownerDocument = self
1644 return e
Fred Drake55c38192000-06-29 19:39:57 +00001645
1646 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001647 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001648 a = Attr(qualifiedName, namespaceURI, localName, prefix)
1649 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001650 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001651 return a
Fred Drake55c38192000-06-29 19:39:57 +00001652
Martin v. Löwis787354c2003-01-25 15:28:29 +00001653 # A couple of implementation-specific helpers to create node types
1654 # not supported by the W3C DOM specs:
1655
1656 def _create_entity(self, name, publicId, systemId, notationName):
1657 e = Entity(name, publicId, systemId, notationName)
1658 e.ownerDocument = self
1659 return e
1660
1661 def _create_notation(self, name, publicId, systemId):
1662 n = Notation(name, publicId, systemId)
1663 n.ownerDocument = self
1664 return n
1665
1666 def getElementById(self, id):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +00001667 if id in self._id_cache:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001668 return self._id_cache[id]
1669 if not (self._elem_info or self._magic_id_count):
1670 return None
1671
1672 stack = self._id_search_stack
1673 if stack is None:
1674 # we never searched before, or the cache has been cleared
1675 stack = [self.documentElement]
1676 self._id_search_stack = stack
1677 elif not stack:
1678 # Previous search was completed and cache is still valid;
1679 # no matching node.
1680 return None
1681
1682 result = None
1683 while stack:
1684 node = stack.pop()
1685 # add child elements to stack for continued searching
1686 stack.extend([child for child in node.childNodes
1687 if child.nodeType in _nodeTypes_with_children])
1688 # check this node
1689 info = self._get_elem_info(node)
1690 if info:
1691 # We have to process all ID attributes before
1692 # returning in order to get all the attributes set to
1693 # be IDs using Element.setIdAttribute*().
1694 for attr in node.attributes.values():
1695 if attr.namespaceURI:
1696 if info.isIdNS(attr.namespaceURI, attr.localName):
1697 self._id_cache[attr.value] = node
1698 if attr.value == id:
1699 result = node
1700 elif not node._magic_id_nodes:
1701 break
1702 elif info.isId(attr.name):
1703 self._id_cache[attr.value] = node
1704 if attr.value == id:
1705 result = node
1706 elif not node._magic_id_nodes:
1707 break
1708 elif attr._is_id:
1709 self._id_cache[attr.value] = node
1710 if attr.value == id:
1711 result = node
1712 elif node._magic_id_nodes == 1:
1713 break
1714 elif node._magic_id_nodes:
1715 for attr in node.attributes.values():
1716 if attr._is_id:
1717 self._id_cache[attr.value] = node
1718 if attr.value == id:
1719 result = node
1720 if result is not None:
1721 break
1722 return result
1723
Fred Drake1f549022000-09-24 05:21:58 +00001724 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001725 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drakefbe7b4f2001-07-04 06:25:53 +00001726
1727 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001728 return _get_elements_by_tagName_ns_helper(
1729 self, namespaceURI, localName, NodeList())
1730
1731 def isSupported(self, feature, version):
1732 return self.implementation.hasFeature(feature, version)
1733
1734 def importNode(self, node, deep):
1735 if node.nodeType == Node.DOCUMENT_NODE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001736 raise xml.dom.NotSupportedErr("cannot import document nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001737 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001738 raise xml.dom.NotSupportedErr("cannot import document type nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001739 return _clone_node(node, deep, self)
Fred Drake55c38192000-06-29 19:39:57 +00001740
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001741 def writexml(self, writer, indent="", addindent="", newl="",
1742 encoding = None):
1743 if encoding is None:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001744 writer.write('<?xml version="1.0" ?>'+newl)
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001745 else:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001746 writer.write('<?xml version="1.0" encoding="%s"?>%s' % (encoding, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001747 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001748 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +00001749
Martin v. Löwis787354c2003-01-25 15:28:29 +00001750 # DOM Level 3 (WD 9 April 2002)
1751
1752 def renameNode(self, n, namespaceURI, name):
1753 if n.ownerDocument is not self:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001754 raise xml.dom.WrongDocumentErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001755 "cannot rename nodes from other documents;\n"
1756 "expected %s,\nfound %s" % (self, n.ownerDocument))
1757 if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001758 raise xml.dom.NotSupportedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001759 "renameNode() only applies to element and attribute nodes")
1760 if namespaceURI != EMPTY_NAMESPACE:
1761 if ':' in name:
1762 prefix, localName = name.split(':', 1)
1763 if ( prefix == "xmlns"
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001764 and namespaceURI != xml.dom.XMLNS_NAMESPACE):
1765 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001766 "illegal use of 'xmlns' prefix")
1767 else:
1768 if ( name == "xmlns"
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001769 and namespaceURI != xml.dom.XMLNS_NAMESPACE
Martin v. Löwis787354c2003-01-25 15:28:29 +00001770 and n.nodeType == Node.ATTRIBUTE_NODE):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001771 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001772 "illegal use of the 'xmlns' attribute")
1773 prefix = None
1774 localName = name
1775 else:
1776 prefix = None
1777 localName = None
1778 if n.nodeType == Node.ATTRIBUTE_NODE:
1779 element = n.ownerElement
1780 if element is not None:
1781 is_id = n._is_id
1782 element.removeAttributeNode(n)
1783 else:
1784 element = None
1785 # avoid __setattr__
1786 d = n.__dict__
1787 d['prefix'] = prefix
1788 d['localName'] = localName
1789 d['namespaceURI'] = namespaceURI
1790 d['nodeName'] = name
1791 if n.nodeType == Node.ELEMENT_NODE:
1792 d['tagName'] = name
1793 else:
1794 # attribute node
1795 d['name'] = name
1796 if element is not None:
1797 element.setAttributeNode(n)
1798 if is_id:
1799 element.setIdAttributeNode(n)
1800 # It's not clear from a semantic perspective whether we should
1801 # call the user data handlers for the NODE_RENAMED event since
1802 # we're re-using the existing node. The draft spec has been
1803 # interpreted as meaning "no, don't call the handler unless a
1804 # new node is created."
1805 return n
1806
1807defproperty(Document, "documentElement",
1808 doc="Top-level element of this document.")
1809
1810
1811def _clone_node(node, deep, newOwnerDocument):
1812 """
1813 Clone a node and give it the new owner document.
1814 Called by Node.cloneNode and Document.importNode
1815 """
1816 if node.ownerDocument.isSameNode(newOwnerDocument):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001817 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001818 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001819 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001820 if node.nodeType == Node.ELEMENT_NODE:
1821 clone = newOwnerDocument.createElementNS(node.namespaceURI,
1822 node.nodeName)
1823 for attr in node.attributes.values():
1824 clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
1825 a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
1826 a.specified = attr.specified
1827
1828 if deep:
1829 for child in node.childNodes:
1830 c = _clone_node(child, deep, newOwnerDocument)
1831 clone.appendChild(c)
1832
1833 elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
1834 clone = newOwnerDocument.createDocumentFragment()
1835 if deep:
1836 for child in node.childNodes:
1837 c = _clone_node(child, deep, newOwnerDocument)
1838 clone.appendChild(c)
1839
1840 elif node.nodeType == Node.TEXT_NODE:
1841 clone = newOwnerDocument.createTextNode(node.data)
1842 elif node.nodeType == Node.CDATA_SECTION_NODE:
1843 clone = newOwnerDocument.createCDATASection(node.data)
1844 elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
1845 clone = newOwnerDocument.createProcessingInstruction(node.target,
1846 node.data)
1847 elif node.nodeType == Node.COMMENT_NODE:
1848 clone = newOwnerDocument.createComment(node.data)
1849 elif node.nodeType == Node.ATTRIBUTE_NODE:
1850 clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
1851 node.nodeName)
1852 clone.specified = True
1853 clone.value = node.value
1854 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
1855 assert node.ownerDocument is not newOwnerDocument
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001856 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001857 clone = newOwnerDocument.implementation.createDocumentType(
1858 node.name, node.publicId, node.systemId)
1859 clone.ownerDocument = newOwnerDocument
1860 if deep:
1861 clone.entities._seq = []
1862 clone.notations._seq = []
1863 for n in node.notations._seq:
1864 notation = Notation(n.nodeName, n.publicId, n.systemId)
1865 notation.ownerDocument = newOwnerDocument
1866 clone.notations._seq.append(notation)
1867 if hasattr(n, '_call_user_data_handler'):
1868 n._call_user_data_handler(operation, n, notation)
1869 for e in node.entities._seq:
1870 entity = Entity(e.nodeName, e.publicId, e.systemId,
1871 e.notationName)
1872 entity.actualEncoding = e.actualEncoding
1873 entity.encoding = e.encoding
1874 entity.version = e.version
1875 entity.ownerDocument = newOwnerDocument
1876 clone.entities._seq.append(entity)
1877 if hasattr(e, '_call_user_data_handler'):
1878 e._call_user_data_handler(operation, n, entity)
1879 else:
1880 # Note the cloning of Document and DocumentType nodes is
1881 # implemenetation specific. minidom handles those cases
1882 # directly in the cloneNode() methods.
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001883 raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001884
1885 # Check for _call_user_data_handler() since this could conceivably
1886 # used with other DOM implementations (one of the FourThought
1887 # DOMs, perhaps?).
1888 if hasattr(node, '_call_user_data_handler'):
1889 node._call_user_data_handler(operation, node, clone)
1890 return clone
1891
1892
1893def _nssplit(qualifiedName):
1894 fields = qualifiedName.split(':', 1)
1895 if len(fields) == 2:
1896 return fields
1897 else:
1898 return (None, fields[0])
1899
1900
Martin v. Löwis787354c2003-01-25 15:28:29 +00001901def _do_pulldom_parse(func, args, kwargs):
Raymond Hettingerff41c482003-04-06 09:01:11 +00001902 events = func(*args, **kwargs)
Fred Drake1f549022000-09-24 05:21:58 +00001903 toktype, rootNode = events.getEvent()
1904 events.expandNode(rootNode)
Martin v. Löwisb417be22001-02-06 01:16:06 +00001905 events.clear()
Fred Drake55c38192000-06-29 19:39:57 +00001906 return rootNode
1907
Martin v. Löwis787354c2003-01-25 15:28:29 +00001908def parse(file, parser=None, bufsize=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001909 """Parse a file into a DOM by filename or file object."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001910 if parser is None and not bufsize:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001911 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001912 return expatbuilder.parse(file)
1913 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001914 from xml.dom import pulldom
Raymond Hettingerff41c482003-04-06 09:01:11 +00001915 return _do_pulldom_parse(pulldom.parse, (file,),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001916 {'parser': parser, 'bufsize': bufsize})
Fred Drake55c38192000-06-29 19:39:57 +00001917
Martin v. Löwis787354c2003-01-25 15:28:29 +00001918def parseString(string, parser=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001919 """Parse a file into a DOM from a string."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001920 if parser is None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001921 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001922 return expatbuilder.parseString(string)
1923 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001924 from xml.dom import pulldom
Martin v. Löwis787354c2003-01-25 15:28:29 +00001925 return _do_pulldom_parse(pulldom.parseString, (string,),
1926 {'parser': parser})
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001927
Martin v. Löwis787354c2003-01-25 15:28:29 +00001928def getDOMImplementation(features=None):
1929 if features:
1930 if isinstance(features, StringTypes):
1931 features = domreg._parse_feature_string(features)
1932 for f, v in features:
1933 if not Document.implementation.hasFeature(f, v):
1934 return None
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001935 return Document.implementation