blob: 489ae5225fd1a7340806bd6779639936cb324cd7 [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
Alexandre Vassalotti794652d2008-06-11 22:58:36 +000017import codecs
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000018import io
Thomas Wouters0e3f5912006-08-11 14:57:12 +000019import xml.dom
Fred Drake55c38192000-06-29 19:39:57 +000020
Thomas Wouters0e3f5912006-08-11 14:57:12 +000021from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
22from xml.dom.minicompat import *
23from xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS
Fred Drake3ac6a092001-09-28 04:33:06 +000024
Martin v. Löwis787354c2003-01-25 15:28:29 +000025# This is used by the ID-cache invalidation checks; the list isn't
26# actually complete, since the nodes being checked will never be the
27# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE. (The node being checked is
28# the node being added or removed, not the node being modified.)
29#
Thomas Wouters0e3f5912006-08-11 14:57:12 +000030_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE,
31 xml.dom.Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis95700f72002-03-15 13:51:59 +000032
Fred Drake3ac6a092001-09-28 04:33:06 +000033
Thomas Wouters0e3f5912006-08-11 14:57:12 +000034class Node(xml.dom.Node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000035 namespaceURI = None # this is non-null only for elements and attributes
Fred Drake575712e2001-09-28 20:25:45 +000036 parentNode = None
37 ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +000038 nextSibling = None
39 previousSibling = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +000040
Martin v. Löwis787354c2003-01-25 15:28:29 +000041 prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
Fred Drake55c38192000-06-29 19:39:57 +000042
Jack Diederich4dafcc42006-11-28 19:15:13 +000043 def __bool__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +000044 return True
Fred Drake55c38192000-06-29 19:39:57 +000045
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000046 def toxml(self, encoding = None):
47 return self.toprettyxml("", "", encoding)
Fred Drake55c38192000-06-29 19:39:57 +000048
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000049 def toprettyxml(self, indent="\t", newl="\n", encoding=None):
Martin v. Löwiscb67ea12001-03-31 16:30:40 +000050 # indent = the indentation string to prepend, per level
51 # newl = the newline string to append
Guido van Rossum55b15c92007-08-07 23:03:33 +000052 use_encoding = "utf-8" if encoding is None else encoding
Alexandre Vassalotti794652d2008-06-11 22:58:36 +000053 writer = codecs.getwriter(use_encoding)(io.BytesIO())
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000054 if self.nodeType == Node.DOCUMENT_NODE:
55 # Can pass encoding only to document, to put it into XML header
56 self.writexml(writer, "", indent, newl, encoding)
57 else:
58 self.writexml(writer, "", indent, newl)
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000059 if encoding is None:
Alexandre Vassalotti794652d2008-06-11 22:58:36 +000060 return writer.stream.getvalue().decode(use_encoding)
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000061 else:
Alexandre Vassalotti794652d2008-06-11 22:58:36 +000062 return writer.stream.getvalue()
Martin v. Löwis46fa39a2001-02-06 00:14:08 +000063
Fred Drake1f549022000-09-24 05:21:58 +000064 def hasChildNodes(self):
65 if self.childNodes:
Martin v. Löwis787354c2003-01-25 15:28:29 +000066 return True
Fred Drake1f549022000-09-24 05:21:58 +000067 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +000068 return False
69
70 def _get_childNodes(self):
71 return self.childNodes
Fred Drake55c38192000-06-29 19:39:57 +000072
Fred Drake1f549022000-09-24 05:21:58 +000073 def _get_firstChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000074 if self.childNodes:
75 return self.childNodes[0]
Paul Prescod73678da2000-07-01 04:58:47 +000076
Fred Drake1f549022000-09-24 05:21:58 +000077 def _get_lastChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000078 if self.childNodes:
79 return self.childNodes[-1]
Paul Prescod73678da2000-07-01 04:58:47 +000080
Fred Drake1f549022000-09-24 05:21:58 +000081 def insertBefore(self, newChild, refChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000082 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +000083 for c in tuple(newChild.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000084 self.insertBefore(c, refChild)
85 ### The DOM does not clearly specify what to return in this case
86 return newChild
Martin v. Löwis787354c2003-01-25 15:28:29 +000087 if newChild.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000088 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +000089 "%s cannot be child of %s" % (repr(newChild), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +000090 if newChild.parentNode is not None:
91 newChild.parentNode.removeChild(newChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +000092 if refChild is None:
93 self.appendChild(newChild)
94 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +000095 try:
96 index = self.childNodes.index(refChild)
97 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000098 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +000099 if newChild.nodeType in _nodeTypes_with_children:
100 _clear_id_cache(self)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000101 self.childNodes.insert(index, newChild)
102 newChild.nextSibling = refChild
103 refChild.previousSibling = newChild
104 if index:
105 node = self.childNodes[index-1]
106 node.nextSibling = newChild
107 newChild.previousSibling = node
108 else:
109 newChild.previousSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000110 newChild.parentNode = self
Fred Drake4ccf4a12000-11-21 22:02:22 +0000111 return newChild
Fred Drake55c38192000-06-29 19:39:57 +0000112
Fred Drake1f549022000-09-24 05:21:58 +0000113 def appendChild(self, node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000114 if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +0000115 for c in tuple(node.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000116 self.appendChild(c)
117 ### The DOM does not clearly specify what to return in this case
118 return node
Martin v. Löwis787354c2003-01-25 15:28:29 +0000119 if node.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000120 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000121 "%s cannot be child of %s" % (repr(node), repr(self)))
122 elif node.nodeType in _nodeTypes_with_children:
123 _clear_id_cache(self)
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000124 if node.parentNode is not None:
125 node.parentNode.removeChild(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000126 _append_child(self, node)
Fred Drake13a30692000-10-09 20:04:16 +0000127 node.nextSibling = None
Paul Prescod73678da2000-07-01 04:58:47 +0000128 return node
129
Fred Drake1f549022000-09-24 05:21:58 +0000130 def replaceChild(self, newChild, oldChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000131 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
132 refChild = oldChild.nextSibling
133 self.removeChild(oldChild)
134 return self.insertBefore(newChild, refChild)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000135 if newChild.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000136 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000137 "%s cannot be child of %s" % (repr(newChild), repr(self)))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000138 if newChild is oldChild:
139 return
Andrew M. Kuchling841d25e2005-11-22 19:03:16 +0000140 if newChild.parentNode is not None:
141 newChild.parentNode.removeChild(newChild)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000142 try:
143 index = self.childNodes.index(oldChild)
144 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000145 raise xml.dom.NotFoundErr()
Fred Drake4ccf4a12000-11-21 22:02:22 +0000146 self.childNodes[index] = newChild
Martin v. Löwis787354c2003-01-25 15:28:29 +0000147 newChild.parentNode = self
148 oldChild.parentNode = None
149 if (newChild.nodeType in _nodeTypes_with_children
150 or oldChild.nodeType in _nodeTypes_with_children):
151 _clear_id_cache(self)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000152 newChild.nextSibling = oldChild.nextSibling
153 newChild.previousSibling = oldChild.previousSibling
Martin v. Löwis156c3372000-12-28 18:40:56 +0000154 oldChild.nextSibling = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000155 oldChild.previousSibling = None
Martin v. Löwis156c3372000-12-28 18:40:56 +0000156 if newChild.previousSibling:
157 newChild.previousSibling.nextSibling = newChild
158 if newChild.nextSibling:
159 newChild.nextSibling.previousSibling = newChild
Fred Drake4ccf4a12000-11-21 22:02:22 +0000160 return oldChild
Paul Prescod73678da2000-07-01 04:58:47 +0000161
Fred Drake1f549022000-09-24 05:21:58 +0000162 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000163 try:
164 self.childNodes.remove(oldChild)
165 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000166 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000167 if oldChild.nextSibling is not None:
168 oldChild.nextSibling.previousSibling = oldChild.previousSibling
169 if oldChild.previousSibling is not None:
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000170 oldChild.previousSibling.nextSibling = oldChild.nextSibling
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000171 oldChild.nextSibling = oldChild.previousSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000172 if oldChild.nodeType in _nodeTypes_with_children:
173 _clear_id_cache(self)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000174
Martin v. Löwis787354c2003-01-25 15:28:29 +0000175 oldChild.parentNode = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000176 return oldChild
177
178 def normalize(self):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000179 L = []
180 for child in self.childNodes:
181 if child.nodeType == Node.TEXT_NODE:
182 data = child.data
183 if data and L and L[-1].nodeType == child.nodeType:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000184 # collapse text node
185 node = L[-1]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000186 node.data = node.data + child.data
Fred Drake4ccf4a12000-11-21 22:02:22 +0000187 node.nextSibling = child.nextSibling
188 child.unlink()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000189 elif data:
190 if L:
191 L[-1].nextSibling = child
192 child.previousSibling = L[-1]
193 else:
194 child.previousSibling = None
195 L.append(child)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000196 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000197 # empty text node; discard
198 child.unlink()
199 else:
200 if L:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000201 L[-1].nextSibling = child
202 child.previousSibling = L[-1]
Fred Drakef7cf40d2000-12-14 18:16:11 +0000203 else:
204 child.previousSibling = None
205 L.append(child)
206 if child.nodeType == Node.ELEMENT_NODE:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000207 child.normalize()
Christian Heimes05e8be12008-02-23 18:30:17 +0000208 if L:
209 L[-1].nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000210 self.childNodes[:] = L
Paul Prescod73678da2000-07-01 04:58:47 +0000211
Fred Drake1f549022000-09-24 05:21:58 +0000212 def cloneNode(self, deep):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000213 return _clone_node(self, deep, self.ownerDocument or self)
Fred Drake55c38192000-06-29 19:39:57 +0000214
Martin v. Löwis787354c2003-01-25 15:28:29 +0000215 def isSupported(self, feature, version):
216 return self.ownerDocument.implementation.hasFeature(feature, version)
217
218 def _get_localName(self):
219 # Overridden in Element and Attr where localName can be Non-Null
220 return None
221
222 # Node interfaces from Level 3 (WD 9 April 2002)
Fred Drake25239772001-02-02 19:40:19 +0000223
224 def isSameNode(self, other):
225 return self is other
226
Martin v. Löwis787354c2003-01-25 15:28:29 +0000227 def getInterface(self, feature):
228 if self.isSupported(feature, None):
229 return self
230 else:
231 return None
232
233 # The "user data" functions use a dictionary that is only present
234 # if some user data has been set, so be careful not to assume it
235 # exists.
236
237 def getUserData(self, key):
238 try:
239 return self._user_data[key][0]
240 except (AttributeError, KeyError):
241 return None
242
243 def setUserData(self, key, data, handler):
244 old = None
245 try:
246 d = self._user_data
247 except AttributeError:
248 d = {}
249 self._user_data = d
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000250 if key in d:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000251 old = d[key][0]
252 if data is None:
253 # ignore handlers passed for None
254 handler = None
255 if old is not None:
256 del d[key]
257 else:
258 d[key] = (data, handler)
259 return old
260
261 def _call_user_data_handler(self, operation, src, dst):
262 if hasattr(self, "_user_data"):
Brett Cannon861fd6f2007-02-21 22:05:37 +0000263 for key, (data, handler) in list(self._user_data.items()):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000264 if handler is not None:
265 handler.handle(operation, key, data, src, dst)
266
Fred Drake25239772001-02-02 19:40:19 +0000267 # minidom-specific API:
268
Fred Drake1f549022000-09-24 05:21:58 +0000269 def unlink(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000270 self.parentNode = self.ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000271 if self.childNodes:
272 for child in self.childNodes:
273 child.unlink()
274 self.childNodes = NodeList()
Paul Prescod4221ff02000-10-13 20:11:42 +0000275 self.previousSibling = None
276 self.nextSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000277
278defproperty(Node, "firstChild", doc="First child node, or None.")
279defproperty(Node, "lastChild", doc="Last child node, or None.")
280defproperty(Node, "localName", doc="Namespace-local name of this node.")
281
282
283def _append_child(self, node):
284 # fast path with less checks; usable by DOM builders if careful
285 childNodes = self.childNodes
286 if childNodes:
287 last = childNodes[-1]
288 node.__dict__["previousSibling"] = last
289 last.__dict__["nextSibling"] = node
290 childNodes.append(node)
291 node.__dict__["parentNode"] = self
292
293def _in_document(node):
294 # return True iff node is part of a document tree
295 while node is not None:
296 if node.nodeType == Node.DOCUMENT_NODE:
297 return True
298 node = node.parentNode
299 return False
Fred Drake55c38192000-06-29 19:39:57 +0000300
Fred Drake1f549022000-09-24 05:21:58 +0000301def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000302 "Writes datachars to writer."
Martin v. Löwis787354c2003-01-25 15:28:29 +0000303 data = data.replace("&", "&amp;").replace("<", "&lt;")
304 data = data.replace("\"", "&quot;").replace(">", "&gt;")
Fred Drake55c38192000-06-29 19:39:57 +0000305 writer.write(data)
306
Martin v. Löwis787354c2003-01-25 15:28:29 +0000307def _get_elements_by_tagName_helper(parent, name, 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 and \
310 (name == "*" or node.tagName == name):
311 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000312 _get_elements_by_tagName_helper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000313 return rc
314
Martin v. Löwis787354c2003-01-25 15:28:29 +0000315def _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000316 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000317 if node.nodeType == Node.ELEMENT_NODE:
Martin v. Löwised525fb2001-06-03 14:06:42 +0000318 if ((localName == "*" or node.localName == localName) and
Fred Drake1f549022000-09-24 05:21:58 +0000319 (nsURI == "*" or node.namespaceURI == nsURI)):
320 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000321 _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000322 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000323
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000324class DocumentFragment(Node):
325 nodeType = Node.DOCUMENT_FRAGMENT_NODE
326 nodeName = "#document-fragment"
327 nodeValue = None
328 attributes = None
329 parentNode = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000330 _child_node_types = (Node.ELEMENT_NODE,
331 Node.TEXT_NODE,
332 Node.CDATA_SECTION_NODE,
333 Node.ENTITY_REFERENCE_NODE,
334 Node.PROCESSING_INSTRUCTION_NODE,
335 Node.COMMENT_NODE,
336 Node.NOTATION_NODE)
337
338 def __init__(self):
339 self.childNodes = NodeList()
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000340
341
Fred Drake55c38192000-06-29 19:39:57 +0000342class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000343 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000344 attributes = None
345 ownerElement = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000346 specified = False
347 _is_id = False
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000348
Martin v. Löwis787354c2003-01-25 15:28:29 +0000349 _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
350
351 def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
352 prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000353 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000354 d = self.__dict__
Fred Drake4ccf4a12000-11-21 22:02:22 +0000355 d["nodeName"] = d["name"] = qName
356 d["namespaceURI"] = namespaceURI
357 d["prefix"] = prefix
Martin v. Löwis787354c2003-01-25 15:28:29 +0000358 d['childNodes'] = NodeList()
359
360 # Add the single child node that represents the value of the attr
361 self.childNodes.append(Text())
362
Paul Prescod73678da2000-07-01 04:58:47 +0000363 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000364
Martin v. Löwis787354c2003-01-25 15:28:29 +0000365 def _get_localName(self):
Alex Martelli0ee43512006-08-21 19:53:20 +0000366 if 'localName' in self.__dict__:
Guido van Rossum3e1f85e2007-07-27 18:03:11 +0000367 return self.__dict__['localName']
Martin v. Löwis787354c2003-01-25 15:28:29 +0000368 return self.nodeName.split(":", 1)[-1]
369
370 def _get_name(self):
371 return self.name
372
373 def _get_specified(self):
374 return self.specified
375
Fred Drake1f549022000-09-24 05:21:58 +0000376 def __setattr__(self, name, value):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000377 d = self.__dict__
Fred Drake1f549022000-09-24 05:21:58 +0000378 if name in ("value", "nodeValue"):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000379 d["value"] = d["nodeValue"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000380 d2 = self.childNodes[0].__dict__
381 d2["data"] = d2["nodeValue"] = value
382 if self.ownerElement is not None:
383 _clear_id_cache(self.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000384 elif name in ("name", "nodeName"):
385 d["name"] = d["nodeName"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000386 if self.ownerElement is not None:
387 _clear_id_cache(self.ownerElement)
Fred Drake55c38192000-06-29 19:39:57 +0000388 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000389 d[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000390
Martin v. Löwis995359c2003-01-26 08:59:32 +0000391 def _set_prefix(self, prefix):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000392 nsuri = self.namespaceURI
Martin v. Löwis995359c2003-01-26 08:59:32 +0000393 if prefix == "xmlns":
394 if nsuri and nsuri != XMLNS_NAMESPACE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000395 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000396 "illegal use of 'xmlns' prefix for the wrong namespace")
397 d = self.__dict__
398 d['prefix'] = prefix
399 if prefix is None:
400 newName = self.localName
401 else:
Martin v. Löwis995359c2003-01-26 08:59:32 +0000402 newName = "%s:%s" % (prefix, self.localName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000403 if self.ownerElement:
404 _clear_id_cache(self.ownerElement)
405 d['nodeName'] = d['name'] = newName
406
407 def _set_value(self, value):
408 d = self.__dict__
409 d['value'] = d['nodeValue'] = value
410 if self.ownerElement:
411 _clear_id_cache(self.ownerElement)
412 self.childNodes[0].data = value
413
414 def unlink(self):
415 # This implementation does not call the base implementation
416 # since most of that is not needed, and the expense of the
417 # method call is not warranted. We duplicate the removal of
418 # children, but that's all we needed from the base class.
419 elem = self.ownerElement
420 if elem is not None:
421 del elem._attrs[self.nodeName]
422 del elem._attrsNS[(self.namespaceURI, self.localName)]
423 if self._is_id:
424 self._is_id = False
425 elem._magic_id_nodes -= 1
426 self.ownerDocument._magic_id_count -= 1
427 for child in self.childNodes:
428 child.unlink()
429 del self.childNodes[:]
430
431 def _get_isId(self):
432 if self._is_id:
433 return True
434 doc = self.ownerDocument
435 elem = self.ownerElement
436 if doc is None or elem is None:
437 return False
438
439 info = doc._get_elem_info(elem)
440 if info is None:
441 return False
442 if self.namespaceURI:
443 return info.isIdNS(self.namespaceURI, self.localName)
444 else:
445 return info.isId(self.nodeName)
446
447 def _get_schemaType(self):
448 doc = self.ownerDocument
449 elem = self.ownerElement
450 if doc is None or elem is None:
451 return _no_type
452
453 info = doc._get_elem_info(elem)
454 if info is None:
455 return _no_type
456 if self.namespaceURI:
457 return info.getAttributeTypeNS(self.namespaceURI, self.localName)
458 else:
459 return info.getAttributeType(self.nodeName)
460
461defproperty(Attr, "isId", doc="True if this attribute is an ID.")
462defproperty(Attr, "localName", doc="Namespace-local name of this attribute.")
463defproperty(Attr, "schemaType", doc="Schema type for this attribute.")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000464
Fred Drakef7cf40d2000-12-14 18:16:11 +0000465
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000466class NamedNodeMap(object):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000467 """The attribute list is a transient interface to the underlying
468 dictionaries. Mutations here will change the underlying element's
Fred Drakef7cf40d2000-12-14 18:16:11 +0000469 dictionary.
470
471 Ordering is imposed artificially and does not reflect the order of
472 attributes as found in an input document.
473 """
Fred Drake4ccf4a12000-11-21 22:02:22 +0000474
Martin v. Löwis787354c2003-01-25 15:28:29 +0000475 __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
476
Fred Drake2998a552001-12-06 18:27:48 +0000477 def __init__(self, attrs, attrsNS, ownerElement):
Fred Drake1f549022000-09-24 05:21:58 +0000478 self._attrs = attrs
479 self._attrsNS = attrsNS
Fred Drake2998a552001-12-06 18:27:48 +0000480 self._ownerElement = ownerElement
Fred Drakef7cf40d2000-12-14 18:16:11 +0000481
Martin v. Löwis787354c2003-01-25 15:28:29 +0000482 def _get_length(self):
483 return len(self._attrs)
Fred Drake55c38192000-06-29 19:39:57 +0000484
Fred Drake1f549022000-09-24 05:21:58 +0000485 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000486 try:
Brett Cannon861fd6f2007-02-21 22:05:37 +0000487 return self[list(self._attrs.keys())[index]]
Fred Drake55c38192000-06-29 19:39:57 +0000488 except IndexError:
489 return None
Fred Drake55c38192000-06-29 19:39:57 +0000490
Fred Drake1f549022000-09-24 05:21:58 +0000491 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000492 L = []
493 for node in self._attrs.values():
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000494 L.append((node.nodeName, node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000495 return L
Fred Drake1f549022000-09-24 05:21:58 +0000496
497 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000498 L = []
499 for node in self._attrs.values():
Fred Drake49a5d032001-11-30 22:21:58 +0000500 L.append(((node.namespaceURI, node.localName), node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000501 return L
Fred Drake16f63292000-10-23 18:09:50 +0000502
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000503 def __contains__(self, key):
Christian Heimesc9543e42007-11-28 08:28:28 +0000504 if isinstance(key, str):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000505 return key in self._attrs
Martin v. Löwis787354c2003-01-25 15:28:29 +0000506 else:
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000507 return key in self._attrsNS
Martin v. Löwis787354c2003-01-25 15:28:29 +0000508
Fred Drake1f549022000-09-24 05:21:58 +0000509 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000510 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000511
Fred Drake1f549022000-09-24 05:21:58 +0000512 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000513 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000514
Fred Drake1f549022000-09-24 05:21:58 +0000515 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000516 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000517
Martin v. Löwis787354c2003-01-25 15:28:29 +0000518 def get(self, name, value=None):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000519 return self._attrs.get(name, value)
520
Martin v. Löwis787354c2003-01-25 15:28:29 +0000521 __len__ = _get_length
Fred Drake55c38192000-06-29 19:39:57 +0000522
Mark Dickinsona56c4672009-01-27 18:17:45 +0000523 def _cmp(self, other):
Fred Drake1f549022000-09-24 05:21:58 +0000524 if self._attrs is getattr(other, "_attrs", None):
Fred Drake55c38192000-06-29 19:39:57 +0000525 return 0
Fred Drake16f63292000-10-23 18:09:50 +0000526 else:
Mark Dickinsona56c4672009-01-27 18:17:45 +0000527 return (id(self) > id(other)) - (id(self) < id(other))
528
529 def __eq__(self, other):
530 return self._cmp(other) == 0
531
532 def __ge__(self, other):
533 return self._cmp(other) >= 0
534
535 def __gt__(self, other):
536 return self._cmp(other) > 0
537
538 def __le__(self, other):
539 return self._cmp(other) <= 0
540
541 def __lt__(self, other):
542 return self._cmp(other) < 0
543
544 def __ne__(self, other):
545 return self._cmp(other) != 0
Fred Drake55c38192000-06-29 19:39:57 +0000546
Fred Drake1f549022000-09-24 05:21:58 +0000547 def __getitem__(self, attname_or_tuple):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000548 if isinstance(attname_or_tuple, tuple):
Paul Prescod73678da2000-07-01 04:58:47 +0000549 return self._attrsNS[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000550 else:
Paul Prescod73678da2000-07-01 04:58:47 +0000551 return self._attrs[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000552
Paul Prescod1e688272000-07-01 19:21:47 +0000553 # same as set
Fred Drake1f549022000-09-24 05:21:58 +0000554 def __setitem__(self, attname, value):
Christian Heimesc9543e42007-11-28 08:28:28 +0000555 if isinstance(value, str):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000556 try:
557 node = self._attrs[attname]
558 except KeyError:
559 node = Attr(attname)
560 node.ownerDocument = self._ownerElement.ownerDocument
Martin v. Löwis995359c2003-01-26 08:59:32 +0000561 self.setNamedItem(node)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000562 node.value = value
Paul Prescod1e688272000-07-01 19:21:47 +0000563 else:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000564 if not isinstance(value, Attr):
Collin Winter70e79802007-08-24 18:57:22 +0000565 raise TypeError("value must be a string or Attr object")
Fred Drake1f549022000-09-24 05:21:58 +0000566 node = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000567 self.setNamedItem(node)
568
569 def getNamedItem(self, name):
570 try:
571 return self._attrs[name]
572 except KeyError:
573 return None
574
575 def getNamedItemNS(self, namespaceURI, localName):
576 try:
577 return self._attrsNS[(namespaceURI, localName)]
578 except KeyError:
579 return None
580
581 def removeNamedItem(self, name):
582 n = self.getNamedItem(name)
583 if n is not None:
584 _clear_id_cache(self._ownerElement)
585 del self._attrs[n.nodeName]
586 del self._attrsNS[(n.namespaceURI, n.localName)]
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000587 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000588 n.__dict__['ownerElement'] = None
589 return n
590 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000591 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000592
593 def removeNamedItemNS(self, namespaceURI, localName):
594 n = self.getNamedItemNS(namespaceURI, localName)
595 if n is not None:
596 _clear_id_cache(self._ownerElement)
597 del self._attrsNS[(n.namespaceURI, n.localName)]
598 del self._attrs[n.nodeName]
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000599 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000600 n.__dict__['ownerElement'] = None
601 return n
602 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000603 raise xml.dom.NotFoundErr()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000604
605 def setNamedItem(self, node):
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000606 if not isinstance(node, Attr):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000607 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000608 "%s cannot be child of %s" % (repr(node), repr(self)))
Fred Drakef7cf40d2000-12-14 18:16:11 +0000609 old = self._attrs.get(node.name)
Paul Prescod1e688272000-07-01 19:21:47 +0000610 if old:
611 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000612 self._attrs[node.name] = node
613 self._attrsNS[(node.namespaceURI, node.localName)] = node
Fred Drake2998a552001-12-06 18:27:48 +0000614 node.ownerElement = self._ownerElement
Martin v. Löwis787354c2003-01-25 15:28:29 +0000615 _clear_id_cache(node.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000616 return old
617
618 def setNamedItemNS(self, node):
619 return self.setNamedItem(node)
Paul Prescod73678da2000-07-01 04:58:47 +0000620
Fred Drake1f549022000-09-24 05:21:58 +0000621 def __delitem__(self, attname_or_tuple):
622 node = self[attname_or_tuple]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000623 _clear_id_cache(node.ownerElement)
Paul Prescod73678da2000-07-01 04:58:47 +0000624 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000625
626 def __getstate__(self):
627 return self._attrs, self._attrsNS, self._ownerElement
628
629 def __setstate__(self, state):
630 self._attrs, self._attrsNS, self._ownerElement = state
631
632defproperty(NamedNodeMap, "length",
633 doc="Number of nodes in the NamedNodeMap.")
Fred Drakef7cf40d2000-12-14 18:16:11 +0000634
635AttributeList = NamedNodeMap
636
Fred Drake1f549022000-09-24 05:21:58 +0000637
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000638class TypeInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000639 __slots__ = 'namespace', 'name'
640
641 def __init__(self, namespace, name):
642 self.namespace = namespace
643 self.name = name
644
645 def __repr__(self):
646 if self.namespace:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000647 return "<TypeInfo %r (from %r)>" % (self.name, self.namespace)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000648 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000649 return "<TypeInfo %r>" % self.name
Martin v. Löwis787354c2003-01-25 15:28:29 +0000650
651 def _get_name(self):
652 return self.name
653
654 def _get_namespace(self):
655 return self.namespace
656
657_no_type = TypeInfo(None, None)
658
Martin v. Löwisa2fda0d2000-10-07 12:10:28 +0000659class Element(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000660 nodeType = Node.ELEMENT_NODE
Martin v. Löwis787354c2003-01-25 15:28:29 +0000661 nodeValue = None
662 schemaType = _no_type
663
664 _magic_id_nodes = 0
665
666 _child_node_types = (Node.ELEMENT_NODE,
667 Node.PROCESSING_INSTRUCTION_NODE,
668 Node.COMMENT_NODE,
669 Node.TEXT_NODE,
670 Node.CDATA_SECTION_NODE,
671 Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000672
Fred Drake49a5d032001-11-30 22:21:58 +0000673 def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
Fred Drake1f549022000-09-24 05:21:58 +0000674 localName=None):
Fred Drake55c38192000-06-29 19:39:57 +0000675 self.tagName = self.nodeName = tagName
Fred Drake1f549022000-09-24 05:21:58 +0000676 self.prefix = prefix
677 self.namespaceURI = namespaceURI
Martin v. Löwis787354c2003-01-25 15:28:29 +0000678 self.childNodes = NodeList()
Fred Drake55c38192000-06-29 19:39:57 +0000679
Fred Drake4ccf4a12000-11-21 22:02:22 +0000680 self._attrs = {} # attributes are double-indexed:
681 self._attrsNS = {} # tagName -> Attribute
682 # URI,localName -> Attribute
683 # in the future: consider lazy generation
684 # of attribute objects this is too tricky
685 # for now because of headaches with
686 # namespaces.
687
Martin v. Löwis787354c2003-01-25 15:28:29 +0000688 def _get_localName(self):
Alex Martelli0ee43512006-08-21 19:53:20 +0000689 if 'localName' in self.__dict__:
Guido van Rossum3e1f85e2007-07-27 18:03:11 +0000690 return self.__dict__['localName']
Martin v. Löwis787354c2003-01-25 15:28:29 +0000691 return self.tagName.split(":", 1)[-1]
692
693 def _get_tagName(self):
694 return self.tagName
Fred Drake4ccf4a12000-11-21 22:02:22 +0000695
696 def unlink(self):
Brett Cannon861fd6f2007-02-21 22:05:37 +0000697 for attr in list(self._attrs.values()):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000698 attr.unlink()
699 self._attrs = None
700 self._attrsNS = None
701 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000702
Fred Drake1f549022000-09-24 05:21:58 +0000703 def getAttribute(self, attname):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000704 try:
705 return self._attrs[attname].value
706 except KeyError:
707 return ""
Fred Drake55c38192000-06-29 19:39:57 +0000708
Fred Drake1f549022000-09-24 05:21:58 +0000709 def getAttributeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000710 try:
711 return self._attrsNS[(namespaceURI, localName)].value
712 except KeyError:
713 return ""
Fred Drake1f549022000-09-24 05:21:58 +0000714
715 def setAttribute(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000716 attr = self.getAttributeNode(attname)
717 if attr is None:
718 attr = Attr(attname)
719 # for performance
720 d = attr.__dict__
721 d["value"] = d["nodeValue"] = value
722 d["ownerDocument"] = self.ownerDocument
723 self.setAttributeNode(attr)
724 elif value != attr.value:
725 d = attr.__dict__
726 d["value"] = d["nodeValue"] = value
727 if attr.isId:
728 _clear_id_cache(self)
Fred Drake55c38192000-06-29 19:39:57 +0000729
Fred Drake1f549022000-09-24 05:21:58 +0000730 def setAttributeNS(self, namespaceURI, qualifiedName, value):
731 prefix, localname = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000732 attr = self.getAttributeNodeNS(namespaceURI, localname)
733 if attr is None:
734 # for performance
735 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
736 d = attr.__dict__
737 d["prefix"] = prefix
738 d["nodeName"] = qualifiedName
739 d["value"] = d["nodeValue"] = value
740 d["ownerDocument"] = self.ownerDocument
741 self.setAttributeNode(attr)
742 else:
743 d = attr.__dict__
744 if value != attr.value:
745 d["value"] = d["nodeValue"] = value
746 if attr.isId:
747 _clear_id_cache(self)
748 if attr.prefix != prefix:
749 d["prefix"] = prefix
750 d["nodeName"] = qualifiedName
Fred Drake55c38192000-06-29 19:39:57 +0000751
Fred Drake1f549022000-09-24 05:21:58 +0000752 def getAttributeNode(self, attrname):
753 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000754
Fred Drake1f549022000-09-24 05:21:58 +0000755 def getAttributeNodeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000756 return self._attrsNS.get((namespaceURI, localName))
Paul Prescod73678da2000-07-01 04:58:47 +0000757
Fred Drake1f549022000-09-24 05:21:58 +0000758 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000759 if attr.ownerElement not in (None, self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000760 raise xml.dom.InuseAttributeErr("attribute node already owned")
Martin v. Löwis787354c2003-01-25 15:28:29 +0000761 old1 = self._attrs.get(attr.name, None)
762 if old1 is not None:
763 self.removeAttributeNode(old1)
764 old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
765 if old2 is not None and old2 is not old1:
766 self.removeAttributeNode(old2)
767 _set_attribute_node(self, attr)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000768
Martin v. Löwis787354c2003-01-25 15:28:29 +0000769 if old1 is not attr:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000770 # It might have already been part of this node, in which case
771 # it doesn't represent a change, and should not be returned.
Martin v. Löwis787354c2003-01-25 15:28:29 +0000772 return old1
773 if old2 is not attr:
774 return old2
Fred Drake55c38192000-06-29 19:39:57 +0000775
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000776 setAttributeNodeNS = setAttributeNode
777
Fred Drake1f549022000-09-24 05:21:58 +0000778 def removeAttribute(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000779 try:
780 attr = self._attrs[name]
781 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000782 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000783 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000784
Fred Drake1f549022000-09-24 05:21:58 +0000785 def removeAttributeNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000786 try:
787 attr = self._attrsNS[(namespaceURI, localName)]
788 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000789 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000790 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000791
Fred Drake1f549022000-09-24 05:21:58 +0000792 def removeAttributeNode(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000793 if node is None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000794 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000795 try:
796 self._attrs[node.name]
797 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000798 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000799 _clear_id_cache(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000800 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000801 # Restore this since the node is still useful and otherwise
802 # unlinked
803 node.ownerDocument = self.ownerDocument
Fred Drake16f63292000-10-23 18:09:50 +0000804
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000805 removeAttributeNodeNS = removeAttributeNode
806
Martin v. Löwis156c3372000-12-28 18:40:56 +0000807 def hasAttribute(self, name):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000808 return name in self._attrs
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000809
Martin v. Löwis156c3372000-12-28 18:40:56 +0000810 def hasAttributeNS(self, namespaceURI, localName):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000811 return (namespaceURI, localName) in self._attrsNS
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000812
Fred Drake1f549022000-09-24 05:21:58 +0000813 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000814 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000815
Fred Drake1f549022000-09-24 05:21:58 +0000816 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000817 return _get_elements_by_tagName_ns_helper(
818 self, namespaceURI, localName, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000819
Fred Drake1f549022000-09-24 05:21:58 +0000820 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000821 return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000822
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000823 def writexml(self, writer, indent="", addindent="", newl=""):
824 # indent = current indentation
825 # addindent = indentation to add to higher levels
826 # newl = newline string
827 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000828
Fred Drake4ccf4a12000-11-21 22:02:22 +0000829 attrs = self._get_attributes()
Brett Cannon861fd6f2007-02-21 22:05:37 +0000830 a_names = sorted(attrs.keys())
Fred Drake55c38192000-06-29 19:39:57 +0000831
832 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000833 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000834 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000835 writer.write("\"")
836 if self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000837 writer.write(">%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000838 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000839 node.writexml(writer,indent+addindent,addindent,newl)
840 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
Fred Drake55c38192000-06-29 19:39:57 +0000841 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000842 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000843
Fred Drake1f549022000-09-24 05:21:58 +0000844 def _get_attributes(self):
Fred Drake2998a552001-12-06 18:27:48 +0000845 return NamedNodeMap(self._attrs, self._attrsNS, self)
Fred Drake55c38192000-06-29 19:39:57 +0000846
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000847 def hasAttributes(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000848 if self._attrs:
849 return True
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000850 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000851 return False
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000852
Martin v. Löwis787354c2003-01-25 15:28:29 +0000853 # DOM Level 3 attributes, based on the 22 Oct 2002 draft
854
855 def setIdAttribute(self, name):
856 idAttr = self.getAttributeNode(name)
857 self.setIdAttributeNode(idAttr)
858
859 def setIdAttributeNS(self, namespaceURI, localName):
860 idAttr = self.getAttributeNodeNS(namespaceURI, localName)
861 self.setIdAttributeNode(idAttr)
862
863 def setIdAttributeNode(self, idAttr):
864 if idAttr is None or not self.isSameNode(idAttr.ownerElement):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000865 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000866 if _get_containing_entref(self) is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000867 raise xml.dom.NoModificationAllowedErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000868 if not idAttr._is_id:
869 idAttr.__dict__['_is_id'] = True
870 self._magic_id_nodes += 1
871 self.ownerDocument._magic_id_count += 1
872 _clear_id_cache(self)
873
874defproperty(Element, "attributes",
875 doc="NamedNodeMap of attributes on the element.")
876defproperty(Element, "localName",
877 doc="Namespace-local name of this element.")
878
879
880def _set_attribute_node(element, attr):
881 _clear_id_cache(element)
882 element._attrs[attr.name] = attr
883 element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
884
885 # This creates a circular reference, but Element.unlink()
886 # breaks the cycle since the references to the attribute
887 # dictionaries are tossed.
888 attr.__dict__['ownerElement'] = element
889
890
891class Childless:
892 """Mixin that makes childless-ness easy to implement and avoids
893 the complexity of the Node methods that deal with children.
894 """
895
Fred Drake4ccf4a12000-11-21 22:02:22 +0000896 attributes = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000897 childNodes = EmptyNodeList()
898 firstChild = None
899 lastChild = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000900
Martin v. Löwis787354c2003-01-25 15:28:29 +0000901 def _get_firstChild(self):
902 return None
Fred Drake55c38192000-06-29 19:39:57 +0000903
Martin v. Löwis787354c2003-01-25 15:28:29 +0000904 def _get_lastChild(self):
905 return None
Fred Drake1f549022000-09-24 05:21:58 +0000906
Martin v. Löwis787354c2003-01-25 15:28:29 +0000907 def appendChild(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000908 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000909 self.nodeName + " nodes cannot have children")
910
911 def hasChildNodes(self):
912 return False
913
914 def insertBefore(self, newChild, refChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000915 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000916 self.nodeName + " nodes do not have children")
917
918 def removeChild(self, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000919 raise xml.dom.NotFoundErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000920 self.nodeName + " nodes do not have children")
921
922 def replaceChild(self, newChild, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000923 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000924 self.nodeName + " nodes do not have children")
925
926
927class ProcessingInstruction(Childless, Node):
Fred Drake1f549022000-09-24 05:21:58 +0000928 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000929
Fred Drake1f549022000-09-24 05:21:58 +0000930 def __init__(self, target, data):
Fred Drake55c38192000-06-29 19:39:57 +0000931 self.target = self.nodeName = target
932 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000933
Martin v. Löwis787354c2003-01-25 15:28:29 +0000934 def _get_data(self):
935 return self.data
936 def _set_data(self, value):
937 d = self.__dict__
938 d['data'] = d['nodeValue'] = value
939
940 def _get_target(self):
941 return self.target
942 def _set_target(self, value):
943 d = self.__dict__
944 d['target'] = d['nodeName'] = value
945
946 def __setattr__(self, name, value):
947 if name == "data" or name == "nodeValue":
948 self.__dict__['data'] = self.__dict__['nodeValue'] = value
949 elif name == "target" or name == "nodeName":
950 self.__dict__['target'] = self.__dict__['nodeName'] = value
951 else:
952 self.__dict__[name] = value
953
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000954 def writexml(self, writer, indent="", addindent="", newl=""):
955 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000956
Martin v. Löwis787354c2003-01-25 15:28:29 +0000957
958class CharacterData(Childless, Node):
959 def _get_length(self):
960 return len(self.data)
961 __len__ = _get_length
962
963 def _get_data(self):
964 return self.__dict__['data']
965 def _set_data(self, data):
966 d = self.__dict__
967 d['data'] = d['nodeValue'] = data
968
969 _get_nodeValue = _get_data
970 _set_nodeValue = _set_data
971
972 def __setattr__(self, name, value):
973 if name == "data" or name == "nodeValue":
974 self.__dict__['data'] = self.__dict__['nodeValue'] = value
975 else:
976 self.__dict__[name] = value
Fred Drake87432f42001-04-04 14:09:46 +0000977
Fred Drake55c38192000-06-29 19:39:57 +0000978 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000979 data = self.data
980 if len(data) > 10:
Fred Drake1f549022000-09-24 05:21:58 +0000981 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000982 else:
Fred Drake1f549022000-09-24 05:21:58 +0000983 dotdotdot = ""
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000984 return '<DOM %s node "%r%s">' % (
Martin v. Löwis787354c2003-01-25 15:28:29 +0000985 self.__class__.__name__, data[0:10], dotdotdot)
Fred Drake87432f42001-04-04 14:09:46 +0000986
987 def substringData(self, offset, count):
988 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000989 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000990 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000991 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000992 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000993 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000994 return self.data[offset:offset+count]
995
996 def appendData(self, arg):
997 self.data = self.data + arg
Fred Drake87432f42001-04-04 14:09:46 +0000998
999 def insertData(self, offset, arg):
1000 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001001 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001002 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001003 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +00001004 if arg:
1005 self.data = "%s%s%s" % (
1006 self.data[:offset], arg, self.data[offset:])
Fred Drake87432f42001-04-04 14:09:46 +00001007
1008 def deleteData(self, offset, count):
1009 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001010 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001011 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001012 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +00001013 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001014 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001015 if count:
1016 self.data = self.data[:offset] + self.data[offset+count:]
Fred Drake87432f42001-04-04 14:09:46 +00001017
1018 def replaceData(self, offset, count, arg):
1019 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001020 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001021 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001022 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +00001023 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001024 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001025 if count:
1026 self.data = "%s%s%s" % (
1027 self.data[:offset], arg, self.data[offset+count:])
Martin v. Löwis787354c2003-01-25 15:28:29 +00001028
1029defproperty(CharacterData, "length", doc="Length of the string data.")
1030
Fred Drake87432f42001-04-04 14:09:46 +00001031
1032class Text(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001033 # Make sure we don't add an instance __dict__ if we don't already
1034 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001035 # XXX this does not work, CharacterData is an old-style class
1036 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001037
Fred Drake87432f42001-04-04 14:09:46 +00001038 nodeType = Node.TEXT_NODE
1039 nodeName = "#text"
1040 attributes = None
Fred Drake55c38192000-06-29 19:39:57 +00001041
Fred Drakef7cf40d2000-12-14 18:16:11 +00001042 def splitText(self, offset):
1043 if offset < 0 or offset > len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001044 raise xml.dom.IndexSizeErr("illegal offset value")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001045 newText = self.__class__()
1046 newText.data = self.data[offset:]
1047 newText.ownerDocument = self.ownerDocument
Fred Drakef7cf40d2000-12-14 18:16:11 +00001048 next = self.nextSibling
1049 if self.parentNode and self in self.parentNode.childNodes:
1050 if next is None:
1051 self.parentNode.appendChild(newText)
1052 else:
1053 self.parentNode.insertBefore(newText, next)
1054 self.data = self.data[:offset]
1055 return newText
1056
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001057 def writexml(self, writer, indent="", addindent="", newl=""):
1058 _write_data(writer, "%s%s%s"%(indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001059
Martin v. Löwis787354c2003-01-25 15:28:29 +00001060 # DOM Level 3 (WD 9 April 2002)
1061
1062 def _get_wholeText(self):
1063 L = [self.data]
1064 n = self.previousSibling
1065 while n is not None:
1066 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1067 L.insert(0, n.data)
1068 n = n.previousSibling
1069 else:
1070 break
1071 n = self.nextSibling
1072 while n is not None:
1073 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1074 L.append(n.data)
1075 n = n.nextSibling
1076 else:
1077 break
1078 return ''.join(L)
1079
1080 def replaceWholeText(self, content):
1081 # XXX This needs to be seriously changed if minidom ever
1082 # supports EntityReference nodes.
1083 parent = self.parentNode
1084 n = self.previousSibling
1085 while n is not None:
1086 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1087 next = n.previousSibling
1088 parent.removeChild(n)
1089 n = next
1090 else:
1091 break
1092 n = self.nextSibling
1093 if not content:
1094 parent.removeChild(self)
1095 while n is not None:
1096 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1097 next = n.nextSibling
1098 parent.removeChild(n)
1099 n = next
1100 else:
1101 break
1102 if content:
1103 d = self.__dict__
1104 d['data'] = content
1105 d['nodeValue'] = content
1106 return self
1107 else:
1108 return None
1109
1110 def _get_isWhitespaceInElementContent(self):
1111 if self.data.strip():
1112 return False
1113 elem = _get_containing_element(self)
1114 if elem is None:
1115 return False
1116 info = self.ownerDocument._get_elem_info(elem)
1117 if info is None:
1118 return False
1119 else:
1120 return info.isElementContent()
1121
1122defproperty(Text, "isWhitespaceInElementContent",
1123 doc="True iff this text node contains only whitespace"
1124 " and is in element content.")
1125defproperty(Text, "wholeText",
1126 doc="The text of all logically-adjacent text nodes.")
1127
1128
1129def _get_containing_element(node):
1130 c = node.parentNode
1131 while c is not None:
1132 if c.nodeType == Node.ELEMENT_NODE:
1133 return c
1134 c = c.parentNode
1135 return None
1136
1137def _get_containing_entref(node):
1138 c = node.parentNode
1139 while c is not None:
1140 if c.nodeType == Node.ENTITY_REFERENCE_NODE:
1141 return c
1142 c = c.parentNode
1143 return None
1144
1145
Alex Martelli0ee43512006-08-21 19:53:20 +00001146class Comment(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001147 nodeType = Node.COMMENT_NODE
1148 nodeName = "#comment"
1149
1150 def __init__(self, data):
1151 self.data = self.nodeValue = data
1152
1153 def writexml(self, writer, indent="", addindent="", newl=""):
Benjamin Peterson2b7411d2008-05-26 17:36:47 +00001154 if "--" in self.data:
1155 raise ValueError("'--' is not allowed in a comment node")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001156 writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
1157
Fred Drake87432f42001-04-04 14:09:46 +00001158
1159class CDATASection(Text):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001160 # Make sure we don't add an instance __dict__ if we don't already
1161 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001162 # XXX this does not work, Text is an old-style class
1163 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001164
Fred Drake87432f42001-04-04 14:09:46 +00001165 nodeType = Node.CDATA_SECTION_NODE
1166 nodeName = "#cdata-section"
1167
1168 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001169 if self.data.find("]]>") >= 0:
1170 raise ValueError("']]>' not allowed in a CDATA section")
Guido van Rossum5b5e0b92001-09-19 13:28:25 +00001171 writer.write("<![CDATA[%s]]>" % self.data)
Fred Drake87432f42001-04-04 14:09:46 +00001172
1173
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001174class ReadOnlySequentialNamedNodeMap(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001175 __slots__ = '_seq',
1176
1177 def __init__(self, seq=()):
1178 # seq should be a list or tuple
1179 self._seq = seq
1180
1181 def __len__(self):
1182 return len(self._seq)
1183
1184 def _get_length(self):
1185 return len(self._seq)
1186
1187 def getNamedItem(self, name):
1188 for n in self._seq:
1189 if n.nodeName == name:
1190 return n
1191
1192 def getNamedItemNS(self, namespaceURI, localName):
1193 for n in self._seq:
1194 if n.namespaceURI == namespaceURI and n.localName == localName:
1195 return n
1196
1197 def __getitem__(self, name_or_tuple):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001198 if isinstance(name_or_tuple, tuple):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001199 node = self.getNamedItemNS(*name_or_tuple)
1200 else:
1201 node = self.getNamedItem(name_or_tuple)
1202 if node is None:
Collin Winter70e79802007-08-24 18:57:22 +00001203 raise KeyError(name_or_tuple)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001204 return node
1205
1206 def item(self, index):
1207 if index < 0:
1208 return None
1209 try:
1210 return self._seq[index]
1211 except IndexError:
1212 return None
1213
1214 def removeNamedItem(self, name):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001215 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001216 "NamedNodeMap instance is read-only")
1217
1218 def removeNamedItemNS(self, namespaceURI, localName):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001219 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001220 "NamedNodeMap instance is read-only")
1221
1222 def setNamedItem(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001223 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001224 "NamedNodeMap instance is read-only")
1225
1226 def setNamedItemNS(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001227 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001228 "NamedNodeMap instance is read-only")
1229
1230 def __getstate__(self):
1231 return [self._seq]
1232
1233 def __setstate__(self, state):
1234 self._seq = state[0]
1235
1236defproperty(ReadOnlySequentialNamedNodeMap, "length",
1237 doc="Number of entries in the NamedNodeMap.")
Paul Prescod73678da2000-07-01 04:58:47 +00001238
Fred Drakef7cf40d2000-12-14 18:16:11 +00001239
Martin v. Löwis787354c2003-01-25 15:28:29 +00001240class Identified:
1241 """Mix-in class that supports the publicId and systemId attributes."""
1242
Martin v. Löwis995359c2003-01-26 08:59:32 +00001243 # XXX this does not work, this is an old-style class
1244 # __slots__ = 'publicId', 'systemId'
Martin v. Löwis787354c2003-01-25 15:28:29 +00001245
1246 def _identified_mixin_init(self, publicId, systemId):
1247 self.publicId = publicId
1248 self.systemId = systemId
1249
1250 def _get_publicId(self):
1251 return self.publicId
1252
1253 def _get_systemId(self):
1254 return self.systemId
1255
1256class DocumentType(Identified, Childless, Node):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001257 nodeType = Node.DOCUMENT_TYPE_NODE
1258 nodeValue = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001259 name = None
1260 publicId = None
1261 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +00001262 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001263
1264 def __init__(self, qualifiedName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001265 self.entities = ReadOnlySequentialNamedNodeMap()
1266 self.notations = ReadOnlySequentialNamedNodeMap()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001267 if qualifiedName:
1268 prefix, localname = _nssplit(qualifiedName)
1269 self.name = localname
Martin v. Löwis787354c2003-01-25 15:28:29 +00001270 self.nodeName = self.name
1271
1272 def _get_internalSubset(self):
1273 return self.internalSubset
1274
1275 def cloneNode(self, deep):
1276 if self.ownerDocument is None:
1277 # it's ok
1278 clone = DocumentType(None)
1279 clone.name = self.name
1280 clone.nodeName = self.name
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001281 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001282 if deep:
1283 clone.entities._seq = []
1284 clone.notations._seq = []
1285 for n in self.notations._seq:
1286 notation = Notation(n.nodeName, n.publicId, n.systemId)
1287 clone.notations._seq.append(notation)
1288 n._call_user_data_handler(operation, n, notation)
1289 for e in self.entities._seq:
1290 entity = Entity(e.nodeName, e.publicId, e.systemId,
1291 e.notationName)
1292 entity.actualEncoding = e.actualEncoding
1293 entity.encoding = e.encoding
1294 entity.version = e.version
1295 clone.entities._seq.append(entity)
1296 e._call_user_data_handler(operation, n, entity)
1297 self._call_user_data_handler(operation, self, clone)
1298 return clone
1299 else:
1300 return None
1301
1302 def writexml(self, writer, indent="", addindent="", newl=""):
1303 writer.write("<!DOCTYPE ")
1304 writer.write(self.name)
1305 if self.publicId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001306 writer.write("%s PUBLIC '%s'%s '%s'"
1307 % (newl, self.publicId, newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001308 elif self.systemId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001309 writer.write("%s SYSTEM '%s'" % (newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001310 if self.internalSubset is not None:
1311 writer.write(" [")
1312 writer.write(self.internalSubset)
1313 writer.write("]")
Georg Brandl175a7dc2005-08-25 22:02:43 +00001314 writer.write(">"+newl)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001315
1316class Entity(Identified, Node):
1317 attributes = None
1318 nodeType = Node.ENTITY_NODE
1319 nodeValue = None
1320
1321 actualEncoding = None
1322 encoding = None
1323 version = None
1324
1325 def __init__(self, name, publicId, systemId, notation):
1326 self.nodeName = name
1327 self.notationName = notation
1328 self.childNodes = NodeList()
1329 self._identified_mixin_init(publicId, systemId)
1330
1331 def _get_actualEncoding(self):
1332 return self.actualEncoding
1333
1334 def _get_encoding(self):
1335 return self.encoding
1336
1337 def _get_version(self):
1338 return self.version
1339
1340 def appendChild(self, newChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001341 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001342 "cannot append children to an entity node")
1343
1344 def insertBefore(self, newChild, refChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001345 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001346 "cannot insert children below an entity node")
1347
1348 def removeChild(self, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001349 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001350 "cannot remove children from an entity node")
1351
1352 def replaceChild(self, newChild, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001353 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001354 "cannot replace children of an entity node")
1355
1356class Notation(Identified, Childless, Node):
1357 nodeType = Node.NOTATION_NODE
1358 nodeValue = None
1359
1360 def __init__(self, name, publicId, systemId):
1361 self.nodeName = name
1362 self._identified_mixin_init(publicId, systemId)
Fred Drakef7cf40d2000-12-14 18:16:11 +00001363
1364
Martin v. Löwis787354c2003-01-25 15:28:29 +00001365class DOMImplementation(DOMImplementationLS):
1366 _features = [("core", "1.0"),
1367 ("core", "2.0"),
1368 ("core", "3.0"),
1369 ("core", None),
1370 ("xml", "1.0"),
1371 ("xml", "2.0"),
1372 ("xml", "3.0"),
1373 ("xml", None),
1374 ("ls-load", "3.0"),
1375 ("ls-load", None),
1376 ]
1377
Fred Drakef7cf40d2000-12-14 18:16:11 +00001378 def hasFeature(self, feature, version):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001379 if version == "":
1380 version = None
1381 return (feature.lower(), version) in self._features
Fred Drakef7cf40d2000-12-14 18:16:11 +00001382
1383 def createDocument(self, namespaceURI, qualifiedName, doctype):
1384 if doctype and doctype.parentNode is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001385 raise xml.dom.WrongDocumentErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001386 "doctype object owned by another DOM tree")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001387 doc = self._create_document()
1388
1389 add_root_element = not (namespaceURI is None
1390 and qualifiedName is None
1391 and doctype is None)
1392
1393 if not qualifiedName and add_root_element:
Martin v. Löwisb417be22001-02-06 01:16:06 +00001394 # The spec is unclear what to raise here; SyntaxErr
1395 # would be the other obvious candidate. Since Xerces raises
1396 # InvalidCharacterErr, and since SyntaxErr is not listed
1397 # for createDocument, that seems to be the better choice.
1398 # XXX: need to check for illegal characters here and in
1399 # createElement.
Martin v. Löwis787354c2003-01-25 15:28:29 +00001400
1401 # DOM Level III clears this up when talking about the return value
1402 # of this function. If namespaceURI, qName and DocType are
1403 # Null the document is returned without a document element
1404 # Otherwise if doctype or namespaceURI are not None
1405 # Then we go back to the above problem
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001406 raise xml.dom.InvalidCharacterErr("Element with no name")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001407
1408 if add_root_element:
1409 prefix, localname = _nssplit(qualifiedName)
1410 if prefix == "xml" \
1411 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001412 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001413 if prefix and not namespaceURI:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001414 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001415 "illegal use of prefix without namespaces")
1416 element = doc.createElementNS(namespaceURI, qualifiedName)
1417 if doctype:
1418 doc.appendChild(doctype)
1419 doc.appendChild(element)
1420
1421 if doctype:
1422 doctype.parentNode = doctype.ownerDocument = doc
1423
Fred Drakef7cf40d2000-12-14 18:16:11 +00001424 doc.doctype = doctype
1425 doc.implementation = self
1426 return doc
1427
1428 def createDocumentType(self, qualifiedName, publicId, systemId):
1429 doctype = DocumentType(qualifiedName)
1430 doctype.publicId = publicId
1431 doctype.systemId = systemId
1432 return doctype
1433
Martin v. Löwis787354c2003-01-25 15:28:29 +00001434 # DOM Level 3 (WD 9 April 2002)
1435
1436 def getInterface(self, feature):
1437 if self.hasFeature(feature, None):
1438 return self
1439 else:
1440 return None
1441
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001442 # internal
Martin v. Löwis787354c2003-01-25 15:28:29 +00001443 def _create_document(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001444 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001445
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001446class ElementInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001447 """Object that represents content-model information for an element.
1448
1449 This implementation is not expected to be used in practice; DOM
1450 builders should provide implementations which do the right thing
1451 using information available to it.
1452
1453 """
1454
1455 __slots__ = 'tagName',
1456
1457 def __init__(self, name):
1458 self.tagName = name
1459
1460 def getAttributeType(self, aname):
1461 return _no_type
1462
1463 def getAttributeTypeNS(self, namespaceURI, localName):
1464 return _no_type
1465
1466 def isElementContent(self):
1467 return False
1468
1469 def isEmpty(self):
1470 """Returns true iff this element is declared to have an EMPTY
1471 content model."""
1472 return False
1473
1474 def isId(self, aname):
1475 """Returns true iff the named attribte is a DTD-style ID."""
1476 return False
1477
1478 def isIdNS(self, namespaceURI, localName):
1479 """Returns true iff the identified attribute is a DTD-style ID."""
1480 return False
1481
1482 def __getstate__(self):
1483 return self.tagName
1484
1485 def __setstate__(self, state):
1486 self.tagName = state
1487
1488def _clear_id_cache(node):
1489 if node.nodeType == Node.DOCUMENT_NODE:
1490 node._id_cache.clear()
1491 node._id_search_stack = None
1492 elif _in_document(node):
1493 node.ownerDocument._id_cache.clear()
1494 node.ownerDocument._id_search_stack= None
1495
1496class Document(Node, DocumentLS):
1497 _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
1498 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
1499
Fred Drake1f549022000-09-24 05:21:58 +00001500 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +00001501 nodeName = "#document"
1502 nodeValue = None
1503 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001504 doctype = None
1505 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001506 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001507
1508 implementation = DOMImplementation()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001509
1510 # Document attributes from Level 3 (WD 9 April 2002)
1511
1512 actualEncoding = None
1513 encoding = None
1514 standalone = None
1515 version = None
1516 strictErrorChecking = False
1517 errorHandler = None
1518 documentURI = None
1519
1520 _magic_id_count = 0
1521
1522 def __init__(self):
1523 self.childNodes = NodeList()
1524 # mapping of (namespaceURI, localName) -> ElementInfo
1525 # and tagName -> ElementInfo
1526 self._elem_info = {}
1527 self._id_cache = {}
1528 self._id_search_stack = None
1529
1530 def _get_elem_info(self, element):
1531 if element.namespaceURI:
1532 key = element.namespaceURI, element.localName
1533 else:
1534 key = element.tagName
1535 return self._elem_info.get(key)
1536
1537 def _get_actualEncoding(self):
1538 return self.actualEncoding
1539
1540 def _get_doctype(self):
1541 return self.doctype
1542
1543 def _get_documentURI(self):
1544 return self.documentURI
1545
1546 def _get_encoding(self):
1547 return self.encoding
1548
1549 def _get_errorHandler(self):
1550 return self.errorHandler
1551
1552 def _get_standalone(self):
1553 return self.standalone
1554
1555 def _get_strictErrorChecking(self):
1556 return self.strictErrorChecking
1557
1558 def _get_version(self):
1559 return self.version
Fred Drake55c38192000-06-29 19:39:57 +00001560
Fred Drake1f549022000-09-24 05:21:58 +00001561 def appendChild(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001562 if node.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001563 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001564 "%s cannot be child of %s" % (repr(node), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001565 if node.parentNode is not None:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001566 # This needs to be done before the next test since this
1567 # may *be* the document element, in which case it should
1568 # end up re-ordered to the end.
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001569 node.parentNode.removeChild(node)
1570
Fred Drakef7cf40d2000-12-14 18:16:11 +00001571 if node.nodeType == Node.ELEMENT_NODE \
1572 and self._get_documentElement():
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001573 raise xml.dom.HierarchyRequestErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001574 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +00001575 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +00001576
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001577 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001578 try:
1579 self.childNodes.remove(oldChild)
1580 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001581 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001582 oldChild.nextSibling = oldChild.previousSibling = None
1583 oldChild.parentNode = None
1584 if self.documentElement is oldChild:
1585 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +00001586
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001587 return oldChild
1588
Fred Drakef7cf40d2000-12-14 18:16:11 +00001589 def _get_documentElement(self):
1590 for node in self.childNodes:
1591 if node.nodeType == Node.ELEMENT_NODE:
1592 return node
1593
1594 def unlink(self):
1595 if self.doctype is not None:
1596 self.doctype.unlink()
1597 self.doctype = None
1598 Node.unlink(self)
1599
Martin v. Löwis787354c2003-01-25 15:28:29 +00001600 def cloneNode(self, deep):
1601 if not deep:
1602 return None
1603 clone = self.implementation.createDocument(None, None, None)
1604 clone.encoding = self.encoding
1605 clone.standalone = self.standalone
1606 clone.version = self.version
1607 for n in self.childNodes:
1608 childclone = _clone_node(n, deep, clone)
1609 assert childclone.ownerDocument.isSameNode(clone)
1610 clone.childNodes.append(childclone)
1611 if childclone.nodeType == Node.DOCUMENT_NODE:
1612 assert clone.documentElement is None
1613 elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
1614 assert clone.doctype is None
1615 clone.doctype = childclone
1616 childclone.parentNode = clone
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001617 self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
Martin v. Löwis787354c2003-01-25 15:28:29 +00001618 self, clone)
1619 return clone
1620
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001621 def createDocumentFragment(self):
1622 d = DocumentFragment()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001623 d.ownerDocument = self
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001624 return d
Fred Drake55c38192000-06-29 19:39:57 +00001625
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001626 def createElement(self, tagName):
1627 e = Element(tagName)
1628 e.ownerDocument = self
1629 return e
Fred Drake55c38192000-06-29 19:39:57 +00001630
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001631 def createTextNode(self, data):
Christian Heimesc9543e42007-11-28 08:28:28 +00001632 if not isinstance(data, str):
Collin Winter70e79802007-08-24 18:57:22 +00001633 raise TypeError("node contents must be a string")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001634 t = Text()
1635 t.data = data
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001636 t.ownerDocument = self
1637 return t
Fred Drake55c38192000-06-29 19:39:57 +00001638
Fred Drake87432f42001-04-04 14:09:46 +00001639 def createCDATASection(self, data):
Christian Heimesc9543e42007-11-28 08:28:28 +00001640 if not isinstance(data, str):
Collin Winter70e79802007-08-24 18:57:22 +00001641 raise TypeError("node contents must be a string")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001642 c = CDATASection()
1643 c.data = data
Fred Drake87432f42001-04-04 14:09:46 +00001644 c.ownerDocument = self
1645 return c
1646
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001647 def createComment(self, data):
1648 c = Comment(data)
1649 c.ownerDocument = self
1650 return c
Fred Drake55c38192000-06-29 19:39:57 +00001651
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001652 def createProcessingInstruction(self, target, data):
1653 p = ProcessingInstruction(target, data)
1654 p.ownerDocument = self
1655 return p
1656
1657 def createAttribute(self, qName):
1658 a = Attr(qName)
1659 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001660 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001661 return a
Fred Drake55c38192000-06-29 19:39:57 +00001662
1663 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001664 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001665 e = Element(qualifiedName, namespaceURI, prefix)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001666 e.ownerDocument = self
1667 return e
Fred Drake55c38192000-06-29 19:39:57 +00001668
1669 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001670 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001671 a = Attr(qualifiedName, namespaceURI, localName, prefix)
1672 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001673 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001674 return a
Fred Drake55c38192000-06-29 19:39:57 +00001675
Martin v. Löwis787354c2003-01-25 15:28:29 +00001676 # A couple of implementation-specific helpers to create node types
1677 # not supported by the W3C DOM specs:
1678
1679 def _create_entity(self, name, publicId, systemId, notationName):
1680 e = Entity(name, publicId, systemId, notationName)
1681 e.ownerDocument = self
1682 return e
1683
1684 def _create_notation(self, name, publicId, systemId):
1685 n = Notation(name, publicId, systemId)
1686 n.ownerDocument = self
1687 return n
1688
1689 def getElementById(self, id):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +00001690 if id in self._id_cache:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001691 return self._id_cache[id]
1692 if not (self._elem_info or self._magic_id_count):
1693 return None
1694
1695 stack = self._id_search_stack
1696 if stack is None:
1697 # we never searched before, or the cache has been cleared
1698 stack = [self.documentElement]
1699 self._id_search_stack = stack
1700 elif not stack:
1701 # Previous search was completed and cache is still valid;
1702 # no matching node.
1703 return None
1704
1705 result = None
1706 while stack:
1707 node = stack.pop()
1708 # add child elements to stack for continued searching
1709 stack.extend([child for child in node.childNodes
1710 if child.nodeType in _nodeTypes_with_children])
1711 # check this node
1712 info = self._get_elem_info(node)
1713 if info:
1714 # We have to process all ID attributes before
1715 # returning in order to get all the attributes set to
1716 # be IDs using Element.setIdAttribute*().
1717 for attr in node.attributes.values():
1718 if attr.namespaceURI:
1719 if info.isIdNS(attr.namespaceURI, attr.localName):
1720 self._id_cache[attr.value] = node
1721 if attr.value == id:
1722 result = node
1723 elif not node._magic_id_nodes:
1724 break
1725 elif info.isId(attr.name):
1726 self._id_cache[attr.value] = node
1727 if attr.value == id:
1728 result = node
1729 elif not node._magic_id_nodes:
1730 break
1731 elif attr._is_id:
1732 self._id_cache[attr.value] = node
1733 if attr.value == id:
1734 result = node
1735 elif node._magic_id_nodes == 1:
1736 break
1737 elif node._magic_id_nodes:
1738 for attr in node.attributes.values():
1739 if attr._is_id:
1740 self._id_cache[attr.value] = node
1741 if attr.value == id:
1742 result = node
1743 if result is not None:
1744 break
1745 return result
1746
Fred Drake1f549022000-09-24 05:21:58 +00001747 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001748 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drakefbe7b4f2001-07-04 06:25:53 +00001749
1750 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001751 return _get_elements_by_tagName_ns_helper(
1752 self, namespaceURI, localName, NodeList())
1753
1754 def isSupported(self, feature, version):
1755 return self.implementation.hasFeature(feature, version)
1756
1757 def importNode(self, node, deep):
1758 if node.nodeType == Node.DOCUMENT_NODE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001759 raise xml.dom.NotSupportedErr("cannot import document nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001760 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001761 raise xml.dom.NotSupportedErr("cannot import document type nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001762 return _clone_node(node, deep, self)
Fred Drake55c38192000-06-29 19:39:57 +00001763
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001764 def writexml(self, writer, indent="", addindent="", newl="",
1765 encoding = None):
1766 if encoding is None:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001767 writer.write('<?xml version="1.0" ?>'+newl)
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001768 else:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001769 writer.write('<?xml version="1.0" encoding="%s"?>%s' % (encoding, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001770 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001771 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +00001772
Martin v. Löwis787354c2003-01-25 15:28:29 +00001773 # DOM Level 3 (WD 9 April 2002)
1774
1775 def renameNode(self, n, namespaceURI, name):
1776 if n.ownerDocument is not self:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001777 raise xml.dom.WrongDocumentErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001778 "cannot rename nodes from other documents;\n"
1779 "expected %s,\nfound %s" % (self, n.ownerDocument))
1780 if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001781 raise xml.dom.NotSupportedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001782 "renameNode() only applies to element and attribute nodes")
1783 if namespaceURI != EMPTY_NAMESPACE:
1784 if ':' in name:
1785 prefix, localName = name.split(':', 1)
1786 if ( prefix == "xmlns"
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001787 and namespaceURI != xml.dom.XMLNS_NAMESPACE):
1788 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001789 "illegal use of 'xmlns' prefix")
1790 else:
1791 if ( name == "xmlns"
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001792 and namespaceURI != xml.dom.XMLNS_NAMESPACE
Martin v. Löwis787354c2003-01-25 15:28:29 +00001793 and n.nodeType == Node.ATTRIBUTE_NODE):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001794 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001795 "illegal use of the 'xmlns' attribute")
1796 prefix = None
1797 localName = name
1798 else:
1799 prefix = None
1800 localName = None
1801 if n.nodeType == Node.ATTRIBUTE_NODE:
1802 element = n.ownerElement
1803 if element is not None:
1804 is_id = n._is_id
1805 element.removeAttributeNode(n)
1806 else:
1807 element = None
1808 # avoid __setattr__
1809 d = n.__dict__
1810 d['prefix'] = prefix
1811 d['localName'] = localName
1812 d['namespaceURI'] = namespaceURI
1813 d['nodeName'] = name
1814 if n.nodeType == Node.ELEMENT_NODE:
1815 d['tagName'] = name
1816 else:
1817 # attribute node
1818 d['name'] = name
1819 if element is not None:
1820 element.setAttributeNode(n)
1821 if is_id:
1822 element.setIdAttributeNode(n)
1823 # It's not clear from a semantic perspective whether we should
1824 # call the user data handlers for the NODE_RENAMED event since
1825 # we're re-using the existing node. The draft spec has been
1826 # interpreted as meaning "no, don't call the handler unless a
1827 # new node is created."
1828 return n
1829
1830defproperty(Document, "documentElement",
1831 doc="Top-level element of this document.")
1832
1833
1834def _clone_node(node, deep, newOwnerDocument):
1835 """
1836 Clone a node and give it the new owner document.
1837 Called by Node.cloneNode and Document.importNode
1838 """
1839 if node.ownerDocument.isSameNode(newOwnerDocument):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001840 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001841 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001842 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001843 if node.nodeType == Node.ELEMENT_NODE:
1844 clone = newOwnerDocument.createElementNS(node.namespaceURI,
1845 node.nodeName)
1846 for attr in node.attributes.values():
1847 clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
1848 a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
1849 a.specified = attr.specified
1850
1851 if deep:
1852 for child in node.childNodes:
1853 c = _clone_node(child, deep, newOwnerDocument)
1854 clone.appendChild(c)
1855
1856 elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
1857 clone = newOwnerDocument.createDocumentFragment()
1858 if deep:
1859 for child in node.childNodes:
1860 c = _clone_node(child, deep, newOwnerDocument)
1861 clone.appendChild(c)
1862
1863 elif node.nodeType == Node.TEXT_NODE:
1864 clone = newOwnerDocument.createTextNode(node.data)
1865 elif node.nodeType == Node.CDATA_SECTION_NODE:
1866 clone = newOwnerDocument.createCDATASection(node.data)
1867 elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
1868 clone = newOwnerDocument.createProcessingInstruction(node.target,
1869 node.data)
1870 elif node.nodeType == Node.COMMENT_NODE:
1871 clone = newOwnerDocument.createComment(node.data)
1872 elif node.nodeType == Node.ATTRIBUTE_NODE:
1873 clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
1874 node.nodeName)
1875 clone.specified = True
1876 clone.value = node.value
1877 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
1878 assert node.ownerDocument is not newOwnerDocument
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001879 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001880 clone = newOwnerDocument.implementation.createDocumentType(
1881 node.name, node.publicId, node.systemId)
1882 clone.ownerDocument = newOwnerDocument
1883 if deep:
1884 clone.entities._seq = []
1885 clone.notations._seq = []
1886 for n in node.notations._seq:
1887 notation = Notation(n.nodeName, n.publicId, n.systemId)
1888 notation.ownerDocument = newOwnerDocument
1889 clone.notations._seq.append(notation)
1890 if hasattr(n, '_call_user_data_handler'):
1891 n._call_user_data_handler(operation, n, notation)
1892 for e in node.entities._seq:
1893 entity = Entity(e.nodeName, e.publicId, e.systemId,
1894 e.notationName)
1895 entity.actualEncoding = e.actualEncoding
1896 entity.encoding = e.encoding
1897 entity.version = e.version
1898 entity.ownerDocument = newOwnerDocument
1899 clone.entities._seq.append(entity)
1900 if hasattr(e, '_call_user_data_handler'):
1901 e._call_user_data_handler(operation, n, entity)
1902 else:
1903 # Note the cloning of Document and DocumentType nodes is
1904 # implemenetation specific. minidom handles those cases
1905 # directly in the cloneNode() methods.
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001906 raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001907
1908 # Check for _call_user_data_handler() since this could conceivably
1909 # used with other DOM implementations (one of the FourThought
1910 # DOMs, perhaps?).
1911 if hasattr(node, '_call_user_data_handler'):
1912 node._call_user_data_handler(operation, node, clone)
1913 return clone
1914
1915
1916def _nssplit(qualifiedName):
1917 fields = qualifiedName.split(':', 1)
1918 if len(fields) == 2:
1919 return fields
1920 else:
1921 return (None, fields[0])
1922
1923
Martin v. Löwis787354c2003-01-25 15:28:29 +00001924def _do_pulldom_parse(func, args, kwargs):
Raymond Hettingerff41c482003-04-06 09:01:11 +00001925 events = func(*args, **kwargs)
Fred Drake1f549022000-09-24 05:21:58 +00001926 toktype, rootNode = events.getEvent()
1927 events.expandNode(rootNode)
Martin v. Löwisb417be22001-02-06 01:16:06 +00001928 events.clear()
Fred Drake55c38192000-06-29 19:39:57 +00001929 return rootNode
1930
Martin v. Löwis787354c2003-01-25 15:28:29 +00001931def parse(file, parser=None, bufsize=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001932 """Parse a file into a DOM by filename or file object."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001933 if parser is None and not bufsize:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001934 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001935 return expatbuilder.parse(file)
1936 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001937 from xml.dom import pulldom
Raymond Hettingerff41c482003-04-06 09:01:11 +00001938 return _do_pulldom_parse(pulldom.parse, (file,),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001939 {'parser': parser, 'bufsize': bufsize})
Fred Drake55c38192000-06-29 19:39:57 +00001940
Martin v. Löwis787354c2003-01-25 15:28:29 +00001941def parseString(string, parser=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001942 """Parse a file into a DOM from a string."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001943 if parser is None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001944 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001945 return expatbuilder.parseString(string)
1946 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001947 from xml.dom import pulldom
Martin v. Löwis787354c2003-01-25 15:28:29 +00001948 return _do_pulldom_parse(pulldom.parseString, (string,),
1949 {'parser': parser})
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001950
Martin v. Löwis787354c2003-01-25 15:28:29 +00001951def getDOMImplementation(features=None):
1952 if features:
Christian Heimesc9543e42007-11-28 08:28:28 +00001953 if isinstance(features, str):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001954 features = domreg._parse_feature_string(features)
1955 for f, v in features:
1956 if not Document.implementation.hasFeature(f, v):
1957 return None
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001958 return Document.implementation