blob: b6f0a862421356333a975595cdbe26a116d5f438 [file] [log] [blame]
Fred Drake1f549022000-09-24 05:21:58 +00001"""\
Fred Drakef7cf40d2000-12-14 18:16:11 +00002minidom.py -- a lightweight DOM implementation.
Fred Drake55c38192000-06-29 19:39:57 +00003
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00004parse("foo.xml")
Paul Prescod623511b2000-07-21 22:05:49 +00005
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00006parseString("<foo><bar/></foo>")
Paul Prescod623511b2000-07-21 22:05:49 +00007
Fred Drake55c38192000-06-29 19:39:57 +00008Todo:
9=====
10 * convenience methods for getting elements and text.
11 * more testing
12 * bring some of the writer and linearizer code into conformance with this
13 interface
14 * SAX 2 namespaces
15"""
16
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000017import io
Thomas Wouters0e3f5912006-08-11 14:57:12 +000018import xml.dom
Fred Drake55c38192000-06-29 19:39:57 +000019
Thomas Wouters0e3f5912006-08-11 14:57:12 +000020from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
21from xml.dom.minicompat import *
22from xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS
Fred Drake3ac6a092001-09-28 04:33:06 +000023
Martin v. Löwis787354c2003-01-25 15:28:29 +000024# This is used by the ID-cache invalidation checks; the list isn't
25# actually complete, since the nodes being checked will never be the
26# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE. (The node being checked is
27# the node being added or removed, not the node being modified.)
28#
Thomas Wouters0e3f5912006-08-11 14:57:12 +000029_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE,
30 xml.dom.Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis95700f72002-03-15 13:51:59 +000031
Fred Drake3ac6a092001-09-28 04:33:06 +000032
Thomas Wouters0e3f5912006-08-11 14:57:12 +000033class Node(xml.dom.Node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000034 namespaceURI = None # this is non-null only for elements and attributes
Fred Drake575712e2001-09-28 20:25:45 +000035 parentNode = None
36 ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +000037 nextSibling = None
38 previousSibling = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +000039
Martin v. Löwis787354c2003-01-25 15:28:29 +000040 prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
Fred Drake55c38192000-06-29 19:39:57 +000041
Jack Diederich4dafcc42006-11-28 19:15:13 +000042 def __bool__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +000043 return True
Fred Drake55c38192000-06-29 19:39:57 +000044
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000045 def toxml(self, encoding = None):
46 return self.toprettyxml("", "", encoding)
Fred Drake55c38192000-06-29 19:39:57 +000047
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000048 def toprettyxml(self, indent="\t", newl="\n", encoding=None):
Martin v. Löwiscb67ea12001-03-31 16:30:40 +000049 # indent = the indentation string to prepend, per level
50 # newl = the newline string to append
Guido van Rossum55b15c92007-08-07 23:03:33 +000051 use_encoding = "utf-8" if encoding is None else encoding
52 writer = io.StringIO(encoding=use_encoding)
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000053 if self.nodeType == Node.DOCUMENT_NODE:
54 # Can pass encoding only to document, to put it into XML header
55 self.writexml(writer, "", indent, newl, encoding)
56 else:
57 self.writexml(writer, "", indent, newl)
Guido van Rossum3e1f85e2007-07-27 18:03:11 +000058 if encoding is None:
59 return writer.getvalue()
60 else:
61 return writer.buffer.getvalue()
Martin v. Löwis46fa39a2001-02-06 00:14:08 +000062
Fred Drake1f549022000-09-24 05:21:58 +000063 def hasChildNodes(self):
64 if self.childNodes:
Martin v. Löwis787354c2003-01-25 15:28:29 +000065 return True
Fred Drake1f549022000-09-24 05:21:58 +000066 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +000067 return False
68
69 def _get_childNodes(self):
70 return self.childNodes
Fred Drake55c38192000-06-29 19:39:57 +000071
Fred Drake1f549022000-09-24 05:21:58 +000072 def _get_firstChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000073 if self.childNodes:
74 return self.childNodes[0]
Paul Prescod73678da2000-07-01 04:58:47 +000075
Fred Drake1f549022000-09-24 05:21:58 +000076 def _get_lastChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000077 if self.childNodes:
78 return self.childNodes[-1]
Paul Prescod73678da2000-07-01 04:58:47 +000079
Fred Drake1f549022000-09-24 05:21:58 +000080 def insertBefore(self, newChild, refChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000081 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +000082 for c in tuple(newChild.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +000083 self.insertBefore(c, refChild)
84 ### The DOM does not clearly specify what to return in this case
85 return newChild
Martin v. Löwis787354c2003-01-25 15:28:29 +000086 if newChild.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000087 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +000088 "%s cannot be child of %s" % (repr(newChild), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +000089 if newChild.parentNode is not None:
90 newChild.parentNode.removeChild(newChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +000091 if refChild is None:
92 self.appendChild(newChild)
93 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +000094 try:
95 index = self.childNodes.index(refChild)
96 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000097 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +000098 if newChild.nodeType in _nodeTypes_with_children:
99 _clear_id_cache(self)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000100 self.childNodes.insert(index, newChild)
101 newChild.nextSibling = refChild
102 refChild.previousSibling = newChild
103 if index:
104 node = self.childNodes[index-1]
105 node.nextSibling = newChild
106 newChild.previousSibling = node
107 else:
108 newChild.previousSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000109 newChild.parentNode = self
Fred Drake4ccf4a12000-11-21 22:02:22 +0000110 return newChild
Fred Drake55c38192000-06-29 19:39:57 +0000111
Fred Drake1f549022000-09-24 05:21:58 +0000112 def appendChild(self, node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000113 if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +0000114 for c in tuple(node.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000115 self.appendChild(c)
116 ### The DOM does not clearly specify what to return in this case
117 return node
Martin v. Löwis787354c2003-01-25 15:28:29 +0000118 if node.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000119 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000120 "%s cannot be child of %s" % (repr(node), repr(self)))
121 elif node.nodeType in _nodeTypes_with_children:
122 _clear_id_cache(self)
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000123 if node.parentNode is not None:
124 node.parentNode.removeChild(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000125 _append_child(self, node)
Fred Drake13a30692000-10-09 20:04:16 +0000126 node.nextSibling = None
Paul Prescod73678da2000-07-01 04:58:47 +0000127 return node
128
Fred Drake1f549022000-09-24 05:21:58 +0000129 def replaceChild(self, newChild, oldChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000130 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
131 refChild = oldChild.nextSibling
132 self.removeChild(oldChild)
133 return self.insertBefore(newChild, refChild)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000134 if newChild.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000135 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000136 "%s cannot be child of %s" % (repr(newChild), repr(self)))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000137 if newChild is oldChild:
138 return
Andrew M. Kuchling841d25e2005-11-22 19:03:16 +0000139 if newChild.parentNode is not None:
140 newChild.parentNode.removeChild(newChild)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000141 try:
142 index = self.childNodes.index(oldChild)
143 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000144 raise xml.dom.NotFoundErr()
Fred Drake4ccf4a12000-11-21 22:02:22 +0000145 self.childNodes[index] = newChild
Martin v. Löwis787354c2003-01-25 15:28:29 +0000146 newChild.parentNode = self
147 oldChild.parentNode = None
148 if (newChild.nodeType in _nodeTypes_with_children
149 or oldChild.nodeType in _nodeTypes_with_children):
150 _clear_id_cache(self)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000151 newChild.nextSibling = oldChild.nextSibling
152 newChild.previousSibling = oldChild.previousSibling
Martin v. Löwis156c3372000-12-28 18:40:56 +0000153 oldChild.nextSibling = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000154 oldChild.previousSibling = None
Martin v. Löwis156c3372000-12-28 18:40:56 +0000155 if newChild.previousSibling:
156 newChild.previousSibling.nextSibling = newChild
157 if newChild.nextSibling:
158 newChild.nextSibling.previousSibling = newChild
Fred Drake4ccf4a12000-11-21 22:02:22 +0000159 return oldChild
Paul Prescod73678da2000-07-01 04:58:47 +0000160
Fred Drake1f549022000-09-24 05:21:58 +0000161 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000162 try:
163 self.childNodes.remove(oldChild)
164 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000165 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000166 if oldChild.nextSibling is not None:
167 oldChild.nextSibling.previousSibling = oldChild.previousSibling
168 if oldChild.previousSibling is not None:
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000169 oldChild.previousSibling.nextSibling = oldChild.nextSibling
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000170 oldChild.nextSibling = oldChild.previousSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000171 if oldChild.nodeType in _nodeTypes_with_children:
172 _clear_id_cache(self)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000173
Martin v. Löwis787354c2003-01-25 15:28:29 +0000174 oldChild.parentNode = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000175 return oldChild
176
177 def normalize(self):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000178 L = []
179 for child in self.childNodes:
180 if child.nodeType == Node.TEXT_NODE:
181 data = child.data
182 if data and L and L[-1].nodeType == child.nodeType:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000183 # collapse text node
184 node = L[-1]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000185 node.data = node.data + child.data
Fred Drake4ccf4a12000-11-21 22:02:22 +0000186 node.nextSibling = child.nextSibling
187 child.unlink()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000188 elif data:
189 if L:
190 L[-1].nextSibling = child
191 child.previousSibling = L[-1]
192 else:
193 child.previousSibling = None
194 L.append(child)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000195 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000196 # empty text node; discard
197 child.unlink()
198 else:
199 if L:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000200 L[-1].nextSibling = child
201 child.previousSibling = L[-1]
Fred Drakef7cf40d2000-12-14 18:16:11 +0000202 else:
203 child.previousSibling = None
204 L.append(child)
205 if child.nodeType == Node.ELEMENT_NODE:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000206 child.normalize()
Christian Heimes05e8be12008-02-23 18:30:17 +0000207 if L:
208 L[-1].nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000209 self.childNodes[:] = L
Paul Prescod73678da2000-07-01 04:58:47 +0000210
Fred Drake1f549022000-09-24 05:21:58 +0000211 def cloneNode(self, deep):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000212 return _clone_node(self, deep, self.ownerDocument or self)
Fred Drake55c38192000-06-29 19:39:57 +0000213
Martin v. Löwis787354c2003-01-25 15:28:29 +0000214 def isSupported(self, feature, version):
215 return self.ownerDocument.implementation.hasFeature(feature, version)
216
217 def _get_localName(self):
218 # Overridden in Element and Attr where localName can be Non-Null
219 return None
220
221 # Node interfaces from Level 3 (WD 9 April 2002)
Fred Drake25239772001-02-02 19:40:19 +0000222
223 def isSameNode(self, other):
224 return self is other
225
Martin v. Löwis787354c2003-01-25 15:28:29 +0000226 def getInterface(self, feature):
227 if self.isSupported(feature, None):
228 return self
229 else:
230 return None
231
232 # The "user data" functions use a dictionary that is only present
233 # if some user data has been set, so be careful not to assume it
234 # exists.
235
236 def getUserData(self, key):
237 try:
238 return self._user_data[key][0]
239 except (AttributeError, KeyError):
240 return None
241
242 def setUserData(self, key, data, handler):
243 old = None
244 try:
245 d = self._user_data
246 except AttributeError:
247 d = {}
248 self._user_data = d
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000249 if key in d:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000250 old = d[key][0]
251 if data is None:
252 # ignore handlers passed for None
253 handler = None
254 if old is not None:
255 del d[key]
256 else:
257 d[key] = (data, handler)
258 return old
259
260 def _call_user_data_handler(self, operation, src, dst):
261 if hasattr(self, "_user_data"):
Brett Cannon861fd6f2007-02-21 22:05:37 +0000262 for key, (data, handler) in list(self._user_data.items()):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000263 if handler is not None:
264 handler.handle(operation, key, data, src, dst)
265
Fred Drake25239772001-02-02 19:40:19 +0000266 # minidom-specific API:
267
Fred Drake1f549022000-09-24 05:21:58 +0000268 def unlink(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000269 self.parentNode = self.ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000270 if self.childNodes:
271 for child in self.childNodes:
272 child.unlink()
273 self.childNodes = NodeList()
Paul Prescod4221ff02000-10-13 20:11:42 +0000274 self.previousSibling = None
275 self.nextSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000276
277defproperty(Node, "firstChild", doc="First child node, or None.")
278defproperty(Node, "lastChild", doc="Last child node, or None.")
279defproperty(Node, "localName", doc="Namespace-local name of this node.")
280
281
282def _append_child(self, node):
283 # fast path with less checks; usable by DOM builders if careful
284 childNodes = self.childNodes
285 if childNodes:
286 last = childNodes[-1]
287 node.__dict__["previousSibling"] = last
288 last.__dict__["nextSibling"] = node
289 childNodes.append(node)
290 node.__dict__["parentNode"] = self
291
292def _in_document(node):
293 # return True iff node is part of a document tree
294 while node is not None:
295 if node.nodeType == Node.DOCUMENT_NODE:
296 return True
297 node = node.parentNode
298 return False
Fred Drake55c38192000-06-29 19:39:57 +0000299
Fred Drake1f549022000-09-24 05:21:58 +0000300def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000301 "Writes datachars to writer."
Martin v. Löwis787354c2003-01-25 15:28:29 +0000302 data = data.replace("&", "&amp;").replace("<", "&lt;")
303 data = data.replace("\"", "&quot;").replace(">", "&gt;")
Fred Drake55c38192000-06-29 19:39:57 +0000304 writer.write(data)
305
Martin v. Löwis787354c2003-01-25 15:28:29 +0000306def _get_elements_by_tagName_helper(parent, name, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000307 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000308 if node.nodeType == Node.ELEMENT_NODE and \
309 (name == "*" or node.tagName == name):
310 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000311 _get_elements_by_tagName_helper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000312 return rc
313
Martin v. Löwis787354c2003-01-25 15:28:29 +0000314def _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000315 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000316 if node.nodeType == Node.ELEMENT_NODE:
Martin v. Löwised525fb2001-06-03 14:06:42 +0000317 if ((localName == "*" or node.localName == localName) and
Fred Drake1f549022000-09-24 05:21:58 +0000318 (nsURI == "*" or node.namespaceURI == nsURI)):
319 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000320 _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000321 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000322
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000323class DocumentFragment(Node):
324 nodeType = Node.DOCUMENT_FRAGMENT_NODE
325 nodeName = "#document-fragment"
326 nodeValue = None
327 attributes = None
328 parentNode = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000329 _child_node_types = (Node.ELEMENT_NODE,
330 Node.TEXT_NODE,
331 Node.CDATA_SECTION_NODE,
332 Node.ENTITY_REFERENCE_NODE,
333 Node.PROCESSING_INSTRUCTION_NODE,
334 Node.COMMENT_NODE,
335 Node.NOTATION_NODE)
336
337 def __init__(self):
338 self.childNodes = NodeList()
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000339
340
Fred Drake55c38192000-06-29 19:39:57 +0000341class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000342 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000343 attributes = None
344 ownerElement = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000345 specified = False
346 _is_id = False
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000347
Martin v. Löwis787354c2003-01-25 15:28:29 +0000348 _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
349
350 def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
351 prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000352 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000353 d = self.__dict__
Fred Drake4ccf4a12000-11-21 22:02:22 +0000354 d["nodeName"] = d["name"] = qName
355 d["namespaceURI"] = namespaceURI
356 d["prefix"] = prefix
Martin v. Löwis787354c2003-01-25 15:28:29 +0000357 d['childNodes'] = NodeList()
358
359 # Add the single child node that represents the value of the attr
360 self.childNodes.append(Text())
361
Paul Prescod73678da2000-07-01 04:58:47 +0000362 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000363
Martin v. Löwis787354c2003-01-25 15:28:29 +0000364 def _get_localName(self):
Alex Martelli0ee43512006-08-21 19:53:20 +0000365 if 'localName' in self.__dict__:
Guido van Rossum3e1f85e2007-07-27 18:03:11 +0000366 return self.__dict__['localName']
Martin v. Löwis787354c2003-01-25 15:28:29 +0000367 return self.nodeName.split(":", 1)[-1]
368
369 def _get_name(self):
370 return self.name
371
372 def _get_specified(self):
373 return self.specified
374
Fred Drake1f549022000-09-24 05:21:58 +0000375 def __setattr__(self, name, value):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000376 d = self.__dict__
Fred Drake1f549022000-09-24 05:21:58 +0000377 if name in ("value", "nodeValue"):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000378 d["value"] = d["nodeValue"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000379 d2 = self.childNodes[0].__dict__
380 d2["data"] = d2["nodeValue"] = value
381 if self.ownerElement is not None:
382 _clear_id_cache(self.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000383 elif name in ("name", "nodeName"):
384 d["name"] = d["nodeName"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000385 if self.ownerElement is not None:
386 _clear_id_cache(self.ownerElement)
Fred Drake55c38192000-06-29 19:39:57 +0000387 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000388 d[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000389
Martin v. Löwis995359c2003-01-26 08:59:32 +0000390 def _set_prefix(self, prefix):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000391 nsuri = self.namespaceURI
Martin v. Löwis995359c2003-01-26 08:59:32 +0000392 if prefix == "xmlns":
393 if nsuri and nsuri != XMLNS_NAMESPACE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000394 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000395 "illegal use of 'xmlns' prefix for the wrong namespace")
396 d = self.__dict__
397 d['prefix'] = prefix
398 if prefix is None:
399 newName = self.localName
400 else:
Martin v. Löwis995359c2003-01-26 08:59:32 +0000401 newName = "%s:%s" % (prefix, self.localName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000402 if self.ownerElement:
403 _clear_id_cache(self.ownerElement)
404 d['nodeName'] = d['name'] = newName
405
406 def _set_value(self, value):
407 d = self.__dict__
408 d['value'] = d['nodeValue'] = value
409 if self.ownerElement:
410 _clear_id_cache(self.ownerElement)
411 self.childNodes[0].data = value
412
413 def unlink(self):
414 # This implementation does not call the base implementation
415 # since most of that is not needed, and the expense of the
416 # method call is not warranted. We duplicate the removal of
417 # children, but that's all we needed from the base class.
418 elem = self.ownerElement
419 if elem is not None:
420 del elem._attrs[self.nodeName]
421 del elem._attrsNS[(self.namespaceURI, self.localName)]
422 if self._is_id:
423 self._is_id = False
424 elem._magic_id_nodes -= 1
425 self.ownerDocument._magic_id_count -= 1
426 for child in self.childNodes:
427 child.unlink()
428 del self.childNodes[:]
429
430 def _get_isId(self):
431 if self._is_id:
432 return True
433 doc = self.ownerDocument
434 elem = self.ownerElement
435 if doc is None or elem is None:
436 return False
437
438 info = doc._get_elem_info(elem)
439 if info is None:
440 return False
441 if self.namespaceURI:
442 return info.isIdNS(self.namespaceURI, self.localName)
443 else:
444 return info.isId(self.nodeName)
445
446 def _get_schemaType(self):
447 doc = self.ownerDocument
448 elem = self.ownerElement
449 if doc is None or elem is None:
450 return _no_type
451
452 info = doc._get_elem_info(elem)
453 if info is None:
454 return _no_type
455 if self.namespaceURI:
456 return info.getAttributeTypeNS(self.namespaceURI, self.localName)
457 else:
458 return info.getAttributeType(self.nodeName)
459
460defproperty(Attr, "isId", doc="True if this attribute is an ID.")
461defproperty(Attr, "localName", doc="Namespace-local name of this attribute.")
462defproperty(Attr, "schemaType", doc="Schema type for this attribute.")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000463
Fred Drakef7cf40d2000-12-14 18:16:11 +0000464
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000465class NamedNodeMap(object):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000466 """The attribute list is a transient interface to the underlying
467 dictionaries. Mutations here will change the underlying element's
Fred Drakef7cf40d2000-12-14 18:16:11 +0000468 dictionary.
469
470 Ordering is imposed artificially and does not reflect the order of
471 attributes as found in an input document.
472 """
Fred Drake4ccf4a12000-11-21 22:02:22 +0000473
Martin v. Löwis787354c2003-01-25 15:28:29 +0000474 __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
475
Fred Drake2998a552001-12-06 18:27:48 +0000476 def __init__(self, attrs, attrsNS, ownerElement):
Fred Drake1f549022000-09-24 05:21:58 +0000477 self._attrs = attrs
478 self._attrsNS = attrsNS
Fred Drake2998a552001-12-06 18:27:48 +0000479 self._ownerElement = ownerElement
Fred Drakef7cf40d2000-12-14 18:16:11 +0000480
Martin v. Löwis787354c2003-01-25 15:28:29 +0000481 def _get_length(self):
482 return len(self._attrs)
Fred Drake55c38192000-06-29 19:39:57 +0000483
Fred Drake1f549022000-09-24 05:21:58 +0000484 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000485 try:
Brett Cannon861fd6f2007-02-21 22:05:37 +0000486 return self[list(self._attrs.keys())[index]]
Fred Drake55c38192000-06-29 19:39:57 +0000487 except IndexError:
488 return None
Fred Drake55c38192000-06-29 19:39:57 +0000489
Fred Drake1f549022000-09-24 05:21:58 +0000490 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000491 L = []
492 for node in self._attrs.values():
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000493 L.append((node.nodeName, node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000494 return L
Fred Drake1f549022000-09-24 05:21:58 +0000495
496 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000497 L = []
498 for node in self._attrs.values():
Fred Drake49a5d032001-11-30 22:21:58 +0000499 L.append(((node.namespaceURI, node.localName), node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000500 return L
Fred Drake16f63292000-10-23 18:09:50 +0000501
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000502 def __contains__(self, key):
Christian Heimesc9543e42007-11-28 08:28:28 +0000503 if isinstance(key, str):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000504 return key in self._attrs
Martin v. Löwis787354c2003-01-25 15:28:29 +0000505 else:
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000506 return key in self._attrsNS
Martin v. Löwis787354c2003-01-25 15:28:29 +0000507
Fred Drake1f549022000-09-24 05:21:58 +0000508 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000509 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000510
Fred Drake1f549022000-09-24 05:21:58 +0000511 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000512 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000513
Fred Drake1f549022000-09-24 05:21:58 +0000514 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000515 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000516
Martin v. Löwis787354c2003-01-25 15:28:29 +0000517 def get(self, name, value=None):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000518 return self._attrs.get(name, value)
519
Martin v. Löwis787354c2003-01-25 15:28:29 +0000520 __len__ = _get_length
Fred Drake55c38192000-06-29 19:39:57 +0000521
Fred Drake1f549022000-09-24 05:21:58 +0000522 def __cmp__(self, other):
523 if self._attrs is getattr(other, "_attrs", None):
Fred Drake55c38192000-06-29 19:39:57 +0000524 return 0
Fred Drake16f63292000-10-23 18:09:50 +0000525 else:
Fred Drake1f549022000-09-24 05:21:58 +0000526 return cmp(id(self), id(other))
Fred Drake55c38192000-06-29 19:39:57 +0000527
Fred Drake1f549022000-09-24 05:21:58 +0000528 def __getitem__(self, attname_or_tuple):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000529 if isinstance(attname_or_tuple, tuple):
Paul Prescod73678da2000-07-01 04:58:47 +0000530 return self._attrsNS[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000531 else:
Paul Prescod73678da2000-07-01 04:58:47 +0000532 return self._attrs[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000533
Paul Prescod1e688272000-07-01 19:21:47 +0000534 # same as set
Fred Drake1f549022000-09-24 05:21:58 +0000535 def __setitem__(self, attname, value):
Christian Heimesc9543e42007-11-28 08:28:28 +0000536 if isinstance(value, str):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000537 try:
538 node = self._attrs[attname]
539 except KeyError:
540 node = Attr(attname)
541 node.ownerDocument = self._ownerElement.ownerDocument
Martin v. Löwis995359c2003-01-26 08:59:32 +0000542 self.setNamedItem(node)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000543 node.value = value
Paul Prescod1e688272000-07-01 19:21:47 +0000544 else:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000545 if not isinstance(value, Attr):
Collin Winter70e79802007-08-24 18:57:22 +0000546 raise TypeError("value must be a string or Attr object")
Fred Drake1f549022000-09-24 05:21:58 +0000547 node = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000548 self.setNamedItem(node)
549
550 def getNamedItem(self, name):
551 try:
552 return self._attrs[name]
553 except KeyError:
554 return None
555
556 def getNamedItemNS(self, namespaceURI, localName):
557 try:
558 return self._attrsNS[(namespaceURI, localName)]
559 except KeyError:
560 return None
561
562 def removeNamedItem(self, name):
563 n = self.getNamedItem(name)
564 if n is not None:
565 _clear_id_cache(self._ownerElement)
566 del self._attrs[n.nodeName]
567 del self._attrsNS[(n.namespaceURI, n.localName)]
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000568 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000569 n.__dict__['ownerElement'] = None
570 return n
571 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000572 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000573
574 def removeNamedItemNS(self, namespaceURI, localName):
575 n = self.getNamedItemNS(namespaceURI, localName)
576 if n is not None:
577 _clear_id_cache(self._ownerElement)
578 del self._attrsNS[(n.namespaceURI, n.localName)]
579 del self._attrs[n.nodeName]
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000580 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000581 n.__dict__['ownerElement'] = None
582 return n
583 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000584 raise xml.dom.NotFoundErr()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000585
586 def setNamedItem(self, node):
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000587 if not isinstance(node, Attr):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000588 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000589 "%s cannot be child of %s" % (repr(node), repr(self)))
Fred Drakef7cf40d2000-12-14 18:16:11 +0000590 old = self._attrs.get(node.name)
Paul Prescod1e688272000-07-01 19:21:47 +0000591 if old:
592 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000593 self._attrs[node.name] = node
594 self._attrsNS[(node.namespaceURI, node.localName)] = node
Fred Drake2998a552001-12-06 18:27:48 +0000595 node.ownerElement = self._ownerElement
Martin v. Löwis787354c2003-01-25 15:28:29 +0000596 _clear_id_cache(node.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000597 return old
598
599 def setNamedItemNS(self, node):
600 return self.setNamedItem(node)
Paul Prescod73678da2000-07-01 04:58:47 +0000601
Fred Drake1f549022000-09-24 05:21:58 +0000602 def __delitem__(self, attname_or_tuple):
603 node = self[attname_or_tuple]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000604 _clear_id_cache(node.ownerElement)
Paul Prescod73678da2000-07-01 04:58:47 +0000605 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000606
607 def __getstate__(self):
608 return self._attrs, self._attrsNS, self._ownerElement
609
610 def __setstate__(self, state):
611 self._attrs, self._attrsNS, self._ownerElement = state
612
613defproperty(NamedNodeMap, "length",
614 doc="Number of nodes in the NamedNodeMap.")
Fred Drakef7cf40d2000-12-14 18:16:11 +0000615
616AttributeList = NamedNodeMap
617
Fred Drake1f549022000-09-24 05:21:58 +0000618
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000619class TypeInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000620 __slots__ = 'namespace', 'name'
621
622 def __init__(self, namespace, name):
623 self.namespace = namespace
624 self.name = name
625
626 def __repr__(self):
627 if self.namespace:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000628 return "<TypeInfo %r (from %r)>" % (self.name, self.namespace)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000629 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000630 return "<TypeInfo %r>" % self.name
Martin v. Löwis787354c2003-01-25 15:28:29 +0000631
632 def _get_name(self):
633 return self.name
634
635 def _get_namespace(self):
636 return self.namespace
637
638_no_type = TypeInfo(None, None)
639
Martin v. Löwisa2fda0d2000-10-07 12:10:28 +0000640class Element(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000641 nodeType = Node.ELEMENT_NODE
Martin v. Löwis787354c2003-01-25 15:28:29 +0000642 nodeValue = None
643 schemaType = _no_type
644
645 _magic_id_nodes = 0
646
647 _child_node_types = (Node.ELEMENT_NODE,
648 Node.PROCESSING_INSTRUCTION_NODE,
649 Node.COMMENT_NODE,
650 Node.TEXT_NODE,
651 Node.CDATA_SECTION_NODE,
652 Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000653
Fred Drake49a5d032001-11-30 22:21:58 +0000654 def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
Fred Drake1f549022000-09-24 05:21:58 +0000655 localName=None):
Fred Drake55c38192000-06-29 19:39:57 +0000656 self.tagName = self.nodeName = tagName
Fred Drake1f549022000-09-24 05:21:58 +0000657 self.prefix = prefix
658 self.namespaceURI = namespaceURI
Martin v. Löwis787354c2003-01-25 15:28:29 +0000659 self.childNodes = NodeList()
Fred Drake55c38192000-06-29 19:39:57 +0000660
Fred Drake4ccf4a12000-11-21 22:02:22 +0000661 self._attrs = {} # attributes are double-indexed:
662 self._attrsNS = {} # tagName -> Attribute
663 # URI,localName -> Attribute
664 # in the future: consider lazy generation
665 # of attribute objects this is too tricky
666 # for now because of headaches with
667 # namespaces.
668
Martin v. Löwis787354c2003-01-25 15:28:29 +0000669 def _get_localName(self):
Alex Martelli0ee43512006-08-21 19:53:20 +0000670 if 'localName' in self.__dict__:
Guido van Rossum3e1f85e2007-07-27 18:03:11 +0000671 return self.__dict__['localName']
Martin v. Löwis787354c2003-01-25 15:28:29 +0000672 return self.tagName.split(":", 1)[-1]
673
674 def _get_tagName(self):
675 return self.tagName
Fred Drake4ccf4a12000-11-21 22:02:22 +0000676
677 def unlink(self):
Brett Cannon861fd6f2007-02-21 22:05:37 +0000678 for attr in list(self._attrs.values()):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000679 attr.unlink()
680 self._attrs = None
681 self._attrsNS = None
682 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000683
Fred Drake1f549022000-09-24 05:21:58 +0000684 def getAttribute(self, attname):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000685 try:
686 return self._attrs[attname].value
687 except KeyError:
688 return ""
Fred Drake55c38192000-06-29 19:39:57 +0000689
Fred Drake1f549022000-09-24 05:21:58 +0000690 def getAttributeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000691 try:
692 return self._attrsNS[(namespaceURI, localName)].value
693 except KeyError:
694 return ""
Fred Drake1f549022000-09-24 05:21:58 +0000695
696 def setAttribute(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000697 attr = self.getAttributeNode(attname)
698 if attr is None:
699 attr = Attr(attname)
700 # for performance
701 d = attr.__dict__
702 d["value"] = d["nodeValue"] = value
703 d["ownerDocument"] = self.ownerDocument
704 self.setAttributeNode(attr)
705 elif value != attr.value:
706 d = attr.__dict__
707 d["value"] = d["nodeValue"] = value
708 if attr.isId:
709 _clear_id_cache(self)
Fred Drake55c38192000-06-29 19:39:57 +0000710
Fred Drake1f549022000-09-24 05:21:58 +0000711 def setAttributeNS(self, namespaceURI, qualifiedName, value):
712 prefix, localname = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000713 attr = self.getAttributeNodeNS(namespaceURI, localname)
714 if attr is None:
715 # for performance
716 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
717 d = attr.__dict__
718 d["prefix"] = prefix
719 d["nodeName"] = qualifiedName
720 d["value"] = d["nodeValue"] = value
721 d["ownerDocument"] = self.ownerDocument
722 self.setAttributeNode(attr)
723 else:
724 d = attr.__dict__
725 if value != attr.value:
726 d["value"] = d["nodeValue"] = value
727 if attr.isId:
728 _clear_id_cache(self)
729 if attr.prefix != prefix:
730 d["prefix"] = prefix
731 d["nodeName"] = qualifiedName
Fred Drake55c38192000-06-29 19:39:57 +0000732
Fred Drake1f549022000-09-24 05:21:58 +0000733 def getAttributeNode(self, attrname):
734 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000735
Fred Drake1f549022000-09-24 05:21:58 +0000736 def getAttributeNodeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000737 return self._attrsNS.get((namespaceURI, localName))
Paul Prescod73678da2000-07-01 04:58:47 +0000738
Fred Drake1f549022000-09-24 05:21:58 +0000739 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000740 if attr.ownerElement not in (None, self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000741 raise xml.dom.InuseAttributeErr("attribute node already owned")
Martin v. Löwis787354c2003-01-25 15:28:29 +0000742 old1 = self._attrs.get(attr.name, None)
743 if old1 is not None:
744 self.removeAttributeNode(old1)
745 old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
746 if old2 is not None and old2 is not old1:
747 self.removeAttributeNode(old2)
748 _set_attribute_node(self, attr)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000749
Martin v. Löwis787354c2003-01-25 15:28:29 +0000750 if old1 is not attr:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000751 # It might have already been part of this node, in which case
752 # it doesn't represent a change, and should not be returned.
Martin v. Löwis787354c2003-01-25 15:28:29 +0000753 return old1
754 if old2 is not attr:
755 return old2
Fred Drake55c38192000-06-29 19:39:57 +0000756
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000757 setAttributeNodeNS = setAttributeNode
758
Fred Drake1f549022000-09-24 05:21:58 +0000759 def removeAttribute(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000760 try:
761 attr = self._attrs[name]
762 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000763 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000764 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000765
Fred Drake1f549022000-09-24 05:21:58 +0000766 def removeAttributeNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000767 try:
768 attr = self._attrsNS[(namespaceURI, localName)]
769 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000770 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000771 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000772
Fred Drake1f549022000-09-24 05:21:58 +0000773 def removeAttributeNode(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000774 if node is None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000775 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000776 try:
777 self._attrs[node.name]
778 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000779 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000780 _clear_id_cache(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000781 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000782 # Restore this since the node is still useful and otherwise
783 # unlinked
784 node.ownerDocument = self.ownerDocument
Fred Drake16f63292000-10-23 18:09:50 +0000785
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000786 removeAttributeNodeNS = removeAttributeNode
787
Martin v. Löwis156c3372000-12-28 18:40:56 +0000788 def hasAttribute(self, name):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000789 return name in self._attrs
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000790
Martin v. Löwis156c3372000-12-28 18:40:56 +0000791 def hasAttributeNS(self, namespaceURI, localName):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000792 return (namespaceURI, localName) in self._attrsNS
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000793
Fred Drake1f549022000-09-24 05:21:58 +0000794 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000795 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000796
Fred Drake1f549022000-09-24 05:21:58 +0000797 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000798 return _get_elements_by_tagName_ns_helper(
799 self, namespaceURI, localName, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000800
Fred Drake1f549022000-09-24 05:21:58 +0000801 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000802 return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000803
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000804 def writexml(self, writer, indent="", addindent="", newl=""):
805 # indent = current indentation
806 # addindent = indentation to add to higher levels
807 # newl = newline string
808 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000809
Fred Drake4ccf4a12000-11-21 22:02:22 +0000810 attrs = self._get_attributes()
Brett Cannon861fd6f2007-02-21 22:05:37 +0000811 a_names = sorted(attrs.keys())
Fred Drake55c38192000-06-29 19:39:57 +0000812
813 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000814 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000815 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000816 writer.write("\"")
817 if self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000818 writer.write(">%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000819 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000820 node.writexml(writer,indent+addindent,addindent,newl)
821 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
Fred Drake55c38192000-06-29 19:39:57 +0000822 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000823 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000824
Fred Drake1f549022000-09-24 05:21:58 +0000825 def _get_attributes(self):
Fred Drake2998a552001-12-06 18:27:48 +0000826 return NamedNodeMap(self._attrs, self._attrsNS, self)
Fred Drake55c38192000-06-29 19:39:57 +0000827
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000828 def hasAttributes(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000829 if self._attrs:
830 return True
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000831 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000832 return False
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000833
Martin v. Löwis787354c2003-01-25 15:28:29 +0000834 # DOM Level 3 attributes, based on the 22 Oct 2002 draft
835
836 def setIdAttribute(self, name):
837 idAttr = self.getAttributeNode(name)
838 self.setIdAttributeNode(idAttr)
839
840 def setIdAttributeNS(self, namespaceURI, localName):
841 idAttr = self.getAttributeNodeNS(namespaceURI, localName)
842 self.setIdAttributeNode(idAttr)
843
844 def setIdAttributeNode(self, idAttr):
845 if idAttr is None or not self.isSameNode(idAttr.ownerElement):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000846 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000847 if _get_containing_entref(self) is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000848 raise xml.dom.NoModificationAllowedErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000849 if not idAttr._is_id:
850 idAttr.__dict__['_is_id'] = True
851 self._magic_id_nodes += 1
852 self.ownerDocument._magic_id_count += 1
853 _clear_id_cache(self)
854
855defproperty(Element, "attributes",
856 doc="NamedNodeMap of attributes on the element.")
857defproperty(Element, "localName",
858 doc="Namespace-local name of this element.")
859
860
861def _set_attribute_node(element, attr):
862 _clear_id_cache(element)
863 element._attrs[attr.name] = attr
864 element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
865
866 # This creates a circular reference, but Element.unlink()
867 # breaks the cycle since the references to the attribute
868 # dictionaries are tossed.
869 attr.__dict__['ownerElement'] = element
870
871
872class Childless:
873 """Mixin that makes childless-ness easy to implement and avoids
874 the complexity of the Node methods that deal with children.
875 """
876
Fred Drake4ccf4a12000-11-21 22:02:22 +0000877 attributes = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000878 childNodes = EmptyNodeList()
879 firstChild = None
880 lastChild = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000881
Martin v. Löwis787354c2003-01-25 15:28:29 +0000882 def _get_firstChild(self):
883 return None
Fred Drake55c38192000-06-29 19:39:57 +0000884
Martin v. Löwis787354c2003-01-25 15:28:29 +0000885 def _get_lastChild(self):
886 return None
Fred Drake1f549022000-09-24 05:21:58 +0000887
Martin v. Löwis787354c2003-01-25 15:28:29 +0000888 def appendChild(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000889 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000890 self.nodeName + " nodes cannot have children")
891
892 def hasChildNodes(self):
893 return False
894
895 def insertBefore(self, newChild, refChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000896 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000897 self.nodeName + " nodes do not have children")
898
899 def removeChild(self, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000900 raise xml.dom.NotFoundErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000901 self.nodeName + " nodes do not have children")
902
903 def replaceChild(self, newChild, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000904 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000905 self.nodeName + " nodes do not have children")
906
907
908class ProcessingInstruction(Childless, Node):
Fred Drake1f549022000-09-24 05:21:58 +0000909 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000910
Fred Drake1f549022000-09-24 05:21:58 +0000911 def __init__(self, target, data):
Fred Drake55c38192000-06-29 19:39:57 +0000912 self.target = self.nodeName = target
913 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000914
Martin v. Löwis787354c2003-01-25 15:28:29 +0000915 def _get_data(self):
916 return self.data
917 def _set_data(self, value):
918 d = self.__dict__
919 d['data'] = d['nodeValue'] = value
920
921 def _get_target(self):
922 return self.target
923 def _set_target(self, value):
924 d = self.__dict__
925 d['target'] = d['nodeName'] = value
926
927 def __setattr__(self, name, value):
928 if name == "data" or name == "nodeValue":
929 self.__dict__['data'] = self.__dict__['nodeValue'] = value
930 elif name == "target" or name == "nodeName":
931 self.__dict__['target'] = self.__dict__['nodeName'] = value
932 else:
933 self.__dict__[name] = value
934
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000935 def writexml(self, writer, indent="", addindent="", newl=""):
936 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000937
Martin v. Löwis787354c2003-01-25 15:28:29 +0000938
939class CharacterData(Childless, Node):
940 def _get_length(self):
941 return len(self.data)
942 __len__ = _get_length
943
944 def _get_data(self):
945 return self.__dict__['data']
946 def _set_data(self, data):
947 d = self.__dict__
948 d['data'] = d['nodeValue'] = data
949
950 _get_nodeValue = _get_data
951 _set_nodeValue = _set_data
952
953 def __setattr__(self, name, value):
954 if name == "data" or name == "nodeValue":
955 self.__dict__['data'] = self.__dict__['nodeValue'] = value
956 else:
957 self.__dict__[name] = value
Fred Drake87432f42001-04-04 14:09:46 +0000958
Fred Drake55c38192000-06-29 19:39:57 +0000959 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000960 data = self.data
961 if len(data) > 10:
Fred Drake1f549022000-09-24 05:21:58 +0000962 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000963 else:
Fred Drake1f549022000-09-24 05:21:58 +0000964 dotdotdot = ""
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000965 return '<DOM %s node "%r%s">' % (
Martin v. Löwis787354c2003-01-25 15:28:29 +0000966 self.__class__.__name__, data[0:10], dotdotdot)
Fred Drake87432f42001-04-04 14:09:46 +0000967
968 def substringData(self, offset, count):
969 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000970 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000971 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000972 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000973 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000974 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000975 return self.data[offset:offset+count]
976
977 def appendData(self, arg):
978 self.data = self.data + arg
Fred Drake87432f42001-04-04 14:09:46 +0000979
980 def insertData(self, offset, arg):
981 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000982 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000983 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000984 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000985 if arg:
986 self.data = "%s%s%s" % (
987 self.data[:offset], arg, self.data[offset:])
Fred Drake87432f42001-04-04 14:09:46 +0000988
989 def deleteData(self, offset, count):
990 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000991 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000992 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000993 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000994 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000995 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000996 if count:
997 self.data = self.data[:offset] + self.data[offset+count:]
Fred Drake87432f42001-04-04 14:09:46 +0000998
999 def replaceData(self, offset, count, 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 count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001005 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001006 if count:
1007 self.data = "%s%s%s" % (
1008 self.data[:offset], arg, self.data[offset+count:])
Martin v. Löwis787354c2003-01-25 15:28:29 +00001009
1010defproperty(CharacterData, "length", doc="Length of the string data.")
1011
Fred Drake87432f42001-04-04 14:09:46 +00001012
1013class Text(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001014 # Make sure we don't add an instance __dict__ if we don't already
1015 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001016 # XXX this does not work, CharacterData is an old-style class
1017 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001018
Fred Drake87432f42001-04-04 14:09:46 +00001019 nodeType = Node.TEXT_NODE
1020 nodeName = "#text"
1021 attributes = None
Fred Drake55c38192000-06-29 19:39:57 +00001022
Fred Drakef7cf40d2000-12-14 18:16:11 +00001023 def splitText(self, offset):
1024 if offset < 0 or offset > len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001025 raise xml.dom.IndexSizeErr("illegal offset value")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001026 newText = self.__class__()
1027 newText.data = self.data[offset:]
1028 newText.ownerDocument = self.ownerDocument
Fred Drakef7cf40d2000-12-14 18:16:11 +00001029 next = self.nextSibling
1030 if self.parentNode and self in self.parentNode.childNodes:
1031 if next is None:
1032 self.parentNode.appendChild(newText)
1033 else:
1034 self.parentNode.insertBefore(newText, next)
1035 self.data = self.data[:offset]
1036 return newText
1037
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001038 def writexml(self, writer, indent="", addindent="", newl=""):
1039 _write_data(writer, "%s%s%s"%(indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001040
Martin v. Löwis787354c2003-01-25 15:28:29 +00001041 # DOM Level 3 (WD 9 April 2002)
1042
1043 def _get_wholeText(self):
1044 L = [self.data]
1045 n = self.previousSibling
1046 while n is not None:
1047 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1048 L.insert(0, n.data)
1049 n = n.previousSibling
1050 else:
1051 break
1052 n = self.nextSibling
1053 while n is not None:
1054 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1055 L.append(n.data)
1056 n = n.nextSibling
1057 else:
1058 break
1059 return ''.join(L)
1060
1061 def replaceWholeText(self, content):
1062 # XXX This needs to be seriously changed if minidom ever
1063 # supports EntityReference nodes.
1064 parent = self.parentNode
1065 n = self.previousSibling
1066 while n is not None:
1067 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1068 next = n.previousSibling
1069 parent.removeChild(n)
1070 n = next
1071 else:
1072 break
1073 n = self.nextSibling
1074 if not content:
1075 parent.removeChild(self)
1076 while n is not None:
1077 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1078 next = n.nextSibling
1079 parent.removeChild(n)
1080 n = next
1081 else:
1082 break
1083 if content:
1084 d = self.__dict__
1085 d['data'] = content
1086 d['nodeValue'] = content
1087 return self
1088 else:
1089 return None
1090
1091 def _get_isWhitespaceInElementContent(self):
1092 if self.data.strip():
1093 return False
1094 elem = _get_containing_element(self)
1095 if elem is None:
1096 return False
1097 info = self.ownerDocument._get_elem_info(elem)
1098 if info is None:
1099 return False
1100 else:
1101 return info.isElementContent()
1102
1103defproperty(Text, "isWhitespaceInElementContent",
1104 doc="True iff this text node contains only whitespace"
1105 " and is in element content.")
1106defproperty(Text, "wholeText",
1107 doc="The text of all logically-adjacent text nodes.")
1108
1109
1110def _get_containing_element(node):
1111 c = node.parentNode
1112 while c is not None:
1113 if c.nodeType == Node.ELEMENT_NODE:
1114 return c
1115 c = c.parentNode
1116 return None
1117
1118def _get_containing_entref(node):
1119 c = node.parentNode
1120 while c is not None:
1121 if c.nodeType == Node.ENTITY_REFERENCE_NODE:
1122 return c
1123 c = c.parentNode
1124 return None
1125
1126
Alex Martelli0ee43512006-08-21 19:53:20 +00001127class Comment(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001128 nodeType = Node.COMMENT_NODE
1129 nodeName = "#comment"
1130
1131 def __init__(self, data):
1132 self.data = self.nodeValue = data
1133
1134 def writexml(self, writer, indent="", addindent="", newl=""):
1135 writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
1136
Fred Drake87432f42001-04-04 14:09:46 +00001137
1138class CDATASection(Text):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001139 # Make sure we don't add an instance __dict__ if we don't already
1140 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001141 # XXX this does not work, Text is an old-style class
1142 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001143
Fred Drake87432f42001-04-04 14:09:46 +00001144 nodeType = Node.CDATA_SECTION_NODE
1145 nodeName = "#cdata-section"
1146
1147 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001148 if self.data.find("]]>") >= 0:
1149 raise ValueError("']]>' not allowed in a CDATA section")
Guido van Rossum5b5e0b92001-09-19 13:28:25 +00001150 writer.write("<![CDATA[%s]]>" % self.data)
Fred Drake87432f42001-04-04 14:09:46 +00001151
1152
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001153class ReadOnlySequentialNamedNodeMap(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001154 __slots__ = '_seq',
1155
1156 def __init__(self, seq=()):
1157 # seq should be a list or tuple
1158 self._seq = seq
1159
1160 def __len__(self):
1161 return len(self._seq)
1162
1163 def _get_length(self):
1164 return len(self._seq)
1165
1166 def getNamedItem(self, name):
1167 for n in self._seq:
1168 if n.nodeName == name:
1169 return n
1170
1171 def getNamedItemNS(self, namespaceURI, localName):
1172 for n in self._seq:
1173 if n.namespaceURI == namespaceURI and n.localName == localName:
1174 return n
1175
1176 def __getitem__(self, name_or_tuple):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001177 if isinstance(name_or_tuple, tuple):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001178 node = self.getNamedItemNS(*name_or_tuple)
1179 else:
1180 node = self.getNamedItem(name_or_tuple)
1181 if node is None:
Collin Winter70e79802007-08-24 18:57:22 +00001182 raise KeyError(name_or_tuple)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001183 return node
1184
1185 def item(self, index):
1186 if index < 0:
1187 return None
1188 try:
1189 return self._seq[index]
1190 except IndexError:
1191 return None
1192
1193 def removeNamedItem(self, name):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001194 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001195 "NamedNodeMap instance is read-only")
1196
1197 def removeNamedItemNS(self, namespaceURI, localName):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001198 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001199 "NamedNodeMap instance is read-only")
1200
1201 def setNamedItem(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001202 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001203 "NamedNodeMap instance is read-only")
1204
1205 def setNamedItemNS(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001206 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001207 "NamedNodeMap instance is read-only")
1208
1209 def __getstate__(self):
1210 return [self._seq]
1211
1212 def __setstate__(self, state):
1213 self._seq = state[0]
1214
1215defproperty(ReadOnlySequentialNamedNodeMap, "length",
1216 doc="Number of entries in the NamedNodeMap.")
Paul Prescod73678da2000-07-01 04:58:47 +00001217
Fred Drakef7cf40d2000-12-14 18:16:11 +00001218
Martin v. Löwis787354c2003-01-25 15:28:29 +00001219class Identified:
1220 """Mix-in class that supports the publicId and systemId attributes."""
1221
Martin v. Löwis995359c2003-01-26 08:59:32 +00001222 # XXX this does not work, this is an old-style class
1223 # __slots__ = 'publicId', 'systemId'
Martin v. Löwis787354c2003-01-25 15:28:29 +00001224
1225 def _identified_mixin_init(self, publicId, systemId):
1226 self.publicId = publicId
1227 self.systemId = systemId
1228
1229 def _get_publicId(self):
1230 return self.publicId
1231
1232 def _get_systemId(self):
1233 return self.systemId
1234
1235class DocumentType(Identified, Childless, Node):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001236 nodeType = Node.DOCUMENT_TYPE_NODE
1237 nodeValue = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001238 name = None
1239 publicId = None
1240 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +00001241 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001242
1243 def __init__(self, qualifiedName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001244 self.entities = ReadOnlySequentialNamedNodeMap()
1245 self.notations = ReadOnlySequentialNamedNodeMap()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001246 if qualifiedName:
1247 prefix, localname = _nssplit(qualifiedName)
1248 self.name = localname
Martin v. Löwis787354c2003-01-25 15:28:29 +00001249 self.nodeName = self.name
1250
1251 def _get_internalSubset(self):
1252 return self.internalSubset
1253
1254 def cloneNode(self, deep):
1255 if self.ownerDocument is None:
1256 # it's ok
1257 clone = DocumentType(None)
1258 clone.name = self.name
1259 clone.nodeName = self.name
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001260 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001261 if deep:
1262 clone.entities._seq = []
1263 clone.notations._seq = []
1264 for n in self.notations._seq:
1265 notation = Notation(n.nodeName, n.publicId, n.systemId)
1266 clone.notations._seq.append(notation)
1267 n._call_user_data_handler(operation, n, notation)
1268 for e in self.entities._seq:
1269 entity = Entity(e.nodeName, e.publicId, e.systemId,
1270 e.notationName)
1271 entity.actualEncoding = e.actualEncoding
1272 entity.encoding = e.encoding
1273 entity.version = e.version
1274 clone.entities._seq.append(entity)
1275 e._call_user_data_handler(operation, n, entity)
1276 self._call_user_data_handler(operation, self, clone)
1277 return clone
1278 else:
1279 return None
1280
1281 def writexml(self, writer, indent="", addindent="", newl=""):
1282 writer.write("<!DOCTYPE ")
1283 writer.write(self.name)
1284 if self.publicId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001285 writer.write("%s PUBLIC '%s'%s '%s'"
1286 % (newl, self.publicId, newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001287 elif self.systemId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001288 writer.write("%s SYSTEM '%s'" % (newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001289 if self.internalSubset is not None:
1290 writer.write(" [")
1291 writer.write(self.internalSubset)
1292 writer.write("]")
Georg Brandl175a7dc2005-08-25 22:02:43 +00001293 writer.write(">"+newl)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001294
1295class Entity(Identified, Node):
1296 attributes = None
1297 nodeType = Node.ENTITY_NODE
1298 nodeValue = None
1299
1300 actualEncoding = None
1301 encoding = None
1302 version = None
1303
1304 def __init__(self, name, publicId, systemId, notation):
1305 self.nodeName = name
1306 self.notationName = notation
1307 self.childNodes = NodeList()
1308 self._identified_mixin_init(publicId, systemId)
1309
1310 def _get_actualEncoding(self):
1311 return self.actualEncoding
1312
1313 def _get_encoding(self):
1314 return self.encoding
1315
1316 def _get_version(self):
1317 return self.version
1318
1319 def appendChild(self, newChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001320 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001321 "cannot append children to an entity node")
1322
1323 def insertBefore(self, newChild, refChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001324 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001325 "cannot insert children below an entity node")
1326
1327 def removeChild(self, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001328 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001329 "cannot remove children from an entity node")
1330
1331 def replaceChild(self, newChild, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001332 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001333 "cannot replace children of an entity node")
1334
1335class Notation(Identified, Childless, Node):
1336 nodeType = Node.NOTATION_NODE
1337 nodeValue = None
1338
1339 def __init__(self, name, publicId, systemId):
1340 self.nodeName = name
1341 self._identified_mixin_init(publicId, systemId)
Fred Drakef7cf40d2000-12-14 18:16:11 +00001342
1343
Martin v. Löwis787354c2003-01-25 15:28:29 +00001344class DOMImplementation(DOMImplementationLS):
1345 _features = [("core", "1.0"),
1346 ("core", "2.0"),
1347 ("core", "3.0"),
1348 ("core", None),
1349 ("xml", "1.0"),
1350 ("xml", "2.0"),
1351 ("xml", "3.0"),
1352 ("xml", None),
1353 ("ls-load", "3.0"),
1354 ("ls-load", None),
1355 ]
1356
Fred Drakef7cf40d2000-12-14 18:16:11 +00001357 def hasFeature(self, feature, version):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001358 if version == "":
1359 version = None
1360 return (feature.lower(), version) in self._features
Fred Drakef7cf40d2000-12-14 18:16:11 +00001361
1362 def createDocument(self, namespaceURI, qualifiedName, doctype):
1363 if doctype and doctype.parentNode is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001364 raise xml.dom.WrongDocumentErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001365 "doctype object owned by another DOM tree")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001366 doc = self._create_document()
1367
1368 add_root_element = not (namespaceURI is None
1369 and qualifiedName is None
1370 and doctype is None)
1371
1372 if not qualifiedName and add_root_element:
Martin v. Löwisb417be22001-02-06 01:16:06 +00001373 # The spec is unclear what to raise here; SyntaxErr
1374 # would be the other obvious candidate. Since Xerces raises
1375 # InvalidCharacterErr, and since SyntaxErr is not listed
1376 # for createDocument, that seems to be the better choice.
1377 # XXX: need to check for illegal characters here and in
1378 # createElement.
Martin v. Löwis787354c2003-01-25 15:28:29 +00001379
1380 # DOM Level III clears this up when talking about the return value
1381 # of this function. If namespaceURI, qName and DocType are
1382 # Null the document is returned without a document element
1383 # Otherwise if doctype or namespaceURI are not None
1384 # Then we go back to the above problem
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001385 raise xml.dom.InvalidCharacterErr("Element with no name")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001386
1387 if add_root_element:
1388 prefix, localname = _nssplit(qualifiedName)
1389 if prefix == "xml" \
1390 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001391 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001392 if prefix and not namespaceURI:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001393 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001394 "illegal use of prefix without namespaces")
1395 element = doc.createElementNS(namespaceURI, qualifiedName)
1396 if doctype:
1397 doc.appendChild(doctype)
1398 doc.appendChild(element)
1399
1400 if doctype:
1401 doctype.parentNode = doctype.ownerDocument = doc
1402
Fred Drakef7cf40d2000-12-14 18:16:11 +00001403 doc.doctype = doctype
1404 doc.implementation = self
1405 return doc
1406
1407 def createDocumentType(self, qualifiedName, publicId, systemId):
1408 doctype = DocumentType(qualifiedName)
1409 doctype.publicId = publicId
1410 doctype.systemId = systemId
1411 return doctype
1412
Martin v. Löwis787354c2003-01-25 15:28:29 +00001413 # DOM Level 3 (WD 9 April 2002)
1414
1415 def getInterface(self, feature):
1416 if self.hasFeature(feature, None):
1417 return self
1418 else:
1419 return None
1420
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001421 # internal
Martin v. Löwis787354c2003-01-25 15:28:29 +00001422 def _create_document(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001423 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001424
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001425class ElementInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001426 """Object that represents content-model information for an element.
1427
1428 This implementation is not expected to be used in practice; DOM
1429 builders should provide implementations which do the right thing
1430 using information available to it.
1431
1432 """
1433
1434 __slots__ = 'tagName',
1435
1436 def __init__(self, name):
1437 self.tagName = name
1438
1439 def getAttributeType(self, aname):
1440 return _no_type
1441
1442 def getAttributeTypeNS(self, namespaceURI, localName):
1443 return _no_type
1444
1445 def isElementContent(self):
1446 return False
1447
1448 def isEmpty(self):
1449 """Returns true iff this element is declared to have an EMPTY
1450 content model."""
1451 return False
1452
1453 def isId(self, aname):
1454 """Returns true iff the named attribte is a DTD-style ID."""
1455 return False
1456
1457 def isIdNS(self, namespaceURI, localName):
1458 """Returns true iff the identified attribute is a DTD-style ID."""
1459 return False
1460
1461 def __getstate__(self):
1462 return self.tagName
1463
1464 def __setstate__(self, state):
1465 self.tagName = state
1466
1467def _clear_id_cache(node):
1468 if node.nodeType == Node.DOCUMENT_NODE:
1469 node._id_cache.clear()
1470 node._id_search_stack = None
1471 elif _in_document(node):
1472 node.ownerDocument._id_cache.clear()
1473 node.ownerDocument._id_search_stack= None
1474
1475class Document(Node, DocumentLS):
1476 _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
1477 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
1478
Fred Drake1f549022000-09-24 05:21:58 +00001479 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +00001480 nodeName = "#document"
1481 nodeValue = None
1482 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001483 doctype = None
1484 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001485 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001486
1487 implementation = DOMImplementation()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001488
1489 # Document attributes from Level 3 (WD 9 April 2002)
1490
1491 actualEncoding = None
1492 encoding = None
1493 standalone = None
1494 version = None
1495 strictErrorChecking = False
1496 errorHandler = None
1497 documentURI = None
1498
1499 _magic_id_count = 0
1500
1501 def __init__(self):
1502 self.childNodes = NodeList()
1503 # mapping of (namespaceURI, localName) -> ElementInfo
1504 # and tagName -> ElementInfo
1505 self._elem_info = {}
1506 self._id_cache = {}
1507 self._id_search_stack = None
1508
1509 def _get_elem_info(self, element):
1510 if element.namespaceURI:
1511 key = element.namespaceURI, element.localName
1512 else:
1513 key = element.tagName
1514 return self._elem_info.get(key)
1515
1516 def _get_actualEncoding(self):
1517 return self.actualEncoding
1518
1519 def _get_doctype(self):
1520 return self.doctype
1521
1522 def _get_documentURI(self):
1523 return self.documentURI
1524
1525 def _get_encoding(self):
1526 return self.encoding
1527
1528 def _get_errorHandler(self):
1529 return self.errorHandler
1530
1531 def _get_standalone(self):
1532 return self.standalone
1533
1534 def _get_strictErrorChecking(self):
1535 return self.strictErrorChecking
1536
1537 def _get_version(self):
1538 return self.version
Fred Drake55c38192000-06-29 19:39:57 +00001539
Fred Drake1f549022000-09-24 05:21:58 +00001540 def appendChild(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001541 if node.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001542 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001543 "%s cannot be child of %s" % (repr(node), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001544 if node.parentNode is not None:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001545 # This needs to be done before the next test since this
1546 # may *be* the document element, in which case it should
1547 # end up re-ordered to the end.
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001548 node.parentNode.removeChild(node)
1549
Fred Drakef7cf40d2000-12-14 18:16:11 +00001550 if node.nodeType == Node.ELEMENT_NODE \
1551 and self._get_documentElement():
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001552 raise xml.dom.HierarchyRequestErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001553 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +00001554 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +00001555
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001556 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001557 try:
1558 self.childNodes.remove(oldChild)
1559 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001560 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001561 oldChild.nextSibling = oldChild.previousSibling = None
1562 oldChild.parentNode = None
1563 if self.documentElement is oldChild:
1564 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +00001565
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001566 return oldChild
1567
Fred Drakef7cf40d2000-12-14 18:16:11 +00001568 def _get_documentElement(self):
1569 for node in self.childNodes:
1570 if node.nodeType == Node.ELEMENT_NODE:
1571 return node
1572
1573 def unlink(self):
1574 if self.doctype is not None:
1575 self.doctype.unlink()
1576 self.doctype = None
1577 Node.unlink(self)
1578
Martin v. Löwis787354c2003-01-25 15:28:29 +00001579 def cloneNode(self, deep):
1580 if not deep:
1581 return None
1582 clone = self.implementation.createDocument(None, None, None)
1583 clone.encoding = self.encoding
1584 clone.standalone = self.standalone
1585 clone.version = self.version
1586 for n in self.childNodes:
1587 childclone = _clone_node(n, deep, clone)
1588 assert childclone.ownerDocument.isSameNode(clone)
1589 clone.childNodes.append(childclone)
1590 if childclone.nodeType == Node.DOCUMENT_NODE:
1591 assert clone.documentElement is None
1592 elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
1593 assert clone.doctype is None
1594 clone.doctype = childclone
1595 childclone.parentNode = clone
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001596 self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
Martin v. Löwis787354c2003-01-25 15:28:29 +00001597 self, clone)
1598 return clone
1599
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001600 def createDocumentFragment(self):
1601 d = DocumentFragment()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001602 d.ownerDocument = self
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001603 return d
Fred Drake55c38192000-06-29 19:39:57 +00001604
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001605 def createElement(self, tagName):
1606 e = Element(tagName)
1607 e.ownerDocument = self
1608 return e
Fred Drake55c38192000-06-29 19:39:57 +00001609
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001610 def createTextNode(self, data):
Christian Heimesc9543e42007-11-28 08:28:28 +00001611 if not isinstance(data, str):
Collin Winter70e79802007-08-24 18:57:22 +00001612 raise TypeError("node contents must be a string")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001613 t = Text()
1614 t.data = data
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001615 t.ownerDocument = self
1616 return t
Fred Drake55c38192000-06-29 19:39:57 +00001617
Fred Drake87432f42001-04-04 14:09:46 +00001618 def createCDATASection(self, data):
Christian Heimesc9543e42007-11-28 08:28:28 +00001619 if not isinstance(data, str):
Collin Winter70e79802007-08-24 18:57:22 +00001620 raise TypeError("node contents must be a string")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001621 c = CDATASection()
1622 c.data = data
Fred Drake87432f42001-04-04 14:09:46 +00001623 c.ownerDocument = self
1624 return c
1625
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001626 def createComment(self, data):
1627 c = Comment(data)
1628 c.ownerDocument = self
1629 return c
Fred Drake55c38192000-06-29 19:39:57 +00001630
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001631 def createProcessingInstruction(self, target, data):
1632 p = ProcessingInstruction(target, data)
1633 p.ownerDocument = self
1634 return p
1635
1636 def createAttribute(self, qName):
1637 a = Attr(qName)
1638 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001639 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001640 return a
Fred Drake55c38192000-06-29 19:39:57 +00001641
1642 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001643 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001644 e = Element(qualifiedName, namespaceURI, prefix)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001645 e.ownerDocument = self
1646 return e
Fred Drake55c38192000-06-29 19:39:57 +00001647
1648 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001649 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001650 a = Attr(qualifiedName, namespaceURI, localName, prefix)
1651 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001652 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001653 return a
Fred Drake55c38192000-06-29 19:39:57 +00001654
Martin v. Löwis787354c2003-01-25 15:28:29 +00001655 # A couple of implementation-specific helpers to create node types
1656 # not supported by the W3C DOM specs:
1657
1658 def _create_entity(self, name, publicId, systemId, notationName):
1659 e = Entity(name, publicId, systemId, notationName)
1660 e.ownerDocument = self
1661 return e
1662
1663 def _create_notation(self, name, publicId, systemId):
1664 n = Notation(name, publicId, systemId)
1665 n.ownerDocument = self
1666 return n
1667
1668 def getElementById(self, id):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +00001669 if id in self._id_cache:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001670 return self._id_cache[id]
1671 if not (self._elem_info or self._magic_id_count):
1672 return None
1673
1674 stack = self._id_search_stack
1675 if stack is None:
1676 # we never searched before, or the cache has been cleared
1677 stack = [self.documentElement]
1678 self._id_search_stack = stack
1679 elif not stack:
1680 # Previous search was completed and cache is still valid;
1681 # no matching node.
1682 return None
1683
1684 result = None
1685 while stack:
1686 node = stack.pop()
1687 # add child elements to stack for continued searching
1688 stack.extend([child for child in node.childNodes
1689 if child.nodeType in _nodeTypes_with_children])
1690 # check this node
1691 info = self._get_elem_info(node)
1692 if info:
1693 # We have to process all ID attributes before
1694 # returning in order to get all the attributes set to
1695 # be IDs using Element.setIdAttribute*().
1696 for attr in node.attributes.values():
1697 if attr.namespaceURI:
1698 if info.isIdNS(attr.namespaceURI, attr.localName):
1699 self._id_cache[attr.value] = node
1700 if attr.value == id:
1701 result = node
1702 elif not node._magic_id_nodes:
1703 break
1704 elif info.isId(attr.name):
1705 self._id_cache[attr.value] = node
1706 if attr.value == id:
1707 result = node
1708 elif not node._magic_id_nodes:
1709 break
1710 elif attr._is_id:
1711 self._id_cache[attr.value] = node
1712 if attr.value == id:
1713 result = node
1714 elif node._magic_id_nodes == 1:
1715 break
1716 elif node._magic_id_nodes:
1717 for attr in node.attributes.values():
1718 if attr._is_id:
1719 self._id_cache[attr.value] = node
1720 if attr.value == id:
1721 result = node
1722 if result is not None:
1723 break
1724 return result
1725
Fred Drake1f549022000-09-24 05:21:58 +00001726 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001727 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drakefbe7b4f2001-07-04 06:25:53 +00001728
1729 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001730 return _get_elements_by_tagName_ns_helper(
1731 self, namespaceURI, localName, NodeList())
1732
1733 def isSupported(self, feature, version):
1734 return self.implementation.hasFeature(feature, version)
1735
1736 def importNode(self, node, deep):
1737 if node.nodeType == Node.DOCUMENT_NODE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001738 raise xml.dom.NotSupportedErr("cannot import document nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001739 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001740 raise xml.dom.NotSupportedErr("cannot import document type nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001741 return _clone_node(node, deep, self)
Fred Drake55c38192000-06-29 19:39:57 +00001742
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001743 def writexml(self, writer, indent="", addindent="", newl="",
1744 encoding = None):
1745 if encoding is None:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001746 writer.write('<?xml version="1.0" ?>'+newl)
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001747 else:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001748 writer.write('<?xml version="1.0" encoding="%s"?>%s' % (encoding, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001749 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001750 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +00001751
Martin v. Löwis787354c2003-01-25 15:28:29 +00001752 # DOM Level 3 (WD 9 April 2002)
1753
1754 def renameNode(self, n, namespaceURI, name):
1755 if n.ownerDocument is not self:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001756 raise xml.dom.WrongDocumentErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001757 "cannot rename nodes from other documents;\n"
1758 "expected %s,\nfound %s" % (self, n.ownerDocument))
1759 if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001760 raise xml.dom.NotSupportedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001761 "renameNode() only applies to element and attribute nodes")
1762 if namespaceURI != EMPTY_NAMESPACE:
1763 if ':' in name:
1764 prefix, localName = name.split(':', 1)
1765 if ( prefix == "xmlns"
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001766 and namespaceURI != xml.dom.XMLNS_NAMESPACE):
1767 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001768 "illegal use of 'xmlns' prefix")
1769 else:
1770 if ( name == "xmlns"
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001771 and namespaceURI != xml.dom.XMLNS_NAMESPACE
Martin v. Löwis787354c2003-01-25 15:28:29 +00001772 and n.nodeType == Node.ATTRIBUTE_NODE):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001773 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001774 "illegal use of the 'xmlns' attribute")
1775 prefix = None
1776 localName = name
1777 else:
1778 prefix = None
1779 localName = None
1780 if n.nodeType == Node.ATTRIBUTE_NODE:
1781 element = n.ownerElement
1782 if element is not None:
1783 is_id = n._is_id
1784 element.removeAttributeNode(n)
1785 else:
1786 element = None
1787 # avoid __setattr__
1788 d = n.__dict__
1789 d['prefix'] = prefix
1790 d['localName'] = localName
1791 d['namespaceURI'] = namespaceURI
1792 d['nodeName'] = name
1793 if n.nodeType == Node.ELEMENT_NODE:
1794 d['tagName'] = name
1795 else:
1796 # attribute node
1797 d['name'] = name
1798 if element is not None:
1799 element.setAttributeNode(n)
1800 if is_id:
1801 element.setIdAttributeNode(n)
1802 # It's not clear from a semantic perspective whether we should
1803 # call the user data handlers for the NODE_RENAMED event since
1804 # we're re-using the existing node. The draft spec has been
1805 # interpreted as meaning "no, don't call the handler unless a
1806 # new node is created."
1807 return n
1808
1809defproperty(Document, "documentElement",
1810 doc="Top-level element of this document.")
1811
1812
1813def _clone_node(node, deep, newOwnerDocument):
1814 """
1815 Clone a node and give it the new owner document.
1816 Called by Node.cloneNode and Document.importNode
1817 """
1818 if node.ownerDocument.isSameNode(newOwnerDocument):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001819 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001820 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001821 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001822 if node.nodeType == Node.ELEMENT_NODE:
1823 clone = newOwnerDocument.createElementNS(node.namespaceURI,
1824 node.nodeName)
1825 for attr in node.attributes.values():
1826 clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
1827 a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
1828 a.specified = attr.specified
1829
1830 if deep:
1831 for child in node.childNodes:
1832 c = _clone_node(child, deep, newOwnerDocument)
1833 clone.appendChild(c)
1834
1835 elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
1836 clone = newOwnerDocument.createDocumentFragment()
1837 if deep:
1838 for child in node.childNodes:
1839 c = _clone_node(child, deep, newOwnerDocument)
1840 clone.appendChild(c)
1841
1842 elif node.nodeType == Node.TEXT_NODE:
1843 clone = newOwnerDocument.createTextNode(node.data)
1844 elif node.nodeType == Node.CDATA_SECTION_NODE:
1845 clone = newOwnerDocument.createCDATASection(node.data)
1846 elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
1847 clone = newOwnerDocument.createProcessingInstruction(node.target,
1848 node.data)
1849 elif node.nodeType == Node.COMMENT_NODE:
1850 clone = newOwnerDocument.createComment(node.data)
1851 elif node.nodeType == Node.ATTRIBUTE_NODE:
1852 clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
1853 node.nodeName)
1854 clone.specified = True
1855 clone.value = node.value
1856 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
1857 assert node.ownerDocument is not newOwnerDocument
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001858 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001859 clone = newOwnerDocument.implementation.createDocumentType(
1860 node.name, node.publicId, node.systemId)
1861 clone.ownerDocument = newOwnerDocument
1862 if deep:
1863 clone.entities._seq = []
1864 clone.notations._seq = []
1865 for n in node.notations._seq:
1866 notation = Notation(n.nodeName, n.publicId, n.systemId)
1867 notation.ownerDocument = newOwnerDocument
1868 clone.notations._seq.append(notation)
1869 if hasattr(n, '_call_user_data_handler'):
1870 n._call_user_data_handler(operation, n, notation)
1871 for e in node.entities._seq:
1872 entity = Entity(e.nodeName, e.publicId, e.systemId,
1873 e.notationName)
1874 entity.actualEncoding = e.actualEncoding
1875 entity.encoding = e.encoding
1876 entity.version = e.version
1877 entity.ownerDocument = newOwnerDocument
1878 clone.entities._seq.append(entity)
1879 if hasattr(e, '_call_user_data_handler'):
1880 e._call_user_data_handler(operation, n, entity)
1881 else:
1882 # Note the cloning of Document and DocumentType nodes is
1883 # implemenetation specific. minidom handles those cases
1884 # directly in the cloneNode() methods.
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001885 raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001886
1887 # Check for _call_user_data_handler() since this could conceivably
1888 # used with other DOM implementations (one of the FourThought
1889 # DOMs, perhaps?).
1890 if hasattr(node, '_call_user_data_handler'):
1891 node._call_user_data_handler(operation, node, clone)
1892 return clone
1893
1894
1895def _nssplit(qualifiedName):
1896 fields = qualifiedName.split(':', 1)
1897 if len(fields) == 2:
1898 return fields
1899 else:
1900 return (None, fields[0])
1901
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:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001913 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001914 return expatbuilder.parse(file)
1915 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +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:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001923 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001924 return expatbuilder.parseString(string)
1925 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +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:
Christian Heimesc9543e42007-11-28 08:28:28 +00001932 if isinstance(features, str):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001933 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