blob: ad42947238d16d7bc92a4ddf1a4d1d4a219b3739 [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
Fred Drakefbdeaad2006-07-29 16:56:15 +000017import xml.dom
Fred Drake55c38192000-06-29 19:39:57 +000018
Fred Drakefbdeaad2006-07-29 16:56:15 +000019from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
20from xml.dom.minicompat import *
21from xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS
Fred Drake3ac6a092001-09-28 04:33:06 +000022
Martin v. Löwis787354c2003-01-25 15:28:29 +000023# This is used by the ID-cache invalidation checks; the list isn't
24# actually complete, since the nodes being checked will never be the
25# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE. (The node being checked is
26# the node being added or removed, not the node being modified.)
27#
Fred Drakefbdeaad2006-07-29 16:56:15 +000028_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE,
29 xml.dom.Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis95700f72002-03-15 13:51:59 +000030
Fred Drake3ac6a092001-09-28 04:33:06 +000031
Fred Drakefbdeaad2006-07-29 16:56:15 +000032class Node(xml.dom.Node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000033 namespaceURI = None # this is non-null only for elements and attributes
Fred Drake575712e2001-09-28 20:25:45 +000034 parentNode = None
35 ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +000036 nextSibling = None
37 previousSibling = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +000038
Martin v. Löwis787354c2003-01-25 15:28:29 +000039 prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
Fred Drake55c38192000-06-29 19:39:57 +000040
Fred Drake1f549022000-09-24 05:21:58 +000041 def __nonzero__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +000042 return True
Fred Drake55c38192000-06-29 19:39:57 +000043
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000044 def toxml(self, encoding = None):
45 return self.toprettyxml("", "", encoding)
Fred Drake55c38192000-06-29 19:39:57 +000046
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000047 def toprettyxml(self, indent="\t", newl="\n", encoding = None):
Martin v. Löwiscb67ea12001-03-31 16:30:40 +000048 # indent = the indentation string to prepend, per level
49 # newl = the newline string to append
50 writer = _get_StringIO()
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000051 if encoding is not None:
52 import codecs
53 # Can't use codecs.getwriter to preserve 2.0 compatibility
54 writer = codecs.lookup(encoding)[3](writer)
55 if self.nodeType == Node.DOCUMENT_NODE:
56 # Can pass encoding only to document, to put it into XML header
57 self.writexml(writer, "", indent, newl, encoding)
58 else:
59 self.writexml(writer, "", indent, newl)
Martin v. Löwiscb67ea12001-03-31 16:30:40 +000060 return writer.getvalue()
Martin v. Löwis46fa39a2001-02-06 00:14:08 +000061
Fred Drake1f549022000-09-24 05:21:58 +000062 def hasChildNodes(self):
63 if self.childNodes:
Martin v. Löwis787354c2003-01-25 15:28:29 +000064 return True
Fred Drake1f549022000-09-24 05:21:58 +000065 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +000066 return False
67
68 def _get_childNodes(self):
69 return self.childNodes
Fred Drake55c38192000-06-29 19:39:57 +000070
Fred Drake1f549022000-09-24 05:21:58 +000071 def _get_firstChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000072 if self.childNodes:
73 return self.childNodes[0]
Paul Prescod73678da2000-07-01 04:58:47 +000074
Fred Drake1f549022000-09-24 05:21:58 +000075 def _get_lastChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000076 if self.childNodes:
77 return self.childNodes[-1]
Paul Prescod73678da2000-07-01 04:58:47 +000078
Fred Drake1f549022000-09-24 05:21:58 +000079 def insertBefore(self, newChild, refChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000080 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +000081 for c in tuple(newChild.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000082 self.insertBefore(c, refChild)
83 ### The DOM does not clearly specify what to return in this case
84 return newChild
Martin v. Löwis787354c2003-01-25 15:28:29 +000085 if newChild.nodeType not in self._child_node_types:
Fred Drakefbdeaad2006-07-29 16:56:15 +000086 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +000087 "%s cannot be child of %s" % (repr(newChild), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +000088 if newChild.parentNode is not None:
89 newChild.parentNode.removeChild(newChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +000090 if refChild is None:
91 self.appendChild(newChild)
92 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +000093 try:
94 index = self.childNodes.index(refChild)
95 except ValueError:
Fred Drakefbdeaad2006-07-29 16:56:15 +000096 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +000097 if newChild.nodeType in _nodeTypes_with_children:
98 _clear_id_cache(self)
Fred Drake4ccf4a12000-11-21 22:02:22 +000099 self.childNodes.insert(index, newChild)
100 newChild.nextSibling = refChild
101 refChild.previousSibling = newChild
102 if index:
103 node = self.childNodes[index-1]
104 node.nextSibling = newChild
105 newChild.previousSibling = node
106 else:
107 newChild.previousSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000108 newChild.parentNode = self
Fred Drake4ccf4a12000-11-21 22:02:22 +0000109 return newChild
Fred Drake55c38192000-06-29 19:39:57 +0000110
Fred Drake1f549022000-09-24 05:21:58 +0000111 def appendChild(self, node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000112 if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +0000113 for c in tuple(node.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000114 self.appendChild(c)
115 ### The DOM does not clearly specify what to return in this case
116 return node
Martin v. Löwis787354c2003-01-25 15:28:29 +0000117 if node.nodeType not in self._child_node_types:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000118 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000119 "%s cannot be child of %s" % (repr(node), repr(self)))
120 elif node.nodeType in _nodeTypes_with_children:
121 _clear_id_cache(self)
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000122 if node.parentNode is not None:
123 node.parentNode.removeChild(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000124 _append_child(self, node)
Fred Drake13a30692000-10-09 20:04:16 +0000125 node.nextSibling = None
Paul Prescod73678da2000-07-01 04:58:47 +0000126 return node
127
Fred Drake1f549022000-09-24 05:21:58 +0000128 def replaceChild(self, newChild, oldChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000129 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
130 refChild = oldChild.nextSibling
131 self.removeChild(oldChild)
132 return self.insertBefore(newChild, refChild)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000133 if newChild.nodeType not in self._child_node_types:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000134 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000135 "%s cannot be child of %s" % (repr(newChild), repr(self)))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000136 if newChild is oldChild:
137 return
Andrew M. Kuchling841d25e2005-11-22 19:03:16 +0000138 if newChild.parentNode is not None:
139 newChild.parentNode.removeChild(newChild)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000140 try:
141 index = self.childNodes.index(oldChild)
142 except ValueError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000143 raise xml.dom.NotFoundErr()
Fred Drake4ccf4a12000-11-21 22:02:22 +0000144 self.childNodes[index] = newChild
Martin v. Löwis787354c2003-01-25 15:28:29 +0000145 newChild.parentNode = self
146 oldChild.parentNode = None
147 if (newChild.nodeType in _nodeTypes_with_children
148 or oldChild.nodeType in _nodeTypes_with_children):
149 _clear_id_cache(self)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000150 newChild.nextSibling = oldChild.nextSibling
151 newChild.previousSibling = oldChild.previousSibling
Martin v. Löwis156c3372000-12-28 18:40:56 +0000152 oldChild.nextSibling = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000153 oldChild.previousSibling = None
Martin v. Löwis156c3372000-12-28 18:40:56 +0000154 if newChild.previousSibling:
155 newChild.previousSibling.nextSibling = newChild
156 if newChild.nextSibling:
157 newChild.nextSibling.previousSibling = newChild
Fred Drake4ccf4a12000-11-21 22:02:22 +0000158 return oldChild
Paul Prescod73678da2000-07-01 04:58:47 +0000159
Fred Drake1f549022000-09-24 05:21:58 +0000160 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000161 try:
162 self.childNodes.remove(oldChild)
163 except ValueError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000164 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000165 if oldChild.nextSibling is not None:
166 oldChild.nextSibling.previousSibling = oldChild.previousSibling
167 if oldChild.previousSibling is not None:
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000168 oldChild.previousSibling.nextSibling = oldChild.nextSibling
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000169 oldChild.nextSibling = oldChild.previousSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000170 if oldChild.nodeType in _nodeTypes_with_children:
171 _clear_id_cache(self)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000172
Martin v. Löwis787354c2003-01-25 15:28:29 +0000173 oldChild.parentNode = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000174 return oldChild
175
176 def normalize(self):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000177 L = []
178 for child in self.childNodes:
179 if child.nodeType == Node.TEXT_NODE:
180 data = child.data
181 if data and L and L[-1].nodeType == child.nodeType:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000182 # collapse text node
183 node = L[-1]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000184 node.data = node.data + child.data
Fred Drake4ccf4a12000-11-21 22:02:22 +0000185 node.nextSibling = child.nextSibling
186 child.unlink()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000187 elif data:
188 if L:
189 L[-1].nextSibling = child
190 child.previousSibling = L[-1]
191 else:
192 child.previousSibling = None
193 L.append(child)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000194 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000195 # empty text node; discard
196 child.unlink()
197 else:
198 if L:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000199 L[-1].nextSibling = child
200 child.previousSibling = L[-1]
Fred Drakef7cf40d2000-12-14 18:16:11 +0000201 else:
202 child.previousSibling = None
203 L.append(child)
204 if child.nodeType == Node.ELEMENT_NODE:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000205 child.normalize()
Andrew M. Kuchling19aff0c2008-02-23 17:10:46 +0000206 if L:
207 L[-1].nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000208 self.childNodes[:] = L
Paul Prescod73678da2000-07-01 04:58:47 +0000209
Fred Drake1f549022000-09-24 05:21:58 +0000210 def cloneNode(self, deep):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000211 return _clone_node(self, deep, self.ownerDocument or self)
Fred Drake55c38192000-06-29 19:39:57 +0000212
Martin v. Löwis787354c2003-01-25 15:28:29 +0000213 def isSupported(self, feature, version):
214 return self.ownerDocument.implementation.hasFeature(feature, version)
215
216 def _get_localName(self):
217 # Overridden in Element and Attr where localName can be Non-Null
218 return None
219
220 # Node interfaces from Level 3 (WD 9 April 2002)
Fred Drake25239772001-02-02 19:40:19 +0000221
222 def isSameNode(self, other):
223 return self is other
224
Martin v. Löwis787354c2003-01-25 15:28:29 +0000225 def getInterface(self, feature):
226 if self.isSupported(feature, None):
227 return self
228 else:
229 return None
230
231 # The "user data" functions use a dictionary that is only present
232 # if some user data has been set, so be careful not to assume it
233 # exists.
234
235 def getUserData(self, key):
236 try:
237 return self._user_data[key][0]
238 except (AttributeError, KeyError):
239 return None
240
241 def setUserData(self, key, data, handler):
242 old = None
243 try:
244 d = self._user_data
245 except AttributeError:
246 d = {}
247 self._user_data = d
Brett Cannon5dd504d2008-08-04 00:23:58 +0000248 if key in d:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000249 old = d[key][0]
250 if data is None:
251 # ignore handlers passed for None
252 handler = None
253 if old is not None:
254 del d[key]
255 else:
256 d[key] = (data, handler)
257 return old
258
259 def _call_user_data_handler(self, operation, src, dst):
260 if hasattr(self, "_user_data"):
261 for key, (data, handler) in self._user_data.items():
262 if handler is not None:
263 handler.handle(operation, key, data, src, dst)
264
Fred Drake25239772001-02-02 19:40:19 +0000265 # minidom-specific API:
266
Fred Drake1f549022000-09-24 05:21:58 +0000267 def unlink(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000268 self.parentNode = self.ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000269 if self.childNodes:
270 for child in self.childNodes:
271 child.unlink()
272 self.childNodes = NodeList()
Paul Prescod4221ff02000-10-13 20:11:42 +0000273 self.previousSibling = None
274 self.nextSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000275
276defproperty(Node, "firstChild", doc="First child node, or None.")
277defproperty(Node, "lastChild", doc="Last child node, or None.")
278defproperty(Node, "localName", doc="Namespace-local name of this node.")
279
280
281def _append_child(self, node):
282 # fast path with less checks; usable by DOM builders if careful
283 childNodes = self.childNodes
284 if childNodes:
285 last = childNodes[-1]
286 node.__dict__["previousSibling"] = last
287 last.__dict__["nextSibling"] = node
288 childNodes.append(node)
289 node.__dict__["parentNode"] = self
290
291def _in_document(node):
292 # return True iff node is part of a document tree
293 while node is not None:
294 if node.nodeType == Node.DOCUMENT_NODE:
295 return True
296 node = node.parentNode
297 return False
Fred Drake55c38192000-06-29 19:39:57 +0000298
Fred Drake1f549022000-09-24 05:21:58 +0000299def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000300 "Writes datachars to writer."
Martin v. Löwis787354c2003-01-25 15:28:29 +0000301 data = data.replace("&", "&amp;").replace("<", "&lt;")
302 data = data.replace("\"", "&quot;").replace(">", "&gt;")
Fred Drake55c38192000-06-29 19:39:57 +0000303 writer.write(data)
304
Martin v. Löwis787354c2003-01-25 15:28:29 +0000305def _get_elements_by_tagName_helper(parent, name, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000306 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000307 if node.nodeType == Node.ELEMENT_NODE and \
308 (name == "*" or node.tagName == name):
309 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000310 _get_elements_by_tagName_helper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000311 return rc
312
Martin v. Löwis787354c2003-01-25 15:28:29 +0000313def _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000314 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000315 if node.nodeType == Node.ELEMENT_NODE:
Martin v. Löwised525fb2001-06-03 14:06:42 +0000316 if ((localName == "*" or node.localName == localName) and
Fred Drake1f549022000-09-24 05:21:58 +0000317 (nsURI == "*" or node.namespaceURI == nsURI)):
318 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000319 _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000320 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000321
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000322class DocumentFragment(Node):
323 nodeType = Node.DOCUMENT_FRAGMENT_NODE
324 nodeName = "#document-fragment"
325 nodeValue = None
326 attributes = None
327 parentNode = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000328 _child_node_types = (Node.ELEMENT_NODE,
329 Node.TEXT_NODE,
330 Node.CDATA_SECTION_NODE,
331 Node.ENTITY_REFERENCE_NODE,
332 Node.PROCESSING_INSTRUCTION_NODE,
333 Node.COMMENT_NODE,
334 Node.NOTATION_NODE)
335
336 def __init__(self):
337 self.childNodes = NodeList()
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000338
339
Fred Drake55c38192000-06-29 19:39:57 +0000340class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000341 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000342 attributes = None
343 ownerElement = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000344 specified = False
345 _is_id = False
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000346
Martin v. Löwis787354c2003-01-25 15:28:29 +0000347 _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
348
349 def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
350 prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000351 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000352 d = self.__dict__
Fred Drake4ccf4a12000-11-21 22:02:22 +0000353 d["nodeName"] = d["name"] = qName
354 d["namespaceURI"] = namespaceURI
355 d["prefix"] = prefix
Martin v. Löwis787354c2003-01-25 15:28:29 +0000356 d['childNodes'] = NodeList()
357
358 # Add the single child node that represents the value of the attr
359 self.childNodes.append(Text())
360
Paul Prescod73678da2000-07-01 04:58:47 +0000361 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000362
Martin v. Löwis787354c2003-01-25 15:28:29 +0000363 def _get_localName(self):
364 return self.nodeName.split(":", 1)[-1]
365
366 def _get_name(self):
367 return self.name
368
369 def _get_specified(self):
370 return self.specified
371
Fred Drake1f549022000-09-24 05:21:58 +0000372 def __setattr__(self, name, value):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000373 d = self.__dict__
Fred Drake1f549022000-09-24 05:21:58 +0000374 if name in ("value", "nodeValue"):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000375 d["value"] = d["nodeValue"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000376 d2 = self.childNodes[0].__dict__
377 d2["data"] = d2["nodeValue"] = value
378 if self.ownerElement is not None:
379 _clear_id_cache(self.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000380 elif name in ("name", "nodeName"):
381 d["name"] = d["nodeName"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000382 if self.ownerElement is not None:
383 _clear_id_cache(self.ownerElement)
Fred Drake55c38192000-06-29 19:39:57 +0000384 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000385 d[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000386
Martin v. Löwis995359c2003-01-26 08:59:32 +0000387 def _set_prefix(self, prefix):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000388 nsuri = self.namespaceURI
Martin v. Löwis995359c2003-01-26 08:59:32 +0000389 if prefix == "xmlns":
390 if nsuri and nsuri != XMLNS_NAMESPACE:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000391 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000392 "illegal use of 'xmlns' prefix for the wrong namespace")
393 d = self.__dict__
394 d['prefix'] = prefix
395 if prefix is None:
396 newName = self.localName
397 else:
Martin v. Löwis995359c2003-01-26 08:59:32 +0000398 newName = "%s:%s" % (prefix, self.localName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000399 if self.ownerElement:
400 _clear_id_cache(self.ownerElement)
401 d['nodeName'] = d['name'] = newName
402
403 def _set_value(self, value):
404 d = self.__dict__
405 d['value'] = d['nodeValue'] = value
406 if self.ownerElement:
407 _clear_id_cache(self.ownerElement)
408 self.childNodes[0].data = value
409
410 def unlink(self):
411 # This implementation does not call the base implementation
412 # since most of that is not needed, and the expense of the
413 # method call is not warranted. We duplicate the removal of
414 # children, but that's all we needed from the base class.
415 elem = self.ownerElement
416 if elem is not None:
417 del elem._attrs[self.nodeName]
418 del elem._attrsNS[(self.namespaceURI, self.localName)]
419 if self._is_id:
420 self._is_id = False
421 elem._magic_id_nodes -= 1
422 self.ownerDocument._magic_id_count -= 1
423 for child in self.childNodes:
424 child.unlink()
425 del self.childNodes[:]
426
427 def _get_isId(self):
428 if self._is_id:
429 return True
430 doc = self.ownerDocument
431 elem = self.ownerElement
432 if doc is None or elem is None:
433 return False
434
435 info = doc._get_elem_info(elem)
436 if info is None:
437 return False
438 if self.namespaceURI:
439 return info.isIdNS(self.namespaceURI, self.localName)
440 else:
441 return info.isId(self.nodeName)
442
443 def _get_schemaType(self):
444 doc = self.ownerDocument
445 elem = self.ownerElement
446 if doc is None or elem is None:
447 return _no_type
448
449 info = doc._get_elem_info(elem)
450 if info is None:
451 return _no_type
452 if self.namespaceURI:
453 return info.getAttributeTypeNS(self.namespaceURI, self.localName)
454 else:
455 return info.getAttributeType(self.nodeName)
456
457defproperty(Attr, "isId", doc="True if this attribute is an ID.")
458defproperty(Attr, "localName", doc="Namespace-local name of this attribute.")
459defproperty(Attr, "schemaType", doc="Schema type for this attribute.")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000460
Fred Drakef7cf40d2000-12-14 18:16:11 +0000461
Fred Drake9ea179f2006-04-06 01:29:04 +0000462class NamedNodeMap(object):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000463 """The attribute list is a transient interface to the underlying
464 dictionaries. Mutations here will change the underlying element's
Fred Drakef7cf40d2000-12-14 18:16:11 +0000465 dictionary.
466
467 Ordering is imposed artificially and does not reflect the order of
468 attributes as found in an input document.
469 """
Fred Drake4ccf4a12000-11-21 22:02:22 +0000470
Martin v. Löwis787354c2003-01-25 15:28:29 +0000471 __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
472
Fred Drake2998a552001-12-06 18:27:48 +0000473 def __init__(self, attrs, attrsNS, ownerElement):
Fred Drake1f549022000-09-24 05:21:58 +0000474 self._attrs = attrs
475 self._attrsNS = attrsNS
Fred Drake2998a552001-12-06 18:27:48 +0000476 self._ownerElement = ownerElement
Fred Drakef7cf40d2000-12-14 18:16:11 +0000477
Martin v. Löwis787354c2003-01-25 15:28:29 +0000478 def _get_length(self):
479 return len(self._attrs)
Fred Drake55c38192000-06-29 19:39:57 +0000480
Fred Drake1f549022000-09-24 05:21:58 +0000481 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000482 try:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000483 return self[self._attrs.keys()[index]]
Fred Drake55c38192000-06-29 19:39:57 +0000484 except IndexError:
485 return None
Fred Drake55c38192000-06-29 19:39:57 +0000486
Fred Drake1f549022000-09-24 05:21:58 +0000487 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000488 L = []
489 for node in self._attrs.values():
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000490 L.append((node.nodeName, node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000491 return L
Fred Drake1f549022000-09-24 05:21:58 +0000492
493 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000494 L = []
495 for node in self._attrs.values():
Fred Drake49a5d032001-11-30 22:21:58 +0000496 L.append(((node.namespaceURI, node.localName), node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000497 return L
Fred Drake16f63292000-10-23 18:09:50 +0000498
Martin v. Löwis787354c2003-01-25 15:28:29 +0000499 def has_key(self, key):
500 if isinstance(key, StringTypes):
501 return self._attrs.has_key(key)
502 else:
503 return self._attrsNS.has_key(key)
504
Fred Drake1f549022000-09-24 05:21:58 +0000505 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000506 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000507
Fred Drake1f549022000-09-24 05:21:58 +0000508 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000509 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000510
Fred Drake1f549022000-09-24 05:21:58 +0000511 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000512 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000513
Martin v. Löwis787354c2003-01-25 15:28:29 +0000514 def get(self, name, value=None):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000515 return self._attrs.get(name, value)
516
Martin v. Löwis787354c2003-01-25 15:28:29 +0000517 __len__ = _get_length
Fred Drake55c38192000-06-29 19:39:57 +0000518
Nick Coghlan48361f52008-08-11 15:45:58 +0000519 __hash__ = None # Mutable type can't be correctly hashed
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):
Fred Drake70d044b2006-04-06 01:32:26 +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):
544 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)]
Brett Cannon5dd504d2008-08-04 00:23:58 +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:
Fred Drakefbdeaad2006-07-29 16:56:15 +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]
Brett Cannon5dd504d2008-08-04 00:23:58 +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:
Fred Drakefbdeaad2006-07-29 16:56:15 +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):
Fred Drakefbdeaad2006-07-29 16:56:15 +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
Fred Drake9ea179f2006-04-06 01:29:04 +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):
668 return self.tagName.split(":", 1)[-1]
669
670 def _get_tagName(self):
671 return self.tagName
Fred Drake4ccf4a12000-11-21 22:02:22 +0000672
673 def unlink(self):
674 for attr in self._attrs.values():
675 attr.unlink()
676 self._attrs = None
677 self._attrsNS = None
678 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000679
Fred Drake1f549022000-09-24 05:21:58 +0000680 def getAttribute(self, attname):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000681 try:
682 return self._attrs[attname].value
683 except KeyError:
684 return ""
Fred Drake55c38192000-06-29 19:39:57 +0000685
Fred Drake1f549022000-09-24 05:21:58 +0000686 def getAttributeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000687 try:
688 return self._attrsNS[(namespaceURI, localName)].value
689 except KeyError:
690 return ""
Fred Drake1f549022000-09-24 05:21:58 +0000691
692 def setAttribute(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000693 attr = self.getAttributeNode(attname)
694 if attr is None:
695 attr = Attr(attname)
696 # for performance
697 d = attr.__dict__
698 d["value"] = d["nodeValue"] = value
699 d["ownerDocument"] = self.ownerDocument
700 self.setAttributeNode(attr)
701 elif value != attr.value:
702 d = attr.__dict__
703 d["value"] = d["nodeValue"] = value
704 if attr.isId:
705 _clear_id_cache(self)
Fred Drake55c38192000-06-29 19:39:57 +0000706
Fred Drake1f549022000-09-24 05:21:58 +0000707 def setAttributeNS(self, namespaceURI, qualifiedName, value):
708 prefix, localname = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000709 attr = self.getAttributeNodeNS(namespaceURI, localname)
710 if attr is None:
711 # for performance
712 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
713 d = attr.__dict__
714 d["prefix"] = prefix
715 d["nodeName"] = qualifiedName
716 d["value"] = d["nodeValue"] = value
717 d["ownerDocument"] = self.ownerDocument
718 self.setAttributeNode(attr)
719 else:
720 d = attr.__dict__
721 if value != attr.value:
722 d["value"] = d["nodeValue"] = value
723 if attr.isId:
724 _clear_id_cache(self)
725 if attr.prefix != prefix:
726 d["prefix"] = prefix
727 d["nodeName"] = qualifiedName
Fred Drake55c38192000-06-29 19:39:57 +0000728
Fred Drake1f549022000-09-24 05:21:58 +0000729 def getAttributeNode(self, attrname):
730 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000731
Fred Drake1f549022000-09-24 05:21:58 +0000732 def getAttributeNodeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000733 return self._attrsNS.get((namespaceURI, localName))
Paul Prescod73678da2000-07-01 04:58:47 +0000734
Fred Drake1f549022000-09-24 05:21:58 +0000735 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000736 if attr.ownerElement not in (None, self):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000737 raise xml.dom.InuseAttributeErr("attribute node already owned")
Martin v. Löwis787354c2003-01-25 15:28:29 +0000738 old1 = self._attrs.get(attr.name, None)
739 if old1 is not None:
740 self.removeAttributeNode(old1)
741 old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
742 if old2 is not None and old2 is not old1:
743 self.removeAttributeNode(old2)
744 _set_attribute_node(self, attr)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000745
Martin v. Löwis787354c2003-01-25 15:28:29 +0000746 if old1 is not attr:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000747 # It might have already been part of this node, in which case
748 # it doesn't represent a change, and should not be returned.
Martin v. Löwis787354c2003-01-25 15:28:29 +0000749 return old1
750 if old2 is not attr:
751 return old2
Fred Drake55c38192000-06-29 19:39:57 +0000752
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000753 setAttributeNodeNS = setAttributeNode
754
Fred Drake1f549022000-09-24 05:21:58 +0000755 def removeAttribute(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000756 try:
757 attr = self._attrs[name]
758 except KeyError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000759 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000760 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000761
Fred Drake1f549022000-09-24 05:21:58 +0000762 def removeAttributeNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000763 try:
764 attr = self._attrsNS[(namespaceURI, localName)]
765 except KeyError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000766 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000767 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000768
Fred Drake1f549022000-09-24 05:21:58 +0000769 def removeAttributeNode(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000770 if node is None:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000771 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000772 try:
773 self._attrs[node.name]
774 except KeyError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000775 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000776 _clear_id_cache(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000777 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000778 # Restore this since the node is still useful and otherwise
779 # unlinked
780 node.ownerDocument = self.ownerDocument
Fred Drake16f63292000-10-23 18:09:50 +0000781
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000782 removeAttributeNodeNS = removeAttributeNode
783
Martin v. Löwis156c3372000-12-28 18:40:56 +0000784 def hasAttribute(self, name):
785 return self._attrs.has_key(name)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000786
Martin v. Löwis156c3372000-12-28 18:40:56 +0000787 def hasAttributeNS(self, namespaceURI, localName):
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000788 return self._attrsNS.has_key((namespaceURI, localName))
789
Fred Drake1f549022000-09-24 05:21:58 +0000790 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000791 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000792
Fred Drake1f549022000-09-24 05:21:58 +0000793 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000794 return _get_elements_by_tagName_ns_helper(
795 self, namespaceURI, localName, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000796
Fred Drake1f549022000-09-24 05:21:58 +0000797 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000798 return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000799
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000800 def writexml(self, writer, indent="", addindent="", newl=""):
801 # indent = current indentation
802 # addindent = indentation to add to higher levels
803 # newl = newline string
804 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000805
Fred Drake4ccf4a12000-11-21 22:02:22 +0000806 attrs = self._get_attributes()
807 a_names = attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000808 a_names.sort()
809
810 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000811 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000812 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000813 writer.write("\"")
814 if self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000815 writer.write(">%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000816 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000817 node.writexml(writer,indent+addindent,addindent,newl)
818 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
Fred Drake55c38192000-06-29 19:39:57 +0000819 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000820 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000821
Fred Drake1f549022000-09-24 05:21:58 +0000822 def _get_attributes(self):
Fred Drake2998a552001-12-06 18:27:48 +0000823 return NamedNodeMap(self._attrs, self._attrsNS, self)
Fred Drake55c38192000-06-29 19:39:57 +0000824
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000825 def hasAttributes(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000826 if self._attrs:
827 return True
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000828 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000829 return False
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000830
Martin v. Löwis787354c2003-01-25 15:28:29 +0000831 # DOM Level 3 attributes, based on the 22 Oct 2002 draft
832
833 def setIdAttribute(self, name):
834 idAttr = self.getAttributeNode(name)
835 self.setIdAttributeNode(idAttr)
836
837 def setIdAttributeNS(self, namespaceURI, localName):
838 idAttr = self.getAttributeNodeNS(namespaceURI, localName)
839 self.setIdAttributeNode(idAttr)
840
841 def setIdAttributeNode(self, idAttr):
842 if idAttr is None or not self.isSameNode(idAttr.ownerElement):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000843 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000844 if _get_containing_entref(self) is not None:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000845 raise xml.dom.NoModificationAllowedErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000846 if not idAttr._is_id:
847 idAttr.__dict__['_is_id'] = True
848 self._magic_id_nodes += 1
849 self.ownerDocument._magic_id_count += 1
850 _clear_id_cache(self)
851
852defproperty(Element, "attributes",
853 doc="NamedNodeMap of attributes on the element.")
854defproperty(Element, "localName",
855 doc="Namespace-local name of this element.")
856
857
858def _set_attribute_node(element, attr):
859 _clear_id_cache(element)
860 element._attrs[attr.name] = attr
861 element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
862
863 # This creates a circular reference, but Element.unlink()
864 # breaks the cycle since the references to the attribute
865 # dictionaries are tossed.
866 attr.__dict__['ownerElement'] = element
867
868
869class Childless:
870 """Mixin that makes childless-ness easy to implement and avoids
871 the complexity of the Node methods that deal with children.
872 """
873
Fred Drake4ccf4a12000-11-21 22:02:22 +0000874 attributes = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000875 childNodes = EmptyNodeList()
876 firstChild = None
877 lastChild = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000878
Martin v. Löwis787354c2003-01-25 15:28:29 +0000879 def _get_firstChild(self):
880 return None
Fred Drake55c38192000-06-29 19:39:57 +0000881
Martin v. Löwis787354c2003-01-25 15:28:29 +0000882 def _get_lastChild(self):
883 return None
Fred Drake1f549022000-09-24 05:21:58 +0000884
Martin v. Löwis787354c2003-01-25 15:28:29 +0000885 def appendChild(self, node):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000886 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000887 self.nodeName + " nodes cannot have children")
888
889 def hasChildNodes(self):
890 return False
891
892 def insertBefore(self, newChild, refChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000893 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000894 self.nodeName + " nodes do not have children")
895
896 def removeChild(self, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000897 raise xml.dom.NotFoundErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000898 self.nodeName + " nodes do not have children")
899
900 def replaceChild(self, newChild, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000901 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000902 self.nodeName + " nodes do not have children")
903
904
905class ProcessingInstruction(Childless, Node):
Fred Drake1f549022000-09-24 05:21:58 +0000906 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000907
Fred Drake1f549022000-09-24 05:21:58 +0000908 def __init__(self, target, data):
Fred Drake55c38192000-06-29 19:39:57 +0000909 self.target = self.nodeName = target
910 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000911
Martin v. Löwis787354c2003-01-25 15:28:29 +0000912 def _get_data(self):
913 return self.data
914 def _set_data(self, value):
915 d = self.__dict__
916 d['data'] = d['nodeValue'] = value
917
918 def _get_target(self):
919 return self.target
920 def _set_target(self, value):
921 d = self.__dict__
922 d['target'] = d['nodeName'] = value
923
924 def __setattr__(self, name, value):
925 if name == "data" or name == "nodeValue":
926 self.__dict__['data'] = self.__dict__['nodeValue'] = value
927 elif name == "target" or name == "nodeName":
928 self.__dict__['target'] = self.__dict__['nodeName'] = value
929 else:
930 self.__dict__[name] = value
931
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000932 def writexml(self, writer, indent="", addindent="", newl=""):
933 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000934
Martin v. Löwis787354c2003-01-25 15:28:29 +0000935
936class CharacterData(Childless, Node):
937 def _get_length(self):
938 return len(self.data)
939 __len__ = _get_length
940
941 def _get_data(self):
942 return self.__dict__['data']
943 def _set_data(self, data):
944 d = self.__dict__
945 d['data'] = d['nodeValue'] = data
946
947 _get_nodeValue = _get_data
948 _set_nodeValue = _set_data
949
950 def __setattr__(self, name, value):
951 if name == "data" or name == "nodeValue":
952 self.__dict__['data'] = self.__dict__['nodeValue'] = value
953 else:
954 self.__dict__[name] = value
Fred Drake87432f42001-04-04 14:09:46 +0000955
Fred Drake55c38192000-06-29 19:39:57 +0000956 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000957 data = self.data
958 if len(data) > 10:
Fred Drake1f549022000-09-24 05:21:58 +0000959 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000960 else:
Fred Drake1f549022000-09-24 05:21:58 +0000961 dotdotdot = ""
Facundo Batistaf5ade632007-10-24 19:11:08 +0000962 return '<DOM %s node "%r%s">' % (
Martin v. Löwis787354c2003-01-25 15:28:29 +0000963 self.__class__.__name__, data[0:10], dotdotdot)
Fred Drake87432f42001-04-04 14:09:46 +0000964
965 def substringData(self, offset, count):
966 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000967 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000968 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000969 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000970 if count < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000971 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000972 return self.data[offset:offset+count]
973
974 def appendData(self, arg):
975 self.data = self.data + arg
Fred Drake87432f42001-04-04 14:09:46 +0000976
977 def insertData(self, offset, arg):
978 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000979 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000980 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000981 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000982 if arg:
983 self.data = "%s%s%s" % (
984 self.data[:offset], arg, self.data[offset:])
Fred Drake87432f42001-04-04 14:09:46 +0000985
986 def deleteData(self, offset, count):
987 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000988 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000989 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000990 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000991 if count < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000992 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000993 if count:
994 self.data = self.data[:offset] + self.data[offset+count:]
Fred Drake87432f42001-04-04 14:09:46 +0000995
996 def replaceData(self, offset, count, arg):
997 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000998 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000999 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001000 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +00001001 if count < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001002 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001003 if count:
1004 self.data = "%s%s%s" % (
1005 self.data[:offset], arg, self.data[offset+count:])
Martin v. Löwis787354c2003-01-25 15:28:29 +00001006
1007defproperty(CharacterData, "length", doc="Length of the string data.")
1008
Fred Drake87432f42001-04-04 14:09:46 +00001009
1010class Text(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001011 # Make sure we don't add an instance __dict__ if we don't already
1012 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001013 # XXX this does not work, CharacterData is an old-style class
1014 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001015
Fred Drake87432f42001-04-04 14:09:46 +00001016 nodeType = Node.TEXT_NODE
1017 nodeName = "#text"
1018 attributes = None
Fred Drake55c38192000-06-29 19:39:57 +00001019
Fred Drakef7cf40d2000-12-14 18:16:11 +00001020 def splitText(self, offset):
1021 if offset < 0 or offset > len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001022 raise xml.dom.IndexSizeErr("illegal offset value")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001023 newText = self.__class__()
1024 newText.data = self.data[offset:]
1025 newText.ownerDocument = self.ownerDocument
Fred Drakef7cf40d2000-12-14 18:16:11 +00001026 next = self.nextSibling
1027 if self.parentNode and self in self.parentNode.childNodes:
1028 if next is None:
1029 self.parentNode.appendChild(newText)
1030 else:
1031 self.parentNode.insertBefore(newText, next)
1032 self.data = self.data[:offset]
1033 return newText
1034
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001035 def writexml(self, writer, indent="", addindent="", newl=""):
1036 _write_data(writer, "%s%s%s"%(indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001037
Martin v. Löwis787354c2003-01-25 15:28:29 +00001038 # DOM Level 3 (WD 9 April 2002)
1039
1040 def _get_wholeText(self):
1041 L = [self.data]
1042 n = self.previousSibling
1043 while n is not None:
1044 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1045 L.insert(0, n.data)
1046 n = n.previousSibling
1047 else:
1048 break
1049 n = self.nextSibling
1050 while n is not None:
1051 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1052 L.append(n.data)
1053 n = n.nextSibling
1054 else:
1055 break
1056 return ''.join(L)
1057
1058 def replaceWholeText(self, content):
1059 # XXX This needs to be seriously changed if minidom ever
1060 # supports EntityReference nodes.
1061 parent = self.parentNode
1062 n = self.previousSibling
1063 while n is not None:
1064 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1065 next = n.previousSibling
1066 parent.removeChild(n)
1067 n = next
1068 else:
1069 break
1070 n = self.nextSibling
1071 if not content:
1072 parent.removeChild(self)
1073 while n is not None:
1074 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1075 next = n.nextSibling
1076 parent.removeChild(n)
1077 n = next
1078 else:
1079 break
1080 if content:
1081 d = self.__dict__
1082 d['data'] = content
1083 d['nodeValue'] = content
1084 return self
1085 else:
1086 return None
1087
1088 def _get_isWhitespaceInElementContent(self):
1089 if self.data.strip():
1090 return False
1091 elem = _get_containing_element(self)
1092 if elem is None:
1093 return False
1094 info = self.ownerDocument._get_elem_info(elem)
1095 if info is None:
1096 return False
1097 else:
1098 return info.isElementContent()
1099
1100defproperty(Text, "isWhitespaceInElementContent",
1101 doc="True iff this text node contains only whitespace"
1102 " and is in element content.")
1103defproperty(Text, "wholeText",
1104 doc="The text of all logically-adjacent text nodes.")
1105
1106
1107def _get_containing_element(node):
1108 c = node.parentNode
1109 while c is not None:
1110 if c.nodeType == Node.ELEMENT_NODE:
1111 return c
1112 c = c.parentNode
1113 return None
1114
1115def _get_containing_entref(node):
1116 c = node.parentNode
1117 while c is not None:
1118 if c.nodeType == Node.ENTITY_REFERENCE_NODE:
1119 return c
1120 c = c.parentNode
1121 return None
1122
1123
1124class Comment(Childless, CharacterData):
1125 nodeType = Node.COMMENT_NODE
1126 nodeName = "#comment"
1127
1128 def __init__(self, data):
1129 self.data = self.nodeValue = data
1130
1131 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis27e4a172008-05-23 15:18:28 +00001132 if "--" in self.data:
1133 raise ValueError("'--' is not allowed in a comment node")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001134 writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
1135
Fred Drake87432f42001-04-04 14:09:46 +00001136
1137class CDATASection(Text):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001138 # Make sure we don't add an instance __dict__ if we don't already
1139 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001140 # XXX this does not work, Text is an old-style class
1141 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001142
Fred Drake87432f42001-04-04 14:09:46 +00001143 nodeType = Node.CDATA_SECTION_NODE
1144 nodeName = "#cdata-section"
1145
1146 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001147 if self.data.find("]]>") >= 0:
1148 raise ValueError("']]>' not allowed in a CDATA section")
Guido van Rossum5b5e0b92001-09-19 13:28:25 +00001149 writer.write("<![CDATA[%s]]>" % self.data)
Fred Drake87432f42001-04-04 14:09:46 +00001150
1151
Fred Drake9ea179f2006-04-06 01:29:04 +00001152class ReadOnlySequentialNamedNodeMap(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001153 __slots__ = '_seq',
1154
1155 def __init__(self, seq=()):
1156 # seq should be a list or tuple
1157 self._seq = seq
1158
1159 def __len__(self):
1160 return len(self._seq)
1161
1162 def _get_length(self):
1163 return len(self._seq)
1164
1165 def getNamedItem(self, name):
1166 for n in self._seq:
1167 if n.nodeName == name:
1168 return n
1169
1170 def getNamedItemNS(self, namespaceURI, localName):
1171 for n in self._seq:
1172 if n.namespaceURI == namespaceURI and n.localName == localName:
1173 return n
1174
1175 def __getitem__(self, name_or_tuple):
Fred Drake70d044b2006-04-06 01:32:26 +00001176 if isinstance(name_or_tuple, tuple):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001177 node = self.getNamedItemNS(*name_or_tuple)
1178 else:
1179 node = self.getNamedItem(name_or_tuple)
1180 if node is None:
1181 raise KeyError, name_or_tuple
1182 return node
1183
1184 def item(self, index):
1185 if index < 0:
1186 return None
1187 try:
1188 return self._seq[index]
1189 except IndexError:
1190 return None
1191
1192 def removeNamedItem(self, name):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001193 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001194 "NamedNodeMap instance is read-only")
1195
1196 def removeNamedItemNS(self, namespaceURI, localName):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001197 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001198 "NamedNodeMap instance is read-only")
1199
1200 def setNamedItem(self, node):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001201 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001202 "NamedNodeMap instance is read-only")
1203
1204 def setNamedItemNS(self, node):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001205 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001206 "NamedNodeMap instance is read-only")
1207
1208 def __getstate__(self):
1209 return [self._seq]
1210
1211 def __setstate__(self, state):
1212 self._seq = state[0]
1213
1214defproperty(ReadOnlySequentialNamedNodeMap, "length",
1215 doc="Number of entries in the NamedNodeMap.")
Paul Prescod73678da2000-07-01 04:58:47 +00001216
Fred Drakef7cf40d2000-12-14 18:16:11 +00001217
Martin v. Löwis787354c2003-01-25 15:28:29 +00001218class Identified:
1219 """Mix-in class that supports the publicId and systemId attributes."""
1220
Martin v. Löwis995359c2003-01-26 08:59:32 +00001221 # XXX this does not work, this is an old-style class
1222 # __slots__ = 'publicId', 'systemId'
Martin v. Löwis787354c2003-01-25 15:28:29 +00001223
1224 def _identified_mixin_init(self, publicId, systemId):
1225 self.publicId = publicId
1226 self.systemId = systemId
1227
1228 def _get_publicId(self):
1229 return self.publicId
1230
1231 def _get_systemId(self):
1232 return self.systemId
1233
1234class DocumentType(Identified, Childless, Node):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001235 nodeType = Node.DOCUMENT_TYPE_NODE
1236 nodeValue = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001237 name = None
1238 publicId = None
1239 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +00001240 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001241
1242 def __init__(self, qualifiedName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001243 self.entities = ReadOnlySequentialNamedNodeMap()
1244 self.notations = ReadOnlySequentialNamedNodeMap()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001245 if qualifiedName:
1246 prefix, localname = _nssplit(qualifiedName)
1247 self.name = localname
Martin v. Löwis787354c2003-01-25 15:28:29 +00001248 self.nodeName = self.name
1249
1250 def _get_internalSubset(self):
1251 return self.internalSubset
1252
1253 def cloneNode(self, deep):
1254 if self.ownerDocument is None:
1255 # it's ok
1256 clone = DocumentType(None)
1257 clone.name = self.name
1258 clone.nodeName = self.name
Fred Drakefbdeaad2006-07-29 16:56:15 +00001259 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001260 if deep:
1261 clone.entities._seq = []
1262 clone.notations._seq = []
1263 for n in self.notations._seq:
1264 notation = Notation(n.nodeName, n.publicId, n.systemId)
1265 clone.notations._seq.append(notation)
1266 n._call_user_data_handler(operation, n, notation)
1267 for e in self.entities._seq:
1268 entity = Entity(e.nodeName, e.publicId, e.systemId,
1269 e.notationName)
1270 entity.actualEncoding = e.actualEncoding
1271 entity.encoding = e.encoding
1272 entity.version = e.version
1273 clone.entities._seq.append(entity)
1274 e._call_user_data_handler(operation, n, entity)
1275 self._call_user_data_handler(operation, self, clone)
1276 return clone
1277 else:
1278 return None
1279
1280 def writexml(self, writer, indent="", addindent="", newl=""):
1281 writer.write("<!DOCTYPE ")
1282 writer.write(self.name)
1283 if self.publicId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001284 writer.write("%s PUBLIC '%s'%s '%s'"
1285 % (newl, self.publicId, newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001286 elif self.systemId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001287 writer.write("%s SYSTEM '%s'" % (newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001288 if self.internalSubset is not None:
1289 writer.write(" [")
1290 writer.write(self.internalSubset)
1291 writer.write("]")
Georg Brandl175a7dc2005-08-25 22:02:43 +00001292 writer.write(">"+newl)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001293
1294class Entity(Identified, Node):
1295 attributes = None
1296 nodeType = Node.ENTITY_NODE
1297 nodeValue = None
1298
1299 actualEncoding = None
1300 encoding = None
1301 version = None
1302
1303 def __init__(self, name, publicId, systemId, notation):
1304 self.nodeName = name
1305 self.notationName = notation
1306 self.childNodes = NodeList()
1307 self._identified_mixin_init(publicId, systemId)
1308
1309 def _get_actualEncoding(self):
1310 return self.actualEncoding
1311
1312 def _get_encoding(self):
1313 return self.encoding
1314
1315 def _get_version(self):
1316 return self.version
1317
1318 def appendChild(self, newChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001319 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001320 "cannot append children to an entity node")
1321
1322 def insertBefore(self, newChild, refChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001323 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001324 "cannot insert children below an entity node")
1325
1326 def removeChild(self, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001327 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001328 "cannot remove children from an entity node")
1329
1330 def replaceChild(self, newChild, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001331 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001332 "cannot replace children of an entity node")
1333
1334class Notation(Identified, Childless, Node):
1335 nodeType = Node.NOTATION_NODE
1336 nodeValue = None
1337
1338 def __init__(self, name, publicId, systemId):
1339 self.nodeName = name
1340 self._identified_mixin_init(publicId, systemId)
Fred Drakef7cf40d2000-12-14 18:16:11 +00001341
1342
Martin v. Löwis787354c2003-01-25 15:28:29 +00001343class DOMImplementation(DOMImplementationLS):
1344 _features = [("core", "1.0"),
1345 ("core", "2.0"),
1346 ("core", "3.0"),
1347 ("core", None),
1348 ("xml", "1.0"),
1349 ("xml", "2.0"),
1350 ("xml", "3.0"),
1351 ("xml", None),
1352 ("ls-load", "3.0"),
1353 ("ls-load", None),
1354 ]
1355
Fred Drakef7cf40d2000-12-14 18:16:11 +00001356 def hasFeature(self, feature, version):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001357 if version == "":
1358 version = None
1359 return (feature.lower(), version) in self._features
Fred Drakef7cf40d2000-12-14 18:16:11 +00001360
1361 def createDocument(self, namespaceURI, qualifiedName, doctype):
1362 if doctype and doctype.parentNode is not None:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001363 raise xml.dom.WrongDocumentErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001364 "doctype object owned by another DOM tree")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001365 doc = self._create_document()
1366
1367 add_root_element = not (namespaceURI is None
1368 and qualifiedName is None
1369 and doctype is None)
1370
1371 if not qualifiedName and add_root_element:
Martin v. Löwisb417be22001-02-06 01:16:06 +00001372 # The spec is unclear what to raise here; SyntaxErr
1373 # would be the other obvious candidate. Since Xerces raises
1374 # InvalidCharacterErr, and since SyntaxErr is not listed
1375 # for createDocument, that seems to be the better choice.
1376 # XXX: need to check for illegal characters here and in
1377 # createElement.
Martin v. Löwis787354c2003-01-25 15:28:29 +00001378
1379 # DOM Level III clears this up when talking about the return value
1380 # of this function. If namespaceURI, qName and DocType are
1381 # Null the document is returned without a document element
1382 # Otherwise if doctype or namespaceURI are not None
1383 # Then we go back to the above problem
Fred Drakefbdeaad2006-07-29 16:56:15 +00001384 raise xml.dom.InvalidCharacterErr("Element with no name")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001385
1386 if add_root_element:
1387 prefix, localname = _nssplit(qualifiedName)
1388 if prefix == "xml" \
1389 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
Fred Drakefbdeaad2006-07-29 16:56:15 +00001390 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001391 if prefix and not namespaceURI:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001392 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001393 "illegal use of prefix without namespaces")
1394 element = doc.createElementNS(namespaceURI, qualifiedName)
1395 if doctype:
1396 doc.appendChild(doctype)
1397 doc.appendChild(element)
1398
1399 if doctype:
1400 doctype.parentNode = doctype.ownerDocument = doc
1401
Fred Drakef7cf40d2000-12-14 18:16:11 +00001402 doc.doctype = doctype
1403 doc.implementation = self
1404 return doc
1405
1406 def createDocumentType(self, qualifiedName, publicId, systemId):
1407 doctype = DocumentType(qualifiedName)
1408 doctype.publicId = publicId
1409 doctype.systemId = systemId
1410 return doctype
1411
Martin v. Löwis787354c2003-01-25 15:28:29 +00001412 # DOM Level 3 (WD 9 April 2002)
1413
1414 def getInterface(self, feature):
1415 if self.hasFeature(feature, None):
1416 return self
1417 else:
1418 return None
1419
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001420 # internal
Martin v. Löwis787354c2003-01-25 15:28:29 +00001421 def _create_document(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001422 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001423
Fred Drake9ea179f2006-04-06 01:29:04 +00001424class ElementInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001425 """Object that represents content-model information for an element.
1426
1427 This implementation is not expected to be used in practice; DOM
1428 builders should provide implementations which do the right thing
1429 using information available to it.
1430
1431 """
1432
1433 __slots__ = 'tagName',
1434
1435 def __init__(self, name):
1436 self.tagName = name
1437
1438 def getAttributeType(self, aname):
1439 return _no_type
1440
1441 def getAttributeTypeNS(self, namespaceURI, localName):
1442 return _no_type
1443
1444 def isElementContent(self):
1445 return False
1446
1447 def isEmpty(self):
1448 """Returns true iff this element is declared to have an EMPTY
1449 content model."""
1450 return False
1451
1452 def isId(self, aname):
1453 """Returns true iff the named attribte is a DTD-style ID."""
1454 return False
1455
1456 def isIdNS(self, namespaceURI, localName):
1457 """Returns true iff the identified attribute is a DTD-style ID."""
1458 return False
1459
1460 def __getstate__(self):
1461 return self.tagName
1462
1463 def __setstate__(self, state):
1464 self.tagName = state
1465
1466def _clear_id_cache(node):
1467 if node.nodeType == Node.DOCUMENT_NODE:
1468 node._id_cache.clear()
1469 node._id_search_stack = None
1470 elif _in_document(node):
1471 node.ownerDocument._id_cache.clear()
1472 node.ownerDocument._id_search_stack= None
1473
1474class Document(Node, DocumentLS):
1475 _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
1476 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
1477
Fred Drake1f549022000-09-24 05:21:58 +00001478 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +00001479 nodeName = "#document"
1480 nodeValue = None
1481 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001482 doctype = None
1483 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001484 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001485
1486 implementation = DOMImplementation()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001487
1488 # Document attributes from Level 3 (WD 9 April 2002)
1489
1490 actualEncoding = None
1491 encoding = None
1492 standalone = None
1493 version = None
1494 strictErrorChecking = False
1495 errorHandler = None
1496 documentURI = None
1497
1498 _magic_id_count = 0
1499
1500 def __init__(self):
1501 self.childNodes = NodeList()
1502 # mapping of (namespaceURI, localName) -> ElementInfo
1503 # and tagName -> ElementInfo
1504 self._elem_info = {}
1505 self._id_cache = {}
1506 self._id_search_stack = None
1507
1508 def _get_elem_info(self, element):
1509 if element.namespaceURI:
1510 key = element.namespaceURI, element.localName
1511 else:
1512 key = element.tagName
1513 return self._elem_info.get(key)
1514
1515 def _get_actualEncoding(self):
1516 return self.actualEncoding
1517
1518 def _get_doctype(self):
1519 return self.doctype
1520
1521 def _get_documentURI(self):
1522 return self.documentURI
1523
1524 def _get_encoding(self):
1525 return self.encoding
1526
1527 def _get_errorHandler(self):
1528 return self.errorHandler
1529
1530 def _get_standalone(self):
1531 return self.standalone
1532
1533 def _get_strictErrorChecking(self):
1534 return self.strictErrorChecking
1535
1536 def _get_version(self):
1537 return self.version
Fred Drake55c38192000-06-29 19:39:57 +00001538
Fred Drake1f549022000-09-24 05:21:58 +00001539 def appendChild(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001540 if node.nodeType not in self._child_node_types:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001541 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001542 "%s cannot be child of %s" % (repr(node), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001543 if node.parentNode is not None:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001544 # This needs to be done before the next test since this
1545 # may *be* the document element, in which case it should
1546 # end up re-ordered to the end.
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001547 node.parentNode.removeChild(node)
1548
Fred Drakef7cf40d2000-12-14 18:16:11 +00001549 if node.nodeType == Node.ELEMENT_NODE \
1550 and self._get_documentElement():
Fred Drakefbdeaad2006-07-29 16:56:15 +00001551 raise xml.dom.HierarchyRequestErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001552 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +00001553 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +00001554
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001555 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001556 try:
1557 self.childNodes.remove(oldChild)
1558 except ValueError:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001559 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001560 oldChild.nextSibling = oldChild.previousSibling = None
1561 oldChild.parentNode = None
1562 if self.documentElement is oldChild:
1563 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +00001564
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001565 return oldChild
1566
Fred Drakef7cf40d2000-12-14 18:16:11 +00001567 def _get_documentElement(self):
1568 for node in self.childNodes:
1569 if node.nodeType == Node.ELEMENT_NODE:
1570 return node
1571
1572 def unlink(self):
1573 if self.doctype is not None:
1574 self.doctype.unlink()
1575 self.doctype = None
1576 Node.unlink(self)
1577
Martin v. Löwis787354c2003-01-25 15:28:29 +00001578 def cloneNode(self, deep):
1579 if not deep:
1580 return None
1581 clone = self.implementation.createDocument(None, None, None)
1582 clone.encoding = self.encoding
1583 clone.standalone = self.standalone
1584 clone.version = self.version
1585 for n in self.childNodes:
1586 childclone = _clone_node(n, deep, clone)
1587 assert childclone.ownerDocument.isSameNode(clone)
1588 clone.childNodes.append(childclone)
1589 if childclone.nodeType == Node.DOCUMENT_NODE:
1590 assert clone.documentElement is None
1591 elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
1592 assert clone.doctype is None
1593 clone.doctype = childclone
1594 childclone.parentNode = clone
Fred Drakefbdeaad2006-07-29 16:56:15 +00001595 self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
Martin v. Löwis787354c2003-01-25 15:28:29 +00001596 self, clone)
1597 return clone
1598
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001599 def createDocumentFragment(self):
1600 d = DocumentFragment()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001601 d.ownerDocument = self
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001602 return d
Fred Drake55c38192000-06-29 19:39:57 +00001603
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001604 def createElement(self, tagName):
1605 e = Element(tagName)
1606 e.ownerDocument = self
1607 return e
Fred Drake55c38192000-06-29 19:39:57 +00001608
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001609 def createTextNode(self, data):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001610 if not isinstance(data, StringTypes):
1611 raise TypeError, "node contents must be a string"
1612 t = Text()
1613 t.data = data
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001614 t.ownerDocument = self
1615 return t
Fred Drake55c38192000-06-29 19:39:57 +00001616
Fred Drake87432f42001-04-04 14:09:46 +00001617 def createCDATASection(self, data):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001618 if not isinstance(data, StringTypes):
1619 raise TypeError, "node contents must be a string"
1620 c = CDATASection()
1621 c.data = data
Fred Drake87432f42001-04-04 14:09:46 +00001622 c.ownerDocument = self
1623 return c
1624
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001625 def createComment(self, data):
1626 c = Comment(data)
1627 c.ownerDocument = self
1628 return c
Fred Drake55c38192000-06-29 19:39:57 +00001629
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001630 def createProcessingInstruction(self, target, data):
1631 p = ProcessingInstruction(target, data)
1632 p.ownerDocument = self
1633 return p
1634
1635 def createAttribute(self, qName):
1636 a = Attr(qName)
1637 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001638 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001639 return a
Fred Drake55c38192000-06-29 19:39:57 +00001640
1641 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001642 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001643 e = Element(qualifiedName, namespaceURI, prefix)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001644 e.ownerDocument = self
1645 return e
Fred Drake55c38192000-06-29 19:39:57 +00001646
1647 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001648 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001649 a = Attr(qualifiedName, namespaceURI, localName, prefix)
1650 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001651 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001652 return a
Fred Drake55c38192000-06-29 19:39:57 +00001653
Martin v. Löwis787354c2003-01-25 15:28:29 +00001654 # A couple of implementation-specific helpers to create node types
1655 # not supported by the W3C DOM specs:
1656
1657 def _create_entity(self, name, publicId, systemId, notationName):
1658 e = Entity(name, publicId, systemId, notationName)
1659 e.ownerDocument = self
1660 return e
1661
1662 def _create_notation(self, name, publicId, systemId):
1663 n = Notation(name, publicId, systemId)
1664 n.ownerDocument = self
1665 return n
1666
1667 def getElementById(self, id):
Brett Cannon5dd504d2008-08-04 00:23:58 +00001668 if id in self._id_cache:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001669 return self._id_cache[id]
1670 if not (self._elem_info or self._magic_id_count):
1671 return None
1672
1673 stack = self._id_search_stack
1674 if stack is None:
1675 # we never searched before, or the cache has been cleared
1676 stack = [self.documentElement]
1677 self._id_search_stack = stack
1678 elif not stack:
1679 # Previous search was completed and cache is still valid;
1680 # no matching node.
1681 return None
1682
1683 result = None
1684 while stack:
1685 node = stack.pop()
1686 # add child elements to stack for continued searching
1687 stack.extend([child for child in node.childNodes
1688 if child.nodeType in _nodeTypes_with_children])
1689 # check this node
1690 info = self._get_elem_info(node)
1691 if info:
1692 # We have to process all ID attributes before
1693 # returning in order to get all the attributes set to
1694 # be IDs using Element.setIdAttribute*().
1695 for attr in node.attributes.values():
1696 if attr.namespaceURI:
1697 if info.isIdNS(attr.namespaceURI, attr.localName):
1698 self._id_cache[attr.value] = node
1699 if attr.value == id:
1700 result = node
1701 elif not node._magic_id_nodes:
1702 break
1703 elif info.isId(attr.name):
1704 self._id_cache[attr.value] = node
1705 if attr.value == id:
1706 result = node
1707 elif not node._magic_id_nodes:
1708 break
1709 elif attr._is_id:
1710 self._id_cache[attr.value] = node
1711 if attr.value == id:
1712 result = node
1713 elif node._magic_id_nodes == 1:
1714 break
1715 elif node._magic_id_nodes:
1716 for attr in node.attributes.values():
1717 if attr._is_id:
1718 self._id_cache[attr.value] = node
1719 if attr.value == id:
1720 result = node
1721 if result is not None:
1722 break
1723 return result
1724
Fred Drake1f549022000-09-24 05:21:58 +00001725 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001726 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drakefbe7b4f2001-07-04 06:25:53 +00001727
1728 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001729 return _get_elements_by_tagName_ns_helper(
1730 self, namespaceURI, localName, NodeList())
1731
1732 def isSupported(self, feature, version):
1733 return self.implementation.hasFeature(feature, version)
1734
1735 def importNode(self, node, deep):
1736 if node.nodeType == Node.DOCUMENT_NODE:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001737 raise xml.dom.NotSupportedErr("cannot import document nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001738 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001739 raise xml.dom.NotSupportedErr("cannot import document type nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001740 return _clone_node(node, deep, self)
Fred Drake55c38192000-06-29 19:39:57 +00001741
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001742 def writexml(self, writer, indent="", addindent="", newl="",
1743 encoding = None):
1744 if encoding is None:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001745 writer.write('<?xml version="1.0" ?>'+newl)
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001746 else:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001747 writer.write('<?xml version="1.0" encoding="%s"?>%s' % (encoding, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001748 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001749 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +00001750
Martin v. Löwis787354c2003-01-25 15:28:29 +00001751 # DOM Level 3 (WD 9 April 2002)
1752
1753 def renameNode(self, n, namespaceURI, name):
1754 if n.ownerDocument is not self:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001755 raise xml.dom.WrongDocumentErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001756 "cannot rename nodes from other documents;\n"
1757 "expected %s,\nfound %s" % (self, n.ownerDocument))
1758 if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001759 raise xml.dom.NotSupportedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001760 "renameNode() only applies to element and attribute nodes")
1761 if namespaceURI != EMPTY_NAMESPACE:
1762 if ':' in name:
1763 prefix, localName = name.split(':', 1)
1764 if ( prefix == "xmlns"
Fred Drakefbdeaad2006-07-29 16:56:15 +00001765 and namespaceURI != xml.dom.XMLNS_NAMESPACE):
1766 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001767 "illegal use of 'xmlns' prefix")
1768 else:
1769 if ( name == "xmlns"
Fred Drakefbdeaad2006-07-29 16:56:15 +00001770 and namespaceURI != xml.dom.XMLNS_NAMESPACE
Martin v. Löwis787354c2003-01-25 15:28:29 +00001771 and n.nodeType == Node.ATTRIBUTE_NODE):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001772 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001773 "illegal use of the 'xmlns' attribute")
1774 prefix = None
1775 localName = name
1776 else:
1777 prefix = None
1778 localName = None
1779 if n.nodeType == Node.ATTRIBUTE_NODE:
1780 element = n.ownerElement
1781 if element is not None:
1782 is_id = n._is_id
1783 element.removeAttributeNode(n)
1784 else:
1785 element = None
1786 # avoid __setattr__
1787 d = n.__dict__
1788 d['prefix'] = prefix
1789 d['localName'] = localName
1790 d['namespaceURI'] = namespaceURI
1791 d['nodeName'] = name
1792 if n.nodeType == Node.ELEMENT_NODE:
1793 d['tagName'] = name
1794 else:
1795 # attribute node
1796 d['name'] = name
1797 if element is not None:
1798 element.setAttributeNode(n)
1799 if is_id:
1800 element.setIdAttributeNode(n)
1801 # It's not clear from a semantic perspective whether we should
1802 # call the user data handlers for the NODE_RENAMED event since
1803 # we're re-using the existing node. The draft spec has been
1804 # interpreted as meaning "no, don't call the handler unless a
1805 # new node is created."
1806 return n
1807
1808defproperty(Document, "documentElement",
1809 doc="Top-level element of this document.")
1810
1811
1812def _clone_node(node, deep, newOwnerDocument):
1813 """
1814 Clone a node and give it the new owner document.
1815 Called by Node.cloneNode and Document.importNode
1816 """
1817 if node.ownerDocument.isSameNode(newOwnerDocument):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001818 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001819 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001820 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001821 if node.nodeType == Node.ELEMENT_NODE:
1822 clone = newOwnerDocument.createElementNS(node.namespaceURI,
1823 node.nodeName)
1824 for attr in node.attributes.values():
1825 clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
1826 a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
1827 a.specified = attr.specified
1828
1829 if deep:
1830 for child in node.childNodes:
1831 c = _clone_node(child, deep, newOwnerDocument)
1832 clone.appendChild(c)
1833
1834 elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
1835 clone = newOwnerDocument.createDocumentFragment()
1836 if deep:
1837 for child in node.childNodes:
1838 c = _clone_node(child, deep, newOwnerDocument)
1839 clone.appendChild(c)
1840
1841 elif node.nodeType == Node.TEXT_NODE:
1842 clone = newOwnerDocument.createTextNode(node.data)
1843 elif node.nodeType == Node.CDATA_SECTION_NODE:
1844 clone = newOwnerDocument.createCDATASection(node.data)
1845 elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
1846 clone = newOwnerDocument.createProcessingInstruction(node.target,
1847 node.data)
1848 elif node.nodeType == Node.COMMENT_NODE:
1849 clone = newOwnerDocument.createComment(node.data)
1850 elif node.nodeType == Node.ATTRIBUTE_NODE:
1851 clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
1852 node.nodeName)
1853 clone.specified = True
1854 clone.value = node.value
1855 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
1856 assert node.ownerDocument is not newOwnerDocument
Fred Drakefbdeaad2006-07-29 16:56:15 +00001857 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001858 clone = newOwnerDocument.implementation.createDocumentType(
1859 node.name, node.publicId, node.systemId)
1860 clone.ownerDocument = newOwnerDocument
1861 if deep:
1862 clone.entities._seq = []
1863 clone.notations._seq = []
1864 for n in node.notations._seq:
1865 notation = Notation(n.nodeName, n.publicId, n.systemId)
1866 notation.ownerDocument = newOwnerDocument
1867 clone.notations._seq.append(notation)
1868 if hasattr(n, '_call_user_data_handler'):
1869 n._call_user_data_handler(operation, n, notation)
1870 for e in node.entities._seq:
1871 entity = Entity(e.nodeName, e.publicId, e.systemId,
1872 e.notationName)
1873 entity.actualEncoding = e.actualEncoding
1874 entity.encoding = e.encoding
1875 entity.version = e.version
1876 entity.ownerDocument = newOwnerDocument
1877 clone.entities._seq.append(entity)
1878 if hasattr(e, '_call_user_data_handler'):
1879 e._call_user_data_handler(operation, n, entity)
1880 else:
1881 # Note the cloning of Document and DocumentType nodes is
1882 # implemenetation specific. minidom handles those cases
1883 # directly in the cloneNode() methods.
Fred Drakefbdeaad2006-07-29 16:56:15 +00001884 raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001885
1886 # Check for _call_user_data_handler() since this could conceivably
1887 # used with other DOM implementations (one of the FourThought
1888 # DOMs, perhaps?).
1889 if hasattr(node, '_call_user_data_handler'):
1890 node._call_user_data_handler(operation, node, clone)
1891 return clone
1892
1893
1894def _nssplit(qualifiedName):
1895 fields = qualifiedName.split(':', 1)
1896 if len(fields) == 2:
1897 return fields
1898 else:
1899 return (None, fields[0])
1900
1901
Fred Drake4ccf4a12000-11-21 22:02:22 +00001902def _get_StringIO():
Fred Drakef7cf40d2000-12-14 18:16:11 +00001903 # we can't use cStringIO since it doesn't support Unicode strings
1904 from StringIO import StringIO
Fred Drake4ccf4a12000-11-21 22:02:22 +00001905 return StringIO()
1906
Martin v. Löwis787354c2003-01-25 15:28:29 +00001907def _do_pulldom_parse(func, args, kwargs):
Raymond Hettingerff41c482003-04-06 09:01:11 +00001908 events = func(*args, **kwargs)
Fred Drake1f549022000-09-24 05:21:58 +00001909 toktype, rootNode = events.getEvent()
1910 events.expandNode(rootNode)
Martin v. Löwisb417be22001-02-06 01:16:06 +00001911 events.clear()
Fred Drake55c38192000-06-29 19:39:57 +00001912 return rootNode
1913
Martin v. Löwis787354c2003-01-25 15:28:29 +00001914def parse(file, parser=None, bufsize=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001915 """Parse a file into a DOM by filename or file object."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001916 if parser is None and not bufsize:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001917 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001918 return expatbuilder.parse(file)
1919 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001920 from xml.dom import pulldom
Raymond Hettingerff41c482003-04-06 09:01:11 +00001921 return _do_pulldom_parse(pulldom.parse, (file,),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001922 {'parser': parser, 'bufsize': bufsize})
Fred Drake55c38192000-06-29 19:39:57 +00001923
Martin v. Löwis787354c2003-01-25 15:28:29 +00001924def parseString(string, parser=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001925 """Parse a file into a DOM from a string."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001926 if parser is None:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001927 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001928 return expatbuilder.parseString(string)
1929 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001930 from xml.dom import pulldom
Martin v. Löwis787354c2003-01-25 15:28:29 +00001931 return _do_pulldom_parse(pulldom.parseString, (string,),
1932 {'parser': parser})
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001933
Martin v. Löwis787354c2003-01-25 15:28:29 +00001934def getDOMImplementation(features=None):
1935 if features:
1936 if isinstance(features, StringTypes):
1937 features = domreg._parse_feature_string(features)
1938 for f, v in features:
1939 if not Document.implementation.hasFeature(f, v):
1940 return None
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001941 return Document.implementation