blob: 7518852798ba4a72021f97f56973a07b1dd7114b [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:
R. David Murray0374a822009-04-09 21:54:50 +0000180 if not child.data:
181 # empty text node; discard
182 if L:
183 L[-1].nextSibling = child.nextSibling
184 if child.nextSibling:
185 child.nextSibling.previousSibling = child.previousSibling
186 child.unlink()
187 elif L and L[-1].nodeType == child.nodeType:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000188 # collapse text node
189 node = L[-1]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000190 node.data = node.data + child.data
Fred Drake4ccf4a12000-11-21 22:02:22 +0000191 node.nextSibling = child.nextSibling
R. David Murray0374a822009-04-09 21:54:50 +0000192 if child.nextSibling:
193 child.nextSibling.previousSibling = node
Fred Drake4ccf4a12000-11-21 22:02:22 +0000194 child.unlink()
R. David Murray0374a822009-04-09 21:54:50 +0000195 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000196 L.append(child)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000197 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000198 L.append(child)
199 if child.nodeType == Node.ELEMENT_NODE:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000200 child.normalize()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000201 self.childNodes[:] = L
Paul Prescod73678da2000-07-01 04:58:47 +0000202
Fred Drake1f549022000-09-24 05:21:58 +0000203 def cloneNode(self, deep):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000204 return _clone_node(self, deep, self.ownerDocument or self)
Fred Drake55c38192000-06-29 19:39:57 +0000205
Martin v. Löwis787354c2003-01-25 15:28:29 +0000206 def isSupported(self, feature, version):
207 return self.ownerDocument.implementation.hasFeature(feature, version)
208
209 def _get_localName(self):
210 # Overridden in Element and Attr where localName can be Non-Null
211 return None
212
213 # Node interfaces from Level 3 (WD 9 April 2002)
Fred Drake25239772001-02-02 19:40:19 +0000214
215 def isSameNode(self, other):
216 return self is other
217
Martin v. Löwis787354c2003-01-25 15:28:29 +0000218 def getInterface(self, feature):
219 if self.isSupported(feature, None):
220 return self
221 else:
222 return None
223
224 # The "user data" functions use a dictionary that is only present
225 # if some user data has been set, so be careful not to assume it
226 # exists.
227
228 def getUserData(self, key):
229 try:
230 return self._user_data[key][0]
231 except (AttributeError, KeyError):
232 return None
233
234 def setUserData(self, key, data, handler):
235 old = None
236 try:
237 d = self._user_data
238 except AttributeError:
239 d = {}
240 self._user_data = d
Brett Cannon5dd504d2008-08-04 00:23:58 +0000241 if key in d:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000242 old = d[key][0]
243 if data is None:
244 # ignore handlers passed for None
245 handler = None
246 if old is not None:
247 del d[key]
248 else:
249 d[key] = (data, handler)
250 return old
251
252 def _call_user_data_handler(self, operation, src, dst):
253 if hasattr(self, "_user_data"):
254 for key, (data, handler) in self._user_data.items():
255 if handler is not None:
256 handler.handle(operation, key, data, src, dst)
257
Fred Drake25239772001-02-02 19:40:19 +0000258 # minidom-specific API:
259
Fred Drake1f549022000-09-24 05:21:58 +0000260 def unlink(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000261 self.parentNode = self.ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000262 if self.childNodes:
263 for child in self.childNodes:
264 child.unlink()
265 self.childNodes = NodeList()
Paul Prescod4221ff02000-10-13 20:11:42 +0000266 self.previousSibling = None
267 self.nextSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000268
269defproperty(Node, "firstChild", doc="First child node, or None.")
270defproperty(Node, "lastChild", doc="Last child node, or None.")
271defproperty(Node, "localName", doc="Namespace-local name of this node.")
272
273
274def _append_child(self, node):
275 # fast path with less checks; usable by DOM builders if careful
276 childNodes = self.childNodes
277 if childNodes:
278 last = childNodes[-1]
279 node.__dict__["previousSibling"] = last
280 last.__dict__["nextSibling"] = node
281 childNodes.append(node)
282 node.__dict__["parentNode"] = self
283
284def _in_document(node):
285 # return True iff node is part of a document tree
286 while node is not None:
287 if node.nodeType == Node.DOCUMENT_NODE:
288 return True
289 node = node.parentNode
290 return False
Fred Drake55c38192000-06-29 19:39:57 +0000291
Fred Drake1f549022000-09-24 05:21:58 +0000292def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000293 "Writes datachars to writer."
Georg Brandl5ded7912010-11-26 07:35:31 +0000294 if data:
295 data = data.replace("&", "&amp;").replace("<", "&lt;"). \
296 replace("\"", "&quot;").replace(">", "&gt;")
297 writer.write(data)
Fred Drake55c38192000-06-29 19:39:57 +0000298
Martin v. Löwis787354c2003-01-25 15:28:29 +0000299def _get_elements_by_tagName_helper(parent, name, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000300 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000301 if node.nodeType == Node.ELEMENT_NODE and \
302 (name == "*" or node.tagName == name):
303 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000304 _get_elements_by_tagName_helper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000305 return rc
306
Martin v. Löwis787354c2003-01-25 15:28:29 +0000307def _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000308 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000309 if node.nodeType == Node.ELEMENT_NODE:
Martin v. Löwised525fb2001-06-03 14:06:42 +0000310 if ((localName == "*" or node.localName == localName) and
Fred Drake1f549022000-09-24 05:21:58 +0000311 (nsURI == "*" or node.namespaceURI == nsURI)):
312 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000313 _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000314 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000315
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000316class DocumentFragment(Node):
317 nodeType = Node.DOCUMENT_FRAGMENT_NODE
318 nodeName = "#document-fragment"
319 nodeValue = None
320 attributes = None
321 parentNode = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000322 _child_node_types = (Node.ELEMENT_NODE,
323 Node.TEXT_NODE,
324 Node.CDATA_SECTION_NODE,
325 Node.ENTITY_REFERENCE_NODE,
326 Node.PROCESSING_INSTRUCTION_NODE,
327 Node.COMMENT_NODE,
328 Node.NOTATION_NODE)
329
330 def __init__(self):
331 self.childNodes = NodeList()
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000332
333
Fred Drake55c38192000-06-29 19:39:57 +0000334class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000335 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000336 attributes = None
337 ownerElement = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000338 specified = False
339 _is_id = False
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000340
Martin v. Löwis787354c2003-01-25 15:28:29 +0000341 _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
342
343 def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
344 prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000345 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000346 d = self.__dict__
Fred Drake4ccf4a12000-11-21 22:02:22 +0000347 d["nodeName"] = d["name"] = qName
348 d["namespaceURI"] = namespaceURI
349 d["prefix"] = prefix
Martin v. Löwis787354c2003-01-25 15:28:29 +0000350 d['childNodes'] = NodeList()
351
352 # Add the single child node that represents the value of the attr
353 self.childNodes.append(Text())
354
Paul Prescod73678da2000-07-01 04:58:47 +0000355 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000356
Martin v. Löwis787354c2003-01-25 15:28:29 +0000357 def _get_localName(self):
358 return self.nodeName.split(":", 1)[-1]
359
360 def _get_name(self):
361 return self.name
362
363 def _get_specified(self):
364 return self.specified
365
Fred Drake1f549022000-09-24 05:21:58 +0000366 def __setattr__(self, name, value):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000367 d = self.__dict__
Fred Drake1f549022000-09-24 05:21:58 +0000368 if name in ("value", "nodeValue"):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000369 d["value"] = d["nodeValue"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000370 d2 = self.childNodes[0].__dict__
371 d2["data"] = d2["nodeValue"] = value
372 if self.ownerElement is not None:
373 _clear_id_cache(self.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000374 elif name in ("name", "nodeName"):
375 d["name"] = d["nodeName"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000376 if self.ownerElement is not None:
377 _clear_id_cache(self.ownerElement)
Fred Drake55c38192000-06-29 19:39:57 +0000378 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000379 d[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000380
Martin v. Löwis995359c2003-01-26 08:59:32 +0000381 def _set_prefix(self, prefix):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000382 nsuri = self.namespaceURI
Martin v. Löwis995359c2003-01-26 08:59:32 +0000383 if prefix == "xmlns":
384 if nsuri and nsuri != XMLNS_NAMESPACE:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000385 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000386 "illegal use of 'xmlns' prefix for the wrong namespace")
387 d = self.__dict__
388 d['prefix'] = prefix
389 if prefix is None:
390 newName = self.localName
391 else:
Martin v. Löwis995359c2003-01-26 08:59:32 +0000392 newName = "%s:%s" % (prefix, self.localName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000393 if self.ownerElement:
394 _clear_id_cache(self.ownerElement)
395 d['nodeName'] = d['name'] = newName
396
397 def _set_value(self, value):
398 d = self.__dict__
399 d['value'] = d['nodeValue'] = value
400 if self.ownerElement:
401 _clear_id_cache(self.ownerElement)
402 self.childNodes[0].data = value
403
404 def unlink(self):
405 # This implementation does not call the base implementation
406 # since most of that is not needed, and the expense of the
407 # method call is not warranted. We duplicate the removal of
408 # children, but that's all we needed from the base class.
409 elem = self.ownerElement
410 if elem is not None:
411 del elem._attrs[self.nodeName]
412 del elem._attrsNS[(self.namespaceURI, self.localName)]
413 if self._is_id:
414 self._is_id = False
415 elem._magic_id_nodes -= 1
416 self.ownerDocument._magic_id_count -= 1
417 for child in self.childNodes:
418 child.unlink()
419 del self.childNodes[:]
420
421 def _get_isId(self):
422 if self._is_id:
423 return True
424 doc = self.ownerDocument
425 elem = self.ownerElement
426 if doc is None or elem is None:
427 return False
428
429 info = doc._get_elem_info(elem)
430 if info is None:
431 return False
432 if self.namespaceURI:
433 return info.isIdNS(self.namespaceURI, self.localName)
434 else:
435 return info.isId(self.nodeName)
436
437 def _get_schemaType(self):
438 doc = self.ownerDocument
439 elem = self.ownerElement
440 if doc is None or elem is None:
441 return _no_type
442
443 info = doc._get_elem_info(elem)
444 if info is None:
445 return _no_type
446 if self.namespaceURI:
447 return info.getAttributeTypeNS(self.namespaceURI, self.localName)
448 else:
449 return info.getAttributeType(self.nodeName)
450
451defproperty(Attr, "isId", doc="True if this attribute is an ID.")
452defproperty(Attr, "localName", doc="Namespace-local name of this attribute.")
453defproperty(Attr, "schemaType", doc="Schema type for this attribute.")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000454
Fred Drakef7cf40d2000-12-14 18:16:11 +0000455
Fred Drake9ea179f2006-04-06 01:29:04 +0000456class NamedNodeMap(object):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000457 """The attribute list is a transient interface to the underlying
458 dictionaries. Mutations here will change the underlying element's
Fred Drakef7cf40d2000-12-14 18:16:11 +0000459 dictionary.
460
461 Ordering is imposed artificially and does not reflect the order of
462 attributes as found in an input document.
463 """
Fred Drake4ccf4a12000-11-21 22:02:22 +0000464
Martin v. Löwis787354c2003-01-25 15:28:29 +0000465 __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
466
Fred Drake2998a552001-12-06 18:27:48 +0000467 def __init__(self, attrs, attrsNS, ownerElement):
Fred Drake1f549022000-09-24 05:21:58 +0000468 self._attrs = attrs
469 self._attrsNS = attrsNS
Fred Drake2998a552001-12-06 18:27:48 +0000470 self._ownerElement = ownerElement
Fred Drakef7cf40d2000-12-14 18:16:11 +0000471
Martin v. Löwis787354c2003-01-25 15:28:29 +0000472 def _get_length(self):
473 return len(self._attrs)
Fred Drake55c38192000-06-29 19:39:57 +0000474
Fred Drake1f549022000-09-24 05:21:58 +0000475 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000476 try:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000477 return self[self._attrs.keys()[index]]
Fred Drake55c38192000-06-29 19:39:57 +0000478 except IndexError:
479 return None
Fred Drake55c38192000-06-29 19:39:57 +0000480
Fred Drake1f549022000-09-24 05:21:58 +0000481 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000482 L = []
483 for node in self._attrs.values():
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000484 L.append((node.nodeName, node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000485 return L
Fred Drake1f549022000-09-24 05:21:58 +0000486
487 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000488 L = []
489 for node in self._attrs.values():
Fred Drake49a5d032001-11-30 22:21:58 +0000490 L.append(((node.namespaceURI, node.localName), node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000491 return L
Fred Drake16f63292000-10-23 18:09:50 +0000492
Martin v. Löwis787354c2003-01-25 15:28:29 +0000493 def has_key(self, key):
494 if isinstance(key, StringTypes):
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000495 return key in self._attrs
Martin v. Löwis787354c2003-01-25 15:28:29 +0000496 else:
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000497 return key in self._attrsNS
Martin v. Löwis787354c2003-01-25 15:28:29 +0000498
Fred Drake1f549022000-09-24 05:21:58 +0000499 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000500 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000501
Fred Drake1f549022000-09-24 05:21:58 +0000502 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000503 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000504
Fred Drake1f549022000-09-24 05:21:58 +0000505 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000506 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000507
Martin v. Löwis787354c2003-01-25 15:28:29 +0000508 def get(self, name, value=None):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000509 return self._attrs.get(name, value)
510
Martin v. Löwis787354c2003-01-25 15:28:29 +0000511 __len__ = _get_length
Fred Drake55c38192000-06-29 19:39:57 +0000512
Nick Coghlan48361f52008-08-11 15:45:58 +0000513 __hash__ = None # Mutable type can't be correctly hashed
Fred Drake1f549022000-09-24 05:21:58 +0000514 def __cmp__(self, other):
515 if self._attrs is getattr(other, "_attrs", None):
Fred Drake55c38192000-06-29 19:39:57 +0000516 return 0
Fred Drake16f63292000-10-23 18:09:50 +0000517 else:
Fred Drake1f549022000-09-24 05:21:58 +0000518 return cmp(id(self), id(other))
Fred Drake55c38192000-06-29 19:39:57 +0000519
Fred Drake1f549022000-09-24 05:21:58 +0000520 def __getitem__(self, attname_or_tuple):
Fred Drake70d044b2006-04-06 01:32:26 +0000521 if isinstance(attname_or_tuple, tuple):
Paul Prescod73678da2000-07-01 04:58:47 +0000522 return self._attrsNS[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000523 else:
Paul Prescod73678da2000-07-01 04:58:47 +0000524 return self._attrs[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000525
Paul Prescod1e688272000-07-01 19:21:47 +0000526 # same as set
Fred Drake1f549022000-09-24 05:21:58 +0000527 def __setitem__(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000528 if isinstance(value, StringTypes):
529 try:
530 node = self._attrs[attname]
531 except KeyError:
532 node = Attr(attname)
533 node.ownerDocument = self._ownerElement.ownerDocument
Martin v. Löwis995359c2003-01-26 08:59:32 +0000534 self.setNamedItem(node)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000535 node.value = value
Paul Prescod1e688272000-07-01 19:21:47 +0000536 else:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000537 if not isinstance(value, Attr):
538 raise TypeError, "value must be a string or Attr object"
Fred Drake1f549022000-09-24 05:21:58 +0000539 node = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000540 self.setNamedItem(node)
541
542 def getNamedItem(self, name):
543 try:
544 return self._attrs[name]
545 except KeyError:
546 return None
547
548 def getNamedItemNS(self, namespaceURI, localName):
549 try:
550 return self._attrsNS[(namespaceURI, localName)]
551 except KeyError:
552 return None
553
554 def removeNamedItem(self, name):
555 n = self.getNamedItem(name)
556 if n is not None:
557 _clear_id_cache(self._ownerElement)
558 del self._attrs[n.nodeName]
559 del self._attrsNS[(n.namespaceURI, n.localName)]
Brett Cannon5dd504d2008-08-04 00:23:58 +0000560 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000561 n.__dict__['ownerElement'] = None
562 return n
563 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000564 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000565
566 def removeNamedItemNS(self, namespaceURI, localName):
567 n = self.getNamedItemNS(namespaceURI, localName)
568 if n is not None:
569 _clear_id_cache(self._ownerElement)
570 del self._attrsNS[(n.namespaceURI, n.localName)]
571 del self._attrs[n.nodeName]
Brett Cannon5dd504d2008-08-04 00:23:58 +0000572 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000573 n.__dict__['ownerElement'] = None
574 return n
575 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000576 raise xml.dom.NotFoundErr()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000577
578 def setNamedItem(self, node):
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000579 if not isinstance(node, Attr):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000580 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000581 "%s cannot be child of %s" % (repr(node), repr(self)))
Fred Drakef7cf40d2000-12-14 18:16:11 +0000582 old = self._attrs.get(node.name)
Paul Prescod1e688272000-07-01 19:21:47 +0000583 if old:
584 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000585 self._attrs[node.name] = node
586 self._attrsNS[(node.namespaceURI, node.localName)] = node
Fred Drake2998a552001-12-06 18:27:48 +0000587 node.ownerElement = self._ownerElement
Martin v. Löwis787354c2003-01-25 15:28:29 +0000588 _clear_id_cache(node.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000589 return old
590
591 def setNamedItemNS(self, node):
592 return self.setNamedItem(node)
Paul Prescod73678da2000-07-01 04:58:47 +0000593
Fred Drake1f549022000-09-24 05:21:58 +0000594 def __delitem__(self, attname_or_tuple):
595 node = self[attname_or_tuple]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000596 _clear_id_cache(node.ownerElement)
Paul Prescod73678da2000-07-01 04:58:47 +0000597 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000598
599 def __getstate__(self):
600 return self._attrs, self._attrsNS, self._ownerElement
601
602 def __setstate__(self, state):
603 self._attrs, self._attrsNS, self._ownerElement = state
604
605defproperty(NamedNodeMap, "length",
606 doc="Number of nodes in the NamedNodeMap.")
Fred Drakef7cf40d2000-12-14 18:16:11 +0000607
608AttributeList = NamedNodeMap
609
Fred Drake1f549022000-09-24 05:21:58 +0000610
Fred Drake9ea179f2006-04-06 01:29:04 +0000611class TypeInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000612 __slots__ = 'namespace', 'name'
613
614 def __init__(self, namespace, name):
615 self.namespace = namespace
616 self.name = name
617
618 def __repr__(self):
619 if self.namespace:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000620 return "<TypeInfo %r (from %r)>" % (self.name, self.namespace)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000621 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000622 return "<TypeInfo %r>" % self.name
Martin v. Löwis787354c2003-01-25 15:28:29 +0000623
624 def _get_name(self):
625 return self.name
626
627 def _get_namespace(self):
628 return self.namespace
629
630_no_type = TypeInfo(None, None)
631
Martin v. Löwisa2fda0d2000-10-07 12:10:28 +0000632class Element(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000633 nodeType = Node.ELEMENT_NODE
Martin v. Löwis787354c2003-01-25 15:28:29 +0000634 nodeValue = None
635 schemaType = _no_type
636
637 _magic_id_nodes = 0
638
639 _child_node_types = (Node.ELEMENT_NODE,
640 Node.PROCESSING_INSTRUCTION_NODE,
641 Node.COMMENT_NODE,
642 Node.TEXT_NODE,
643 Node.CDATA_SECTION_NODE,
644 Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000645
Fred Drake49a5d032001-11-30 22:21:58 +0000646 def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
Fred Drake1f549022000-09-24 05:21:58 +0000647 localName=None):
Fred Drake55c38192000-06-29 19:39:57 +0000648 self.tagName = self.nodeName = tagName
Fred Drake1f549022000-09-24 05:21:58 +0000649 self.prefix = prefix
650 self.namespaceURI = namespaceURI
Martin v. Löwis787354c2003-01-25 15:28:29 +0000651 self.childNodes = NodeList()
Fred Drake55c38192000-06-29 19:39:57 +0000652
Fred Drake4ccf4a12000-11-21 22:02:22 +0000653 self._attrs = {} # attributes are double-indexed:
654 self._attrsNS = {} # tagName -> Attribute
655 # URI,localName -> Attribute
656 # in the future: consider lazy generation
657 # of attribute objects this is too tricky
658 # for now because of headaches with
659 # namespaces.
660
Martin v. Löwis787354c2003-01-25 15:28:29 +0000661 def _get_localName(self):
662 return self.tagName.split(":", 1)[-1]
663
664 def _get_tagName(self):
665 return self.tagName
Fred Drake4ccf4a12000-11-21 22:02:22 +0000666
667 def unlink(self):
668 for attr in self._attrs.values():
669 attr.unlink()
670 self._attrs = None
671 self._attrsNS = None
672 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000673
Fred Drake1f549022000-09-24 05:21:58 +0000674 def getAttribute(self, attname):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000675 try:
676 return self._attrs[attname].value
677 except KeyError:
678 return ""
Fred Drake55c38192000-06-29 19:39:57 +0000679
Fred Drake1f549022000-09-24 05:21:58 +0000680 def getAttributeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000681 try:
682 return self._attrsNS[(namespaceURI, localName)].value
683 except KeyError:
684 return ""
Fred Drake1f549022000-09-24 05:21:58 +0000685
686 def setAttribute(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000687 attr = self.getAttributeNode(attname)
688 if attr is None:
689 attr = Attr(attname)
690 # for performance
691 d = attr.__dict__
692 d["value"] = d["nodeValue"] = value
693 d["ownerDocument"] = self.ownerDocument
694 self.setAttributeNode(attr)
695 elif value != attr.value:
696 d = attr.__dict__
697 d["value"] = d["nodeValue"] = value
698 if attr.isId:
699 _clear_id_cache(self)
Fred Drake55c38192000-06-29 19:39:57 +0000700
Fred Drake1f549022000-09-24 05:21:58 +0000701 def setAttributeNS(self, namespaceURI, qualifiedName, value):
702 prefix, localname = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000703 attr = self.getAttributeNodeNS(namespaceURI, localname)
704 if attr is None:
705 # for performance
706 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
707 d = attr.__dict__
708 d["prefix"] = prefix
709 d["nodeName"] = qualifiedName
710 d["value"] = d["nodeValue"] = value
711 d["ownerDocument"] = self.ownerDocument
712 self.setAttributeNode(attr)
713 else:
714 d = attr.__dict__
715 if value != attr.value:
716 d["value"] = d["nodeValue"] = value
717 if attr.isId:
718 _clear_id_cache(self)
719 if attr.prefix != prefix:
720 d["prefix"] = prefix
721 d["nodeName"] = qualifiedName
Fred Drake55c38192000-06-29 19:39:57 +0000722
Fred Drake1f549022000-09-24 05:21:58 +0000723 def getAttributeNode(self, attrname):
724 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000725
Fred Drake1f549022000-09-24 05:21:58 +0000726 def getAttributeNodeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000727 return self._attrsNS.get((namespaceURI, localName))
Paul Prescod73678da2000-07-01 04:58:47 +0000728
Fred Drake1f549022000-09-24 05:21:58 +0000729 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000730 if attr.ownerElement not in (None, self):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000731 raise xml.dom.InuseAttributeErr("attribute node already owned")
Martin v. Löwis787354c2003-01-25 15:28:29 +0000732 old1 = self._attrs.get(attr.name, None)
733 if old1 is not None:
734 self.removeAttributeNode(old1)
735 old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
736 if old2 is not None and old2 is not old1:
737 self.removeAttributeNode(old2)
738 _set_attribute_node(self, attr)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000739
Martin v. Löwis787354c2003-01-25 15:28:29 +0000740 if old1 is not attr:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000741 # It might have already been part of this node, in which case
742 # it doesn't represent a change, and should not be returned.
Martin v. Löwis787354c2003-01-25 15:28:29 +0000743 return old1
744 if old2 is not attr:
745 return old2
Fred Drake55c38192000-06-29 19:39:57 +0000746
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000747 setAttributeNodeNS = setAttributeNode
748
Fred Drake1f549022000-09-24 05:21:58 +0000749 def removeAttribute(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000750 try:
751 attr = self._attrs[name]
752 except KeyError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000753 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000754 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000755
Fred Drake1f549022000-09-24 05:21:58 +0000756 def removeAttributeNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000757 try:
758 attr = self._attrsNS[(namespaceURI, localName)]
759 except KeyError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000760 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000761 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000762
Fred Drake1f549022000-09-24 05:21:58 +0000763 def removeAttributeNode(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000764 if node is None:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000765 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000766 try:
767 self._attrs[node.name]
768 except KeyError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000769 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000770 _clear_id_cache(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000771 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000772 # Restore this since the node is still useful and otherwise
773 # unlinked
774 node.ownerDocument = self.ownerDocument
Fred Drake16f63292000-10-23 18:09:50 +0000775
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000776 removeAttributeNodeNS = removeAttributeNode
777
Martin v. Löwis156c3372000-12-28 18:40:56 +0000778 def hasAttribute(self, name):
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000779 return name in self._attrs
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000780
Martin v. Löwis156c3372000-12-28 18:40:56 +0000781 def hasAttributeNS(self, namespaceURI, localName):
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000782 return (namespaceURI, localName) in self._attrsNS
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000783
Fred Drake1f549022000-09-24 05:21:58 +0000784 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000785 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000786
Fred Drake1f549022000-09-24 05:21:58 +0000787 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000788 return _get_elements_by_tagName_ns_helper(
789 self, namespaceURI, localName, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000790
Fred Drake1f549022000-09-24 05:21:58 +0000791 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000792 return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000793
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000794 def writexml(self, writer, indent="", addindent="", newl=""):
795 # indent = current indentation
796 # addindent = indentation to add to higher levels
797 # newl = newline string
798 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000799
Fred Drake4ccf4a12000-11-21 22:02:22 +0000800 attrs = self._get_attributes()
801 a_names = attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000802 a_names.sort()
803
804 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000805 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000806 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000807 writer.write("\"")
808 if self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000809 writer.write(">%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000810 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000811 node.writexml(writer,indent+addindent,addindent,newl)
812 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
Fred Drake55c38192000-06-29 19:39:57 +0000813 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000814 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000815
Fred Drake1f549022000-09-24 05:21:58 +0000816 def _get_attributes(self):
Fred Drake2998a552001-12-06 18:27:48 +0000817 return NamedNodeMap(self._attrs, self._attrsNS, self)
Fred Drake55c38192000-06-29 19:39:57 +0000818
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000819 def hasAttributes(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000820 if self._attrs:
821 return True
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000822 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000823 return False
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000824
Martin v. Löwis787354c2003-01-25 15:28:29 +0000825 # DOM Level 3 attributes, based on the 22 Oct 2002 draft
826
827 def setIdAttribute(self, name):
828 idAttr = self.getAttributeNode(name)
829 self.setIdAttributeNode(idAttr)
830
831 def setIdAttributeNS(self, namespaceURI, localName):
832 idAttr = self.getAttributeNodeNS(namespaceURI, localName)
833 self.setIdAttributeNode(idAttr)
834
835 def setIdAttributeNode(self, idAttr):
836 if idAttr is None or not self.isSameNode(idAttr.ownerElement):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000837 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000838 if _get_containing_entref(self) is not None:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000839 raise xml.dom.NoModificationAllowedErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000840 if not idAttr._is_id:
841 idAttr.__dict__['_is_id'] = True
842 self._magic_id_nodes += 1
843 self.ownerDocument._magic_id_count += 1
844 _clear_id_cache(self)
845
846defproperty(Element, "attributes",
847 doc="NamedNodeMap of attributes on the element.")
848defproperty(Element, "localName",
849 doc="Namespace-local name of this element.")
850
851
852def _set_attribute_node(element, attr):
853 _clear_id_cache(element)
854 element._attrs[attr.name] = attr
855 element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
856
857 # This creates a circular reference, but Element.unlink()
858 # breaks the cycle since the references to the attribute
859 # dictionaries are tossed.
860 attr.__dict__['ownerElement'] = element
861
862
863class Childless:
864 """Mixin that makes childless-ness easy to implement and avoids
865 the complexity of the Node methods that deal with children.
866 """
867
Fred Drake4ccf4a12000-11-21 22:02:22 +0000868 attributes = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000869 childNodes = EmptyNodeList()
870 firstChild = None
871 lastChild = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000872
Martin v. Löwis787354c2003-01-25 15:28:29 +0000873 def _get_firstChild(self):
874 return None
Fred Drake55c38192000-06-29 19:39:57 +0000875
Martin v. Löwis787354c2003-01-25 15:28:29 +0000876 def _get_lastChild(self):
877 return None
Fred Drake1f549022000-09-24 05:21:58 +0000878
Martin v. Löwis787354c2003-01-25 15:28:29 +0000879 def appendChild(self, node):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000880 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000881 self.nodeName + " nodes cannot have children")
882
883 def hasChildNodes(self):
884 return False
885
886 def insertBefore(self, newChild, refChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000887 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000888 self.nodeName + " nodes do not have children")
889
890 def removeChild(self, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000891 raise xml.dom.NotFoundErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000892 self.nodeName + " nodes do not have children")
893
Andrew M. Kuchling53f94d02010-07-25 23:49:57 +0000894 def normalize(self):
895 # For childless nodes, normalize() has nothing to do.
896 pass
897
Martin v. Löwis787354c2003-01-25 15:28:29 +0000898 def replaceChild(self, newChild, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000899 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000900 self.nodeName + " nodes do not have children")
901
902
903class ProcessingInstruction(Childless, Node):
Fred Drake1f549022000-09-24 05:21:58 +0000904 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000905
Fred Drake1f549022000-09-24 05:21:58 +0000906 def __init__(self, target, data):
Fred Drake55c38192000-06-29 19:39:57 +0000907 self.target = self.nodeName = target
908 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000909
Martin v. Löwis787354c2003-01-25 15:28:29 +0000910 def _get_data(self):
911 return self.data
912 def _set_data(self, value):
913 d = self.__dict__
914 d['data'] = d['nodeValue'] = value
915
916 def _get_target(self):
917 return self.target
918 def _set_target(self, value):
919 d = self.__dict__
920 d['target'] = d['nodeName'] = value
921
922 def __setattr__(self, name, value):
923 if name == "data" or name == "nodeValue":
924 self.__dict__['data'] = self.__dict__['nodeValue'] = value
925 elif name == "target" or name == "nodeName":
926 self.__dict__['target'] = self.__dict__['nodeName'] = value
927 else:
928 self.__dict__[name] = value
929
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000930 def writexml(self, writer, indent="", addindent="", newl=""):
931 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000932
Martin v. Löwis787354c2003-01-25 15:28:29 +0000933
934class CharacterData(Childless, Node):
935 def _get_length(self):
936 return len(self.data)
937 __len__ = _get_length
938
939 def _get_data(self):
940 return self.__dict__['data']
941 def _set_data(self, data):
942 d = self.__dict__
943 d['data'] = d['nodeValue'] = data
944
945 _get_nodeValue = _get_data
946 _set_nodeValue = _set_data
947
948 def __setattr__(self, name, value):
949 if name == "data" or name == "nodeValue":
950 self.__dict__['data'] = self.__dict__['nodeValue'] = value
951 else:
952 self.__dict__[name] = value
Fred Drake87432f42001-04-04 14:09:46 +0000953
Fred Drake55c38192000-06-29 19:39:57 +0000954 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000955 data = self.data
956 if len(data) > 10:
Fred Drake1f549022000-09-24 05:21:58 +0000957 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000958 else:
Fred Drake1f549022000-09-24 05:21:58 +0000959 dotdotdot = ""
Facundo Batistaf5ade632007-10-24 19:11:08 +0000960 return '<DOM %s node "%r%s">' % (
Martin v. Löwis787354c2003-01-25 15:28:29 +0000961 self.__class__.__name__, data[0:10], dotdotdot)
Fred Drake87432f42001-04-04 14:09:46 +0000962
963 def substringData(self, offset, count):
964 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000965 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000966 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000967 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000968 if count < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000969 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000970 return self.data[offset:offset+count]
971
972 def appendData(self, arg):
973 self.data = self.data + arg
Fred Drake87432f42001-04-04 14:09:46 +0000974
975 def insertData(self, offset, arg):
976 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000977 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000978 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000979 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000980 if arg:
981 self.data = "%s%s%s" % (
982 self.data[:offset], arg, self.data[offset:])
Fred Drake87432f42001-04-04 14:09:46 +0000983
984 def deleteData(self, offset, count):
985 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000986 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000987 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000988 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000989 if count < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000990 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000991 if count:
992 self.data = self.data[:offset] + self.data[offset+count:]
Fred Drake87432f42001-04-04 14:09:46 +0000993
994 def replaceData(self, offset, count, arg):
995 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000996 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000997 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000998 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000999 if count < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001000 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001001 if count:
1002 self.data = "%s%s%s" % (
1003 self.data[:offset], arg, self.data[offset+count:])
Martin v. Löwis787354c2003-01-25 15:28:29 +00001004
1005defproperty(CharacterData, "length", doc="Length of the string data.")
1006
Fred Drake87432f42001-04-04 14:09:46 +00001007
1008class Text(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001009 # Make sure we don't add an instance __dict__ if we don't already
1010 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001011 # XXX this does not work, CharacterData is an old-style class
1012 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001013
Fred Drake87432f42001-04-04 14:09:46 +00001014 nodeType = Node.TEXT_NODE
1015 nodeName = "#text"
1016 attributes = None
Fred Drake55c38192000-06-29 19:39:57 +00001017
Fred Drakef7cf40d2000-12-14 18:16:11 +00001018 def splitText(self, offset):
1019 if offset < 0 or offset > len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001020 raise xml.dom.IndexSizeErr("illegal offset value")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001021 newText = self.__class__()
1022 newText.data = self.data[offset:]
1023 newText.ownerDocument = self.ownerDocument
Fred Drakef7cf40d2000-12-14 18:16:11 +00001024 next = self.nextSibling
1025 if self.parentNode and self in self.parentNode.childNodes:
1026 if next is None:
1027 self.parentNode.appendChild(newText)
1028 else:
1029 self.parentNode.insertBefore(newText, next)
1030 self.data = self.data[:offset]
1031 return newText
1032
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001033 def writexml(self, writer, indent="", addindent="", newl=""):
1034 _write_data(writer, "%s%s%s"%(indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001035
Martin v. Löwis787354c2003-01-25 15:28:29 +00001036 # DOM Level 3 (WD 9 April 2002)
1037
1038 def _get_wholeText(self):
1039 L = [self.data]
1040 n = self.previousSibling
1041 while n is not None:
1042 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1043 L.insert(0, n.data)
1044 n = n.previousSibling
1045 else:
1046 break
1047 n = self.nextSibling
1048 while n is not None:
1049 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1050 L.append(n.data)
1051 n = n.nextSibling
1052 else:
1053 break
1054 return ''.join(L)
1055
1056 def replaceWholeText(self, content):
1057 # XXX This needs to be seriously changed if minidom ever
1058 # supports EntityReference nodes.
1059 parent = self.parentNode
1060 n = self.previousSibling
1061 while n is not None:
1062 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1063 next = n.previousSibling
1064 parent.removeChild(n)
1065 n = next
1066 else:
1067 break
1068 n = self.nextSibling
1069 if not content:
1070 parent.removeChild(self)
1071 while n is not None:
1072 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1073 next = n.nextSibling
1074 parent.removeChild(n)
1075 n = next
1076 else:
1077 break
1078 if content:
1079 d = self.__dict__
1080 d['data'] = content
1081 d['nodeValue'] = content
1082 return self
1083 else:
1084 return None
1085
1086 def _get_isWhitespaceInElementContent(self):
1087 if self.data.strip():
1088 return False
1089 elem = _get_containing_element(self)
1090 if elem is None:
1091 return False
1092 info = self.ownerDocument._get_elem_info(elem)
1093 if info is None:
1094 return False
1095 else:
1096 return info.isElementContent()
1097
1098defproperty(Text, "isWhitespaceInElementContent",
1099 doc="True iff this text node contains only whitespace"
1100 " and is in element content.")
1101defproperty(Text, "wholeText",
1102 doc="The text of all logically-adjacent text nodes.")
1103
1104
1105def _get_containing_element(node):
1106 c = node.parentNode
1107 while c is not None:
1108 if c.nodeType == Node.ELEMENT_NODE:
1109 return c
1110 c = c.parentNode
1111 return None
1112
1113def _get_containing_entref(node):
1114 c = node.parentNode
1115 while c is not None:
1116 if c.nodeType == Node.ENTITY_REFERENCE_NODE:
1117 return c
1118 c = c.parentNode
1119 return None
1120
1121
1122class Comment(Childless, CharacterData):
1123 nodeType = Node.COMMENT_NODE
1124 nodeName = "#comment"
1125
1126 def __init__(self, data):
1127 self.data = self.nodeValue = data
1128
1129 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis27e4a172008-05-23 15:18:28 +00001130 if "--" in self.data:
1131 raise ValueError("'--' is not allowed in a comment node")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001132 writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
1133
Fred Drake87432f42001-04-04 14:09:46 +00001134
1135class CDATASection(Text):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001136 # Make sure we don't add an instance __dict__ if we don't already
1137 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001138 # XXX this does not work, Text is an old-style class
1139 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001140
Fred Drake87432f42001-04-04 14:09:46 +00001141 nodeType = Node.CDATA_SECTION_NODE
1142 nodeName = "#cdata-section"
1143
1144 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001145 if self.data.find("]]>") >= 0:
1146 raise ValueError("']]>' not allowed in a CDATA section")
Guido van Rossum5b5e0b92001-09-19 13:28:25 +00001147 writer.write("<![CDATA[%s]]>" % self.data)
Fred Drake87432f42001-04-04 14:09:46 +00001148
1149
Fred Drake9ea179f2006-04-06 01:29:04 +00001150class ReadOnlySequentialNamedNodeMap(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001151 __slots__ = '_seq',
1152
1153 def __init__(self, seq=()):
1154 # seq should be a list or tuple
1155 self._seq = seq
1156
1157 def __len__(self):
1158 return len(self._seq)
1159
1160 def _get_length(self):
1161 return len(self._seq)
1162
1163 def getNamedItem(self, name):
1164 for n in self._seq:
1165 if n.nodeName == name:
1166 return n
1167
1168 def getNamedItemNS(self, namespaceURI, localName):
1169 for n in self._seq:
1170 if n.namespaceURI == namespaceURI and n.localName == localName:
1171 return n
1172
1173 def __getitem__(self, name_or_tuple):
Fred Drake70d044b2006-04-06 01:32:26 +00001174 if isinstance(name_or_tuple, tuple):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001175 node = self.getNamedItemNS(*name_or_tuple)
1176 else:
1177 node = self.getNamedItem(name_or_tuple)
1178 if node is None:
1179 raise KeyError, name_or_tuple
1180 return node
1181
1182 def item(self, index):
1183 if index < 0:
1184 return None
1185 try:
1186 return self._seq[index]
1187 except IndexError:
1188 return None
1189
1190 def removeNamedItem(self, name):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001191 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001192 "NamedNodeMap instance is read-only")
1193
1194 def removeNamedItemNS(self, namespaceURI, localName):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001195 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001196 "NamedNodeMap instance is read-only")
1197
1198 def setNamedItem(self, node):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001199 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001200 "NamedNodeMap instance is read-only")
1201
1202 def setNamedItemNS(self, node):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001203 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001204 "NamedNodeMap instance is read-only")
1205
1206 def __getstate__(self):
1207 return [self._seq]
1208
1209 def __setstate__(self, state):
1210 self._seq = state[0]
1211
1212defproperty(ReadOnlySequentialNamedNodeMap, "length",
1213 doc="Number of entries in the NamedNodeMap.")
Paul Prescod73678da2000-07-01 04:58:47 +00001214
Fred Drakef7cf40d2000-12-14 18:16:11 +00001215
Martin v. Löwis787354c2003-01-25 15:28:29 +00001216class Identified:
1217 """Mix-in class that supports the publicId and systemId attributes."""
1218
Martin v. Löwis995359c2003-01-26 08:59:32 +00001219 # XXX this does not work, this is an old-style class
1220 # __slots__ = 'publicId', 'systemId'
Martin v. Löwis787354c2003-01-25 15:28:29 +00001221
1222 def _identified_mixin_init(self, publicId, systemId):
1223 self.publicId = publicId
1224 self.systemId = systemId
1225
1226 def _get_publicId(self):
1227 return self.publicId
1228
1229 def _get_systemId(self):
1230 return self.systemId
1231
1232class DocumentType(Identified, Childless, Node):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001233 nodeType = Node.DOCUMENT_TYPE_NODE
1234 nodeValue = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001235 name = None
1236 publicId = None
1237 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +00001238 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001239
1240 def __init__(self, qualifiedName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001241 self.entities = ReadOnlySequentialNamedNodeMap()
1242 self.notations = ReadOnlySequentialNamedNodeMap()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001243 if qualifiedName:
1244 prefix, localname = _nssplit(qualifiedName)
1245 self.name = localname
Martin v. Löwis787354c2003-01-25 15:28:29 +00001246 self.nodeName = self.name
1247
1248 def _get_internalSubset(self):
1249 return self.internalSubset
1250
1251 def cloneNode(self, deep):
1252 if self.ownerDocument is None:
1253 # it's ok
1254 clone = DocumentType(None)
1255 clone.name = self.name
1256 clone.nodeName = self.name
Fred Drakefbdeaad2006-07-29 16:56:15 +00001257 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001258 if deep:
1259 clone.entities._seq = []
1260 clone.notations._seq = []
1261 for n in self.notations._seq:
1262 notation = Notation(n.nodeName, n.publicId, n.systemId)
1263 clone.notations._seq.append(notation)
1264 n._call_user_data_handler(operation, n, notation)
1265 for e in self.entities._seq:
1266 entity = Entity(e.nodeName, e.publicId, e.systemId,
1267 e.notationName)
1268 entity.actualEncoding = e.actualEncoding
1269 entity.encoding = e.encoding
1270 entity.version = e.version
1271 clone.entities._seq.append(entity)
1272 e._call_user_data_handler(operation, n, entity)
1273 self._call_user_data_handler(operation, self, clone)
1274 return clone
1275 else:
1276 return None
1277
1278 def writexml(self, writer, indent="", addindent="", newl=""):
1279 writer.write("<!DOCTYPE ")
1280 writer.write(self.name)
1281 if self.publicId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001282 writer.write("%s PUBLIC '%s'%s '%s'"
1283 % (newl, self.publicId, newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001284 elif self.systemId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001285 writer.write("%s SYSTEM '%s'" % (newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001286 if self.internalSubset is not None:
1287 writer.write(" [")
1288 writer.write(self.internalSubset)
1289 writer.write("]")
Georg Brandl175a7dc2005-08-25 22:02:43 +00001290 writer.write(">"+newl)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001291
1292class Entity(Identified, Node):
1293 attributes = None
1294 nodeType = Node.ENTITY_NODE
1295 nodeValue = None
1296
1297 actualEncoding = None
1298 encoding = None
1299 version = None
1300
1301 def __init__(self, name, publicId, systemId, notation):
1302 self.nodeName = name
1303 self.notationName = notation
1304 self.childNodes = NodeList()
1305 self._identified_mixin_init(publicId, systemId)
1306
1307 def _get_actualEncoding(self):
1308 return self.actualEncoding
1309
1310 def _get_encoding(self):
1311 return self.encoding
1312
1313 def _get_version(self):
1314 return self.version
1315
1316 def appendChild(self, newChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001317 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001318 "cannot append children to an entity node")
1319
1320 def insertBefore(self, newChild, refChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001321 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001322 "cannot insert children below an entity node")
1323
1324 def removeChild(self, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001325 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001326 "cannot remove children from an entity node")
1327
1328 def replaceChild(self, newChild, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001329 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001330 "cannot replace children of an entity node")
1331
1332class Notation(Identified, Childless, Node):
1333 nodeType = Node.NOTATION_NODE
1334 nodeValue = None
1335
1336 def __init__(self, name, publicId, systemId):
1337 self.nodeName = name
1338 self._identified_mixin_init(publicId, systemId)
Fred Drakef7cf40d2000-12-14 18:16:11 +00001339
1340
Martin v. Löwis787354c2003-01-25 15:28:29 +00001341class DOMImplementation(DOMImplementationLS):
1342 _features = [("core", "1.0"),
1343 ("core", "2.0"),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001344 ("core", None),
1345 ("xml", "1.0"),
1346 ("xml", "2.0"),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001347 ("xml", None),
1348 ("ls-load", "3.0"),
1349 ("ls-load", None),
1350 ]
1351
Fred Drakef7cf40d2000-12-14 18:16:11 +00001352 def hasFeature(self, feature, version):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001353 if version == "":
1354 version = None
1355 return (feature.lower(), version) in self._features
Fred Drakef7cf40d2000-12-14 18:16:11 +00001356
1357 def createDocument(self, namespaceURI, qualifiedName, doctype):
1358 if doctype and doctype.parentNode is not None:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001359 raise xml.dom.WrongDocumentErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001360 "doctype object owned by another DOM tree")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001361 doc = self._create_document()
1362
1363 add_root_element = not (namespaceURI is None
1364 and qualifiedName is None
1365 and doctype is None)
1366
1367 if not qualifiedName and add_root_element:
Martin v. Löwisb417be22001-02-06 01:16:06 +00001368 # The spec is unclear what to raise here; SyntaxErr
1369 # would be the other obvious candidate. Since Xerces raises
1370 # InvalidCharacterErr, and since SyntaxErr is not listed
1371 # for createDocument, that seems to be the better choice.
1372 # XXX: need to check for illegal characters here and in
1373 # createElement.
Martin v. Löwis787354c2003-01-25 15:28:29 +00001374
1375 # DOM Level III clears this up when talking about the return value
1376 # of this function. If namespaceURI, qName and DocType are
1377 # Null the document is returned without a document element
1378 # Otherwise if doctype or namespaceURI are not None
1379 # Then we go back to the above problem
Fred Drakefbdeaad2006-07-29 16:56:15 +00001380 raise xml.dom.InvalidCharacterErr("Element with no name")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001381
1382 if add_root_element:
1383 prefix, localname = _nssplit(qualifiedName)
1384 if prefix == "xml" \
1385 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
Fred Drakefbdeaad2006-07-29 16:56:15 +00001386 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001387 if prefix and not namespaceURI:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001388 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001389 "illegal use of prefix without namespaces")
1390 element = doc.createElementNS(namespaceURI, qualifiedName)
1391 if doctype:
1392 doc.appendChild(doctype)
1393 doc.appendChild(element)
1394
1395 if doctype:
1396 doctype.parentNode = doctype.ownerDocument = doc
1397
Fred Drakef7cf40d2000-12-14 18:16:11 +00001398 doc.doctype = doctype
1399 doc.implementation = self
1400 return doc
1401
1402 def createDocumentType(self, qualifiedName, publicId, systemId):
1403 doctype = DocumentType(qualifiedName)
1404 doctype.publicId = publicId
1405 doctype.systemId = systemId
1406 return doctype
1407
Martin v. Löwis787354c2003-01-25 15:28:29 +00001408 # DOM Level 3 (WD 9 April 2002)
1409
1410 def getInterface(self, feature):
1411 if self.hasFeature(feature, None):
1412 return self
1413 else:
1414 return None
1415
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001416 # internal
Martin v. Löwis787354c2003-01-25 15:28:29 +00001417 def _create_document(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001418 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001419
Fred Drake9ea179f2006-04-06 01:29:04 +00001420class ElementInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001421 """Object that represents content-model information for an element.
1422
1423 This implementation is not expected to be used in practice; DOM
1424 builders should provide implementations which do the right thing
1425 using information available to it.
1426
1427 """
1428
1429 __slots__ = 'tagName',
1430
1431 def __init__(self, name):
1432 self.tagName = name
1433
1434 def getAttributeType(self, aname):
1435 return _no_type
1436
1437 def getAttributeTypeNS(self, namespaceURI, localName):
1438 return _no_type
1439
1440 def isElementContent(self):
1441 return False
1442
1443 def isEmpty(self):
1444 """Returns true iff this element is declared to have an EMPTY
1445 content model."""
1446 return False
1447
1448 def isId(self, aname):
Ezio Melotti24b07bc2011-03-15 18:55:01 +02001449 """Returns true iff the named attribute is a DTD-style ID."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001450 return False
1451
1452 def isIdNS(self, namespaceURI, localName):
1453 """Returns true iff the identified attribute is a DTD-style ID."""
1454 return False
1455
1456 def __getstate__(self):
1457 return self.tagName
1458
1459 def __setstate__(self, state):
1460 self.tagName = state
1461
1462def _clear_id_cache(node):
1463 if node.nodeType == Node.DOCUMENT_NODE:
1464 node._id_cache.clear()
1465 node._id_search_stack = None
1466 elif _in_document(node):
1467 node.ownerDocument._id_cache.clear()
1468 node.ownerDocument._id_search_stack= None
1469
1470class Document(Node, DocumentLS):
1471 _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
1472 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
1473
Fred Drake1f549022000-09-24 05:21:58 +00001474 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +00001475 nodeName = "#document"
1476 nodeValue = None
1477 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001478 doctype = None
1479 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001480 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001481
1482 implementation = DOMImplementation()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001483
1484 # Document attributes from Level 3 (WD 9 April 2002)
1485
1486 actualEncoding = None
1487 encoding = None
1488 standalone = None
1489 version = None
1490 strictErrorChecking = False
1491 errorHandler = None
1492 documentURI = None
1493
1494 _magic_id_count = 0
1495
1496 def __init__(self):
1497 self.childNodes = NodeList()
1498 # mapping of (namespaceURI, localName) -> ElementInfo
1499 # and tagName -> ElementInfo
1500 self._elem_info = {}
1501 self._id_cache = {}
1502 self._id_search_stack = None
1503
1504 def _get_elem_info(self, element):
1505 if element.namespaceURI:
1506 key = element.namespaceURI, element.localName
1507 else:
1508 key = element.tagName
1509 return self._elem_info.get(key)
1510
1511 def _get_actualEncoding(self):
1512 return self.actualEncoding
1513
1514 def _get_doctype(self):
1515 return self.doctype
1516
1517 def _get_documentURI(self):
1518 return self.documentURI
1519
1520 def _get_encoding(self):
1521 return self.encoding
1522
1523 def _get_errorHandler(self):
1524 return self.errorHandler
1525
1526 def _get_standalone(self):
1527 return self.standalone
1528
1529 def _get_strictErrorChecking(self):
1530 return self.strictErrorChecking
1531
1532 def _get_version(self):
1533 return self.version
Fred Drake55c38192000-06-29 19:39:57 +00001534
Fred Drake1f549022000-09-24 05:21:58 +00001535 def appendChild(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001536 if node.nodeType not in self._child_node_types:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001537 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001538 "%s cannot be child of %s" % (repr(node), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001539 if node.parentNode is not None:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001540 # This needs to be done before the next test since this
1541 # may *be* the document element, in which case it should
1542 # end up re-ordered to the end.
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001543 node.parentNode.removeChild(node)
1544
Fred Drakef7cf40d2000-12-14 18:16:11 +00001545 if node.nodeType == Node.ELEMENT_NODE \
1546 and self._get_documentElement():
Fred Drakefbdeaad2006-07-29 16:56:15 +00001547 raise xml.dom.HierarchyRequestErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001548 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +00001549 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +00001550
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001551 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001552 try:
1553 self.childNodes.remove(oldChild)
1554 except ValueError:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001555 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001556 oldChild.nextSibling = oldChild.previousSibling = None
1557 oldChild.parentNode = None
1558 if self.documentElement is oldChild:
1559 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +00001560
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001561 return oldChild
1562
Fred Drakef7cf40d2000-12-14 18:16:11 +00001563 def _get_documentElement(self):
1564 for node in self.childNodes:
1565 if node.nodeType == Node.ELEMENT_NODE:
1566 return node
1567
1568 def unlink(self):
1569 if self.doctype is not None:
1570 self.doctype.unlink()
1571 self.doctype = None
1572 Node.unlink(self)
1573
Martin v. Löwis787354c2003-01-25 15:28:29 +00001574 def cloneNode(self, deep):
1575 if not deep:
1576 return None
1577 clone = self.implementation.createDocument(None, None, None)
1578 clone.encoding = self.encoding
1579 clone.standalone = self.standalone
1580 clone.version = self.version
1581 for n in self.childNodes:
1582 childclone = _clone_node(n, deep, clone)
1583 assert childclone.ownerDocument.isSameNode(clone)
1584 clone.childNodes.append(childclone)
1585 if childclone.nodeType == Node.DOCUMENT_NODE:
1586 assert clone.documentElement is None
1587 elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
1588 assert clone.doctype is None
1589 clone.doctype = childclone
1590 childclone.parentNode = clone
Fred Drakefbdeaad2006-07-29 16:56:15 +00001591 self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
Martin v. Löwis787354c2003-01-25 15:28:29 +00001592 self, clone)
1593 return clone
1594
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001595 def createDocumentFragment(self):
1596 d = DocumentFragment()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001597 d.ownerDocument = self
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001598 return d
Fred Drake55c38192000-06-29 19:39:57 +00001599
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001600 def createElement(self, tagName):
1601 e = Element(tagName)
1602 e.ownerDocument = self
1603 return e
Fred Drake55c38192000-06-29 19:39:57 +00001604
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001605 def createTextNode(self, data):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001606 if not isinstance(data, StringTypes):
1607 raise TypeError, "node contents must be a string"
1608 t = Text()
1609 t.data = data
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001610 t.ownerDocument = self
1611 return t
Fred Drake55c38192000-06-29 19:39:57 +00001612
Fred Drake87432f42001-04-04 14:09:46 +00001613 def createCDATASection(self, data):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001614 if not isinstance(data, StringTypes):
1615 raise TypeError, "node contents must be a string"
1616 c = CDATASection()
1617 c.data = data
Fred Drake87432f42001-04-04 14:09:46 +00001618 c.ownerDocument = self
1619 return c
1620
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001621 def createComment(self, data):
1622 c = Comment(data)
1623 c.ownerDocument = self
1624 return c
Fred Drake55c38192000-06-29 19:39:57 +00001625
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001626 def createProcessingInstruction(self, target, data):
1627 p = ProcessingInstruction(target, data)
1628 p.ownerDocument = self
1629 return p
1630
1631 def createAttribute(self, qName):
1632 a = Attr(qName)
1633 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001634 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001635 return a
Fred Drake55c38192000-06-29 19:39:57 +00001636
1637 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001638 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001639 e = Element(qualifiedName, namespaceURI, prefix)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001640 e.ownerDocument = self
1641 return e
Fred Drake55c38192000-06-29 19:39:57 +00001642
1643 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001644 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001645 a = Attr(qualifiedName, namespaceURI, localName, prefix)
1646 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001647 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001648 return a
Fred Drake55c38192000-06-29 19:39:57 +00001649
Martin v. Löwis787354c2003-01-25 15:28:29 +00001650 # A couple of implementation-specific helpers to create node types
1651 # not supported by the W3C DOM specs:
1652
1653 def _create_entity(self, name, publicId, systemId, notationName):
1654 e = Entity(name, publicId, systemId, notationName)
1655 e.ownerDocument = self
1656 return e
1657
1658 def _create_notation(self, name, publicId, systemId):
1659 n = Notation(name, publicId, systemId)
1660 n.ownerDocument = self
1661 return n
1662
1663 def getElementById(self, id):
Brett Cannon5dd504d2008-08-04 00:23:58 +00001664 if id in self._id_cache:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001665 return self._id_cache[id]
1666 if not (self._elem_info or self._magic_id_count):
1667 return None
1668
1669 stack = self._id_search_stack
1670 if stack is None:
1671 # we never searched before, or the cache has been cleared
1672 stack = [self.documentElement]
1673 self._id_search_stack = stack
1674 elif not stack:
1675 # Previous search was completed and cache is still valid;
1676 # no matching node.
1677 return None
1678
1679 result = None
1680 while stack:
1681 node = stack.pop()
1682 # add child elements to stack for continued searching
1683 stack.extend([child for child in node.childNodes
1684 if child.nodeType in _nodeTypes_with_children])
1685 # check this node
1686 info = self._get_elem_info(node)
1687 if info:
1688 # We have to process all ID attributes before
1689 # returning in order to get all the attributes set to
1690 # be IDs using Element.setIdAttribute*().
1691 for attr in node.attributes.values():
1692 if attr.namespaceURI:
1693 if info.isIdNS(attr.namespaceURI, attr.localName):
1694 self._id_cache[attr.value] = node
1695 if attr.value == id:
1696 result = node
1697 elif not node._magic_id_nodes:
1698 break
1699 elif info.isId(attr.name):
1700 self._id_cache[attr.value] = node
1701 if attr.value == id:
1702 result = node
1703 elif not node._magic_id_nodes:
1704 break
1705 elif attr._is_id:
1706 self._id_cache[attr.value] = node
1707 if attr.value == id:
1708 result = node
1709 elif node._magic_id_nodes == 1:
1710 break
1711 elif node._magic_id_nodes:
1712 for attr in node.attributes.values():
1713 if attr._is_id:
1714 self._id_cache[attr.value] = node
1715 if attr.value == id:
1716 result = node
1717 if result is not None:
1718 break
1719 return result
1720
Fred Drake1f549022000-09-24 05:21:58 +00001721 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001722 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drakefbe7b4f2001-07-04 06:25:53 +00001723
1724 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001725 return _get_elements_by_tagName_ns_helper(
1726 self, namespaceURI, localName, NodeList())
1727
1728 def isSupported(self, feature, version):
1729 return self.implementation.hasFeature(feature, version)
1730
1731 def importNode(self, node, deep):
1732 if node.nodeType == Node.DOCUMENT_NODE:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001733 raise xml.dom.NotSupportedErr("cannot import document nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001734 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001735 raise xml.dom.NotSupportedErr("cannot import document type nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001736 return _clone_node(node, deep, self)
Fred Drake55c38192000-06-29 19:39:57 +00001737
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001738 def writexml(self, writer, indent="", addindent="", newl="",
1739 encoding = None):
1740 if encoding is None:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001741 writer.write('<?xml version="1.0" ?>'+newl)
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001742 else:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001743 writer.write('<?xml version="1.0" encoding="%s"?>%s' % (encoding, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001744 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001745 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +00001746
Martin v. Löwis787354c2003-01-25 15:28:29 +00001747 # DOM Level 3 (WD 9 April 2002)
1748
1749 def renameNode(self, n, namespaceURI, name):
1750 if n.ownerDocument is not self:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001751 raise xml.dom.WrongDocumentErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001752 "cannot rename nodes from other documents;\n"
1753 "expected %s,\nfound %s" % (self, n.ownerDocument))
1754 if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001755 raise xml.dom.NotSupportedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001756 "renameNode() only applies to element and attribute nodes")
1757 if namespaceURI != EMPTY_NAMESPACE:
1758 if ':' in name:
1759 prefix, localName = name.split(':', 1)
1760 if ( prefix == "xmlns"
Fred Drakefbdeaad2006-07-29 16:56:15 +00001761 and namespaceURI != xml.dom.XMLNS_NAMESPACE):
1762 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001763 "illegal use of 'xmlns' prefix")
1764 else:
1765 if ( name == "xmlns"
Fred Drakefbdeaad2006-07-29 16:56:15 +00001766 and namespaceURI != xml.dom.XMLNS_NAMESPACE
Martin v. Löwis787354c2003-01-25 15:28:29 +00001767 and n.nodeType == Node.ATTRIBUTE_NODE):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001768 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001769 "illegal use of the 'xmlns' attribute")
1770 prefix = None
1771 localName = name
1772 else:
1773 prefix = None
1774 localName = None
1775 if n.nodeType == Node.ATTRIBUTE_NODE:
1776 element = n.ownerElement
1777 if element is not None:
1778 is_id = n._is_id
1779 element.removeAttributeNode(n)
1780 else:
1781 element = None
1782 # avoid __setattr__
1783 d = n.__dict__
1784 d['prefix'] = prefix
1785 d['localName'] = localName
1786 d['namespaceURI'] = namespaceURI
1787 d['nodeName'] = name
1788 if n.nodeType == Node.ELEMENT_NODE:
1789 d['tagName'] = name
1790 else:
1791 # attribute node
1792 d['name'] = name
1793 if element is not None:
1794 element.setAttributeNode(n)
1795 if is_id:
1796 element.setIdAttributeNode(n)
1797 # It's not clear from a semantic perspective whether we should
1798 # call the user data handlers for the NODE_RENAMED event since
1799 # we're re-using the existing node. The draft spec has been
1800 # interpreted as meaning "no, don't call the handler unless a
1801 # new node is created."
1802 return n
1803
1804defproperty(Document, "documentElement",
1805 doc="Top-level element of this document.")
1806
1807
1808def _clone_node(node, deep, newOwnerDocument):
1809 """
1810 Clone a node and give it the new owner document.
1811 Called by Node.cloneNode and Document.importNode
1812 """
1813 if node.ownerDocument.isSameNode(newOwnerDocument):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001814 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001815 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001816 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001817 if node.nodeType == Node.ELEMENT_NODE:
1818 clone = newOwnerDocument.createElementNS(node.namespaceURI,
1819 node.nodeName)
1820 for attr in node.attributes.values():
1821 clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
1822 a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
1823 a.specified = attr.specified
1824
1825 if deep:
1826 for child in node.childNodes:
1827 c = _clone_node(child, deep, newOwnerDocument)
1828 clone.appendChild(c)
1829
1830 elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
1831 clone = newOwnerDocument.createDocumentFragment()
1832 if deep:
1833 for child in node.childNodes:
1834 c = _clone_node(child, deep, newOwnerDocument)
1835 clone.appendChild(c)
1836
1837 elif node.nodeType == Node.TEXT_NODE:
1838 clone = newOwnerDocument.createTextNode(node.data)
1839 elif node.nodeType == Node.CDATA_SECTION_NODE:
1840 clone = newOwnerDocument.createCDATASection(node.data)
1841 elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
1842 clone = newOwnerDocument.createProcessingInstruction(node.target,
1843 node.data)
1844 elif node.nodeType == Node.COMMENT_NODE:
1845 clone = newOwnerDocument.createComment(node.data)
1846 elif node.nodeType == Node.ATTRIBUTE_NODE:
1847 clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
1848 node.nodeName)
1849 clone.specified = True
1850 clone.value = node.value
1851 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
1852 assert node.ownerDocument is not newOwnerDocument
Fred Drakefbdeaad2006-07-29 16:56:15 +00001853 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001854 clone = newOwnerDocument.implementation.createDocumentType(
1855 node.name, node.publicId, node.systemId)
1856 clone.ownerDocument = newOwnerDocument
1857 if deep:
1858 clone.entities._seq = []
1859 clone.notations._seq = []
1860 for n in node.notations._seq:
1861 notation = Notation(n.nodeName, n.publicId, n.systemId)
1862 notation.ownerDocument = newOwnerDocument
1863 clone.notations._seq.append(notation)
1864 if hasattr(n, '_call_user_data_handler'):
1865 n._call_user_data_handler(operation, n, notation)
1866 for e in node.entities._seq:
1867 entity = Entity(e.nodeName, e.publicId, e.systemId,
1868 e.notationName)
1869 entity.actualEncoding = e.actualEncoding
1870 entity.encoding = e.encoding
1871 entity.version = e.version
1872 entity.ownerDocument = newOwnerDocument
1873 clone.entities._seq.append(entity)
1874 if hasattr(e, '_call_user_data_handler'):
1875 e._call_user_data_handler(operation, n, entity)
1876 else:
1877 # Note the cloning of Document and DocumentType nodes is
Ezio Melottic2077b02011-03-16 12:34:31 +02001878 # implementation specific. minidom handles those cases
Martin v. Löwis787354c2003-01-25 15:28:29 +00001879 # directly in the cloneNode() methods.
Fred Drakefbdeaad2006-07-29 16:56:15 +00001880 raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001881
1882 # Check for _call_user_data_handler() since this could conceivably
1883 # used with other DOM implementations (one of the FourThought
1884 # DOMs, perhaps?).
1885 if hasattr(node, '_call_user_data_handler'):
1886 node._call_user_data_handler(operation, node, clone)
1887 return clone
1888
1889
1890def _nssplit(qualifiedName):
1891 fields = qualifiedName.split(':', 1)
1892 if len(fields) == 2:
1893 return fields
1894 else:
1895 return (None, fields[0])
1896
1897
Fred Drake4ccf4a12000-11-21 22:02:22 +00001898def _get_StringIO():
Fred Drakef7cf40d2000-12-14 18:16:11 +00001899 # we can't use cStringIO since it doesn't support Unicode strings
1900 from StringIO import StringIO
Fred Drake4ccf4a12000-11-21 22:02:22 +00001901 return StringIO()
1902
Martin v. Löwis787354c2003-01-25 15:28:29 +00001903def _do_pulldom_parse(func, args, kwargs):
Raymond Hettingerff41c482003-04-06 09:01:11 +00001904 events = func(*args, **kwargs)
Fred Drake1f549022000-09-24 05:21:58 +00001905 toktype, rootNode = events.getEvent()
1906 events.expandNode(rootNode)
Martin v. Löwisb417be22001-02-06 01:16:06 +00001907 events.clear()
Fred Drake55c38192000-06-29 19:39:57 +00001908 return rootNode
1909
Martin v. Löwis787354c2003-01-25 15:28:29 +00001910def parse(file, parser=None, bufsize=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001911 """Parse a file into a DOM by filename or file object."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001912 if parser is None and not bufsize:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001913 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001914 return expatbuilder.parse(file)
1915 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001916 from xml.dom import pulldom
Raymond Hettingerff41c482003-04-06 09:01:11 +00001917 return _do_pulldom_parse(pulldom.parse, (file,),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001918 {'parser': parser, 'bufsize': bufsize})
Fred Drake55c38192000-06-29 19:39:57 +00001919
Martin v. Löwis787354c2003-01-25 15:28:29 +00001920def parseString(string, parser=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001921 """Parse a file into a DOM from a string."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001922 if parser is None:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001923 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001924 return expatbuilder.parseString(string)
1925 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001926 from xml.dom import pulldom
Martin v. Löwis787354c2003-01-25 15:28:29 +00001927 return _do_pulldom_parse(pulldom.parseString, (string,),
1928 {'parser': parser})
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001929
Martin v. Löwis787354c2003-01-25 15:28:29 +00001930def getDOMImplementation(features=None):
1931 if features:
1932 if isinstance(features, StringTypes):
1933 features = domreg._parse_feature_string(features)
1934 for f, v in features:
1935 if not Document.implementation.hasFeature(f, v):
1936 return None
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001937 return Document.implementation