blob: bc68cf89335d93e18736c8259a490cabf33ec1be [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
Georg Brandlb044b2a2009-09-16 16:05:59 +000046 def toxml(self, encoding=None):
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000047 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:
R. David Murraydc6da8a2009-04-09 22:16:43 +0000182 if not child.data:
183 # empty text node; discard
184 if L:
185 L[-1].nextSibling = child.nextSibling
186 if child.nextSibling:
187 child.nextSibling.previousSibling = child.previousSibling
188 child.unlink()
189 elif L and L[-1].nodeType == child.nodeType:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000190 # collapse text node
191 node = L[-1]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000192 node.data = node.data + child.data
Fred Drake4ccf4a12000-11-21 22:02:22 +0000193 node.nextSibling = child.nextSibling
R. David Murraydc6da8a2009-04-09 22:16:43 +0000194 if child.nextSibling:
195 child.nextSibling.previousSibling = node
Fred Drake4ccf4a12000-11-21 22:02:22 +0000196 child.unlink()
R. David Murraydc6da8a2009-04-09 22:16:43 +0000197 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000198 L.append(child)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000199 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000200 L.append(child)
201 if child.nodeType == Node.ELEMENT_NODE:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000202 child.normalize()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000203 self.childNodes[:] = L
Paul Prescod73678da2000-07-01 04:58:47 +0000204
Fred Drake1f549022000-09-24 05:21:58 +0000205 def cloneNode(self, deep):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000206 return _clone_node(self, deep, self.ownerDocument or self)
Fred Drake55c38192000-06-29 19:39:57 +0000207
Martin v. Löwis787354c2003-01-25 15:28:29 +0000208 def isSupported(self, feature, version):
209 return self.ownerDocument.implementation.hasFeature(feature, version)
210
211 def _get_localName(self):
212 # Overridden in Element and Attr where localName can be Non-Null
213 return None
214
215 # Node interfaces from Level 3 (WD 9 April 2002)
Fred Drake25239772001-02-02 19:40:19 +0000216
217 def isSameNode(self, other):
218 return self is other
219
Martin v. Löwis787354c2003-01-25 15:28:29 +0000220 def getInterface(self, feature):
221 if self.isSupported(feature, None):
222 return self
223 else:
224 return None
225
226 # The "user data" functions use a dictionary that is only present
227 # if some user data has been set, so be careful not to assume it
228 # exists.
229
230 def getUserData(self, key):
231 try:
232 return self._user_data[key][0]
233 except (AttributeError, KeyError):
234 return None
235
236 def setUserData(self, key, data, handler):
237 old = None
238 try:
239 d = self._user_data
240 except AttributeError:
241 d = {}
242 self._user_data = d
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000243 if key in d:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000244 old = d[key][0]
245 if data is None:
246 # ignore handlers passed for None
247 handler = None
248 if old is not None:
249 del d[key]
250 else:
251 d[key] = (data, handler)
252 return old
253
254 def _call_user_data_handler(self, operation, src, dst):
255 if hasattr(self, "_user_data"):
Brett Cannon861fd6f2007-02-21 22:05:37 +0000256 for key, (data, handler) in list(self._user_data.items()):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000257 if handler is not None:
258 handler.handle(operation, key, data, src, dst)
259
Fred Drake25239772001-02-02 19:40:19 +0000260 # minidom-specific API:
261
Fred Drake1f549022000-09-24 05:21:58 +0000262 def unlink(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000263 self.parentNode = self.ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000264 if self.childNodes:
265 for child in self.childNodes:
266 child.unlink()
267 self.childNodes = NodeList()
Paul Prescod4221ff02000-10-13 20:11:42 +0000268 self.previousSibling = None
269 self.nextSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000270
271defproperty(Node, "firstChild", doc="First child node, or None.")
272defproperty(Node, "lastChild", doc="Last child node, or None.")
273defproperty(Node, "localName", doc="Namespace-local name of this node.")
274
275
276def _append_child(self, node):
277 # fast path with less checks; usable by DOM builders if careful
278 childNodes = self.childNodes
279 if childNodes:
280 last = childNodes[-1]
281 node.__dict__["previousSibling"] = last
282 last.__dict__["nextSibling"] = node
283 childNodes.append(node)
284 node.__dict__["parentNode"] = self
285
286def _in_document(node):
287 # return True iff node is part of a document tree
288 while node is not None:
289 if node.nodeType == Node.DOCUMENT_NODE:
290 return True
291 node = node.parentNode
292 return False
Fred Drake55c38192000-06-29 19:39:57 +0000293
Fred Drake1f549022000-09-24 05:21:58 +0000294def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000295 "Writes datachars to writer."
Georg Brandlc524cff2010-11-26 08:42:45 +0000296 if data:
297 data = data.replace("&", "&amp;").replace("<", "&lt;"). \
298 replace("\"", "&quot;").replace(">", "&gt;")
299 writer.write(data)
Fred Drake55c38192000-06-29 19:39:57 +0000300
Martin v. Löwis787354c2003-01-25 15:28:29 +0000301def _get_elements_by_tagName_helper(parent, name, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000302 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000303 if node.nodeType == Node.ELEMENT_NODE and \
304 (name == "*" or node.tagName == name):
305 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000306 _get_elements_by_tagName_helper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000307 return rc
308
Martin v. Löwis787354c2003-01-25 15:28:29 +0000309def _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000310 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000311 if node.nodeType == Node.ELEMENT_NODE:
Martin v. Löwised525fb2001-06-03 14:06:42 +0000312 if ((localName == "*" or node.localName == localName) and
Fred Drake1f549022000-09-24 05:21:58 +0000313 (nsURI == "*" or node.namespaceURI == nsURI)):
314 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000315 _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000316 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000317
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000318class DocumentFragment(Node):
319 nodeType = Node.DOCUMENT_FRAGMENT_NODE
320 nodeName = "#document-fragment"
321 nodeValue = None
322 attributes = None
323 parentNode = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000324 _child_node_types = (Node.ELEMENT_NODE,
325 Node.TEXT_NODE,
326 Node.CDATA_SECTION_NODE,
327 Node.ENTITY_REFERENCE_NODE,
328 Node.PROCESSING_INSTRUCTION_NODE,
329 Node.COMMENT_NODE,
330 Node.NOTATION_NODE)
331
332 def __init__(self):
333 self.childNodes = NodeList()
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000334
335
Fred Drake55c38192000-06-29 19:39:57 +0000336class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000337 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000338 attributes = None
339 ownerElement = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000340 specified = False
341 _is_id = False
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000342
Martin v. Löwis787354c2003-01-25 15:28:29 +0000343 _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
344
345 def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
346 prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000347 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000348 d = self.__dict__
Fred Drake4ccf4a12000-11-21 22:02:22 +0000349 d["nodeName"] = d["name"] = qName
350 d["namespaceURI"] = namespaceURI
351 d["prefix"] = prefix
Martin v. Löwis787354c2003-01-25 15:28:29 +0000352 d['childNodes'] = NodeList()
353
354 # Add the single child node that represents the value of the attr
355 self.childNodes.append(Text())
356
Paul Prescod73678da2000-07-01 04:58:47 +0000357 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000358
Martin v. Löwis787354c2003-01-25 15:28:29 +0000359 def _get_localName(self):
Alex Martelli0ee43512006-08-21 19:53:20 +0000360 if 'localName' in self.__dict__:
Guido van Rossum3e1f85e2007-07-27 18:03:11 +0000361 return self.__dict__['localName']
Martin v. Löwis787354c2003-01-25 15:28:29 +0000362 return self.nodeName.split(":", 1)[-1]
363
364 def _get_name(self):
365 return self.name
366
367 def _get_specified(self):
368 return self.specified
369
Fred Drake1f549022000-09-24 05:21:58 +0000370 def __setattr__(self, name, value):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000371 d = self.__dict__
Fred Drake1f549022000-09-24 05:21:58 +0000372 if name in ("value", "nodeValue"):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000373 d["value"] = d["nodeValue"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000374 d2 = self.childNodes[0].__dict__
375 d2["data"] = d2["nodeValue"] = value
376 if self.ownerElement is not None:
377 _clear_id_cache(self.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000378 elif name in ("name", "nodeName"):
379 d["name"] = d["nodeName"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000380 if self.ownerElement is not None:
381 _clear_id_cache(self.ownerElement)
Fred Drake55c38192000-06-29 19:39:57 +0000382 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000383 d[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000384
Martin v. Löwis995359c2003-01-26 08:59:32 +0000385 def _set_prefix(self, prefix):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000386 nsuri = self.namespaceURI
Martin v. Löwis995359c2003-01-26 08:59:32 +0000387 if prefix == "xmlns":
388 if nsuri and nsuri != XMLNS_NAMESPACE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000389 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000390 "illegal use of 'xmlns' prefix for the wrong namespace")
391 d = self.__dict__
392 d['prefix'] = prefix
393 if prefix is None:
394 newName = self.localName
395 else:
Martin v. Löwis995359c2003-01-26 08:59:32 +0000396 newName = "%s:%s" % (prefix, self.localName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000397 if self.ownerElement:
398 _clear_id_cache(self.ownerElement)
399 d['nodeName'] = d['name'] = newName
400
401 def _set_value(self, value):
402 d = self.__dict__
403 d['value'] = d['nodeValue'] = value
404 if self.ownerElement:
405 _clear_id_cache(self.ownerElement)
406 self.childNodes[0].data = value
407
408 def unlink(self):
409 # This implementation does not call the base implementation
410 # since most of that is not needed, and the expense of the
411 # method call is not warranted. We duplicate the removal of
412 # children, but that's all we needed from the base class.
413 elem = self.ownerElement
414 if elem is not None:
415 del elem._attrs[self.nodeName]
416 del elem._attrsNS[(self.namespaceURI, self.localName)]
417 if self._is_id:
418 self._is_id = False
419 elem._magic_id_nodes -= 1
420 self.ownerDocument._magic_id_count -= 1
421 for child in self.childNodes:
422 child.unlink()
423 del self.childNodes[:]
424
425 def _get_isId(self):
426 if self._is_id:
427 return True
428 doc = self.ownerDocument
429 elem = self.ownerElement
430 if doc is None or elem is None:
431 return False
432
433 info = doc._get_elem_info(elem)
434 if info is None:
435 return False
436 if self.namespaceURI:
437 return info.isIdNS(self.namespaceURI, self.localName)
438 else:
439 return info.isId(self.nodeName)
440
441 def _get_schemaType(self):
442 doc = self.ownerDocument
443 elem = self.ownerElement
444 if doc is None or elem is None:
445 return _no_type
446
447 info = doc._get_elem_info(elem)
448 if info is None:
449 return _no_type
450 if self.namespaceURI:
451 return info.getAttributeTypeNS(self.namespaceURI, self.localName)
452 else:
453 return info.getAttributeType(self.nodeName)
454
455defproperty(Attr, "isId", doc="True if this attribute is an ID.")
456defproperty(Attr, "localName", doc="Namespace-local name of this attribute.")
457defproperty(Attr, "schemaType", doc="Schema type for this attribute.")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000458
Fred Drakef7cf40d2000-12-14 18:16:11 +0000459
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000460class NamedNodeMap(object):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000461 """The attribute list is a transient interface to the underlying
462 dictionaries. Mutations here will change the underlying element's
Fred Drakef7cf40d2000-12-14 18:16:11 +0000463 dictionary.
464
465 Ordering is imposed artificially and does not reflect the order of
466 attributes as found in an input document.
467 """
Fred Drake4ccf4a12000-11-21 22:02:22 +0000468
Martin v. Löwis787354c2003-01-25 15:28:29 +0000469 __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
470
Fred Drake2998a552001-12-06 18:27:48 +0000471 def __init__(self, attrs, attrsNS, ownerElement):
Fred Drake1f549022000-09-24 05:21:58 +0000472 self._attrs = attrs
473 self._attrsNS = attrsNS
Fred Drake2998a552001-12-06 18:27:48 +0000474 self._ownerElement = ownerElement
Fred Drakef7cf40d2000-12-14 18:16:11 +0000475
Martin v. Löwis787354c2003-01-25 15:28:29 +0000476 def _get_length(self):
477 return len(self._attrs)
Fred Drake55c38192000-06-29 19:39:57 +0000478
Fred Drake1f549022000-09-24 05:21:58 +0000479 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000480 try:
Brett Cannon861fd6f2007-02-21 22:05:37 +0000481 return self[list(self._attrs.keys())[index]]
Fred Drake55c38192000-06-29 19:39:57 +0000482 except IndexError:
483 return None
Fred Drake55c38192000-06-29 19:39:57 +0000484
Fred Drake1f549022000-09-24 05:21:58 +0000485 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000486 L = []
487 for node in self._attrs.values():
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000488 L.append((node.nodeName, node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000489 return L
Fred Drake1f549022000-09-24 05:21:58 +0000490
491 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000492 L = []
493 for node in self._attrs.values():
Fred Drake49a5d032001-11-30 22:21:58 +0000494 L.append(((node.namespaceURI, node.localName), node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000495 return L
Fred Drake16f63292000-10-23 18:09:50 +0000496
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000497 def __contains__(self, key):
Christian Heimesc9543e42007-11-28 08:28:28 +0000498 if isinstance(key, str):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000499 return key in self._attrs
Martin v. Löwis787354c2003-01-25 15:28:29 +0000500 else:
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000501 return key in self._attrsNS
Martin v. Löwis787354c2003-01-25 15:28:29 +0000502
Fred Drake1f549022000-09-24 05:21:58 +0000503 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000504 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000505
Fred Drake1f549022000-09-24 05:21:58 +0000506 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000507 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000508
Fred Drake1f549022000-09-24 05:21:58 +0000509 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000510 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000511
Martin v. Löwis787354c2003-01-25 15:28:29 +0000512 def get(self, name, value=None):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000513 return self._attrs.get(name, value)
514
Martin v. Löwis787354c2003-01-25 15:28:29 +0000515 __len__ = _get_length
Fred Drake55c38192000-06-29 19:39:57 +0000516
Mark Dickinsona56c4672009-01-27 18:17:45 +0000517 def _cmp(self, other):
Fred Drake1f549022000-09-24 05:21:58 +0000518 if self._attrs is getattr(other, "_attrs", None):
Fred Drake55c38192000-06-29 19:39:57 +0000519 return 0
Fred Drake16f63292000-10-23 18:09:50 +0000520 else:
Mark Dickinsona56c4672009-01-27 18:17:45 +0000521 return (id(self) > id(other)) - (id(self) < id(other))
522
523 def __eq__(self, other):
524 return self._cmp(other) == 0
525
526 def __ge__(self, other):
527 return self._cmp(other) >= 0
528
529 def __gt__(self, other):
530 return self._cmp(other) > 0
531
532 def __le__(self, other):
533 return self._cmp(other) <= 0
534
535 def __lt__(self, other):
536 return self._cmp(other) < 0
537
538 def __ne__(self, other):
539 return self._cmp(other) != 0
Fred Drake55c38192000-06-29 19:39:57 +0000540
Fred Drake1f549022000-09-24 05:21:58 +0000541 def __getitem__(self, attname_or_tuple):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000542 if isinstance(attname_or_tuple, tuple):
Paul Prescod73678da2000-07-01 04:58:47 +0000543 return self._attrsNS[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000544 else:
Paul Prescod73678da2000-07-01 04:58:47 +0000545 return self._attrs[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000546
Paul Prescod1e688272000-07-01 19:21:47 +0000547 # same as set
Fred Drake1f549022000-09-24 05:21:58 +0000548 def __setitem__(self, attname, value):
Christian Heimesc9543e42007-11-28 08:28:28 +0000549 if isinstance(value, str):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000550 try:
551 node = self._attrs[attname]
552 except KeyError:
553 node = Attr(attname)
554 node.ownerDocument = self._ownerElement.ownerDocument
Martin v. Löwis995359c2003-01-26 08:59:32 +0000555 self.setNamedItem(node)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000556 node.value = value
Paul Prescod1e688272000-07-01 19:21:47 +0000557 else:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000558 if not isinstance(value, Attr):
Collin Winter70e79802007-08-24 18:57:22 +0000559 raise TypeError("value must be a string or Attr object")
Fred Drake1f549022000-09-24 05:21:58 +0000560 node = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000561 self.setNamedItem(node)
562
563 def getNamedItem(self, name):
564 try:
565 return self._attrs[name]
566 except KeyError:
567 return None
568
569 def getNamedItemNS(self, namespaceURI, localName):
570 try:
571 return self._attrsNS[(namespaceURI, localName)]
572 except KeyError:
573 return None
574
575 def removeNamedItem(self, name):
576 n = self.getNamedItem(name)
577 if n is not None:
578 _clear_id_cache(self._ownerElement)
579 del self._attrs[n.nodeName]
580 del self._attrsNS[(n.namespaceURI, n.localName)]
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000581 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000582 n.__dict__['ownerElement'] = None
583 return n
584 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000585 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000586
587 def removeNamedItemNS(self, namespaceURI, localName):
588 n = self.getNamedItemNS(namespaceURI, localName)
589 if n is not None:
590 _clear_id_cache(self._ownerElement)
591 del self._attrsNS[(n.namespaceURI, n.localName)]
592 del self._attrs[n.nodeName]
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000593 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000594 n.__dict__['ownerElement'] = None
595 return n
596 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000597 raise xml.dom.NotFoundErr()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000598
599 def setNamedItem(self, node):
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000600 if not isinstance(node, Attr):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000601 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000602 "%s cannot be child of %s" % (repr(node), repr(self)))
Fred Drakef7cf40d2000-12-14 18:16:11 +0000603 old = self._attrs.get(node.name)
Paul Prescod1e688272000-07-01 19:21:47 +0000604 if old:
605 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000606 self._attrs[node.name] = node
607 self._attrsNS[(node.namespaceURI, node.localName)] = node
Fred Drake2998a552001-12-06 18:27:48 +0000608 node.ownerElement = self._ownerElement
Martin v. Löwis787354c2003-01-25 15:28:29 +0000609 _clear_id_cache(node.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000610 return old
611
612 def setNamedItemNS(self, node):
613 return self.setNamedItem(node)
Paul Prescod73678da2000-07-01 04:58:47 +0000614
Fred Drake1f549022000-09-24 05:21:58 +0000615 def __delitem__(self, attname_or_tuple):
616 node = self[attname_or_tuple]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000617 _clear_id_cache(node.ownerElement)
Paul Prescod73678da2000-07-01 04:58:47 +0000618 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000619
620 def __getstate__(self):
621 return self._attrs, self._attrsNS, self._ownerElement
622
623 def __setstate__(self, state):
624 self._attrs, self._attrsNS, self._ownerElement = state
625
626defproperty(NamedNodeMap, "length",
627 doc="Number of nodes in the NamedNodeMap.")
Fred Drakef7cf40d2000-12-14 18:16:11 +0000628
629AttributeList = NamedNodeMap
630
Fred Drake1f549022000-09-24 05:21:58 +0000631
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000632class TypeInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000633 __slots__ = 'namespace', 'name'
634
635 def __init__(self, namespace, name):
636 self.namespace = namespace
637 self.name = name
638
639 def __repr__(self):
640 if self.namespace:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000641 return "<TypeInfo %r (from %r)>" % (self.name, self.namespace)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000642 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000643 return "<TypeInfo %r>" % self.name
Martin v. Löwis787354c2003-01-25 15:28:29 +0000644
645 def _get_name(self):
646 return self.name
647
648 def _get_namespace(self):
649 return self.namespace
650
651_no_type = TypeInfo(None, None)
652
Martin v. Löwisa2fda0d2000-10-07 12:10:28 +0000653class Element(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000654 nodeType = Node.ELEMENT_NODE
Martin v. Löwis787354c2003-01-25 15:28:29 +0000655 nodeValue = None
656 schemaType = _no_type
657
658 _magic_id_nodes = 0
659
660 _child_node_types = (Node.ELEMENT_NODE,
661 Node.PROCESSING_INSTRUCTION_NODE,
662 Node.COMMENT_NODE,
663 Node.TEXT_NODE,
664 Node.CDATA_SECTION_NODE,
665 Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000666
Fred Drake49a5d032001-11-30 22:21:58 +0000667 def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
Fred Drake1f549022000-09-24 05:21:58 +0000668 localName=None):
Fred Drake55c38192000-06-29 19:39:57 +0000669 self.tagName = self.nodeName = tagName
Fred Drake1f549022000-09-24 05:21:58 +0000670 self.prefix = prefix
671 self.namespaceURI = namespaceURI
Martin v. Löwis787354c2003-01-25 15:28:29 +0000672 self.childNodes = NodeList()
Fred Drake55c38192000-06-29 19:39:57 +0000673
Fred Drake4ccf4a12000-11-21 22:02:22 +0000674 self._attrs = {} # attributes are double-indexed:
675 self._attrsNS = {} # tagName -> Attribute
676 # URI,localName -> Attribute
677 # in the future: consider lazy generation
678 # of attribute objects this is too tricky
679 # for now because of headaches with
680 # namespaces.
681
Martin v. Löwis787354c2003-01-25 15:28:29 +0000682 def _get_localName(self):
Alex Martelli0ee43512006-08-21 19:53:20 +0000683 if 'localName' in self.__dict__:
Guido van Rossum3e1f85e2007-07-27 18:03:11 +0000684 return self.__dict__['localName']
Martin v. Löwis787354c2003-01-25 15:28:29 +0000685 return self.tagName.split(":", 1)[-1]
686
687 def _get_tagName(self):
688 return self.tagName
Fred Drake4ccf4a12000-11-21 22:02:22 +0000689
690 def unlink(self):
Brett Cannon861fd6f2007-02-21 22:05:37 +0000691 for attr in list(self._attrs.values()):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000692 attr.unlink()
693 self._attrs = None
694 self._attrsNS = None
695 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000696
Fred Drake1f549022000-09-24 05:21:58 +0000697 def getAttribute(self, attname):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000698 try:
699 return self._attrs[attname].value
700 except KeyError:
701 return ""
Fred Drake55c38192000-06-29 19:39:57 +0000702
Fred Drake1f549022000-09-24 05:21:58 +0000703 def getAttributeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000704 try:
705 return self._attrsNS[(namespaceURI, localName)].value
706 except KeyError:
707 return ""
Fred Drake1f549022000-09-24 05:21:58 +0000708
709 def setAttribute(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000710 attr = self.getAttributeNode(attname)
711 if attr is None:
712 attr = Attr(attname)
713 # for performance
714 d = attr.__dict__
715 d["value"] = d["nodeValue"] = value
716 d["ownerDocument"] = self.ownerDocument
717 self.setAttributeNode(attr)
718 elif value != attr.value:
719 d = attr.__dict__
720 d["value"] = d["nodeValue"] = value
721 if attr.isId:
722 _clear_id_cache(self)
Fred Drake55c38192000-06-29 19:39:57 +0000723
Fred Drake1f549022000-09-24 05:21:58 +0000724 def setAttributeNS(self, namespaceURI, qualifiedName, value):
725 prefix, localname = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000726 attr = self.getAttributeNodeNS(namespaceURI, localname)
727 if attr is None:
728 # for performance
729 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
730 d = attr.__dict__
731 d["prefix"] = prefix
732 d["nodeName"] = qualifiedName
733 d["value"] = d["nodeValue"] = value
734 d["ownerDocument"] = self.ownerDocument
735 self.setAttributeNode(attr)
736 else:
737 d = attr.__dict__
738 if value != attr.value:
739 d["value"] = d["nodeValue"] = value
740 if attr.isId:
741 _clear_id_cache(self)
742 if attr.prefix != prefix:
743 d["prefix"] = prefix
744 d["nodeName"] = qualifiedName
Fred Drake55c38192000-06-29 19:39:57 +0000745
Fred Drake1f549022000-09-24 05:21:58 +0000746 def getAttributeNode(self, attrname):
747 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000748
Fred Drake1f549022000-09-24 05:21:58 +0000749 def getAttributeNodeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000750 return self._attrsNS.get((namespaceURI, localName))
Paul Prescod73678da2000-07-01 04:58:47 +0000751
Fred Drake1f549022000-09-24 05:21:58 +0000752 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000753 if attr.ownerElement not in (None, self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000754 raise xml.dom.InuseAttributeErr("attribute node already owned")
Martin v. Löwis787354c2003-01-25 15:28:29 +0000755 old1 = self._attrs.get(attr.name, None)
756 if old1 is not None:
757 self.removeAttributeNode(old1)
758 old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
759 if old2 is not None and old2 is not old1:
760 self.removeAttributeNode(old2)
761 _set_attribute_node(self, attr)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000762
Martin v. Löwis787354c2003-01-25 15:28:29 +0000763 if old1 is not attr:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000764 # It might have already been part of this node, in which case
765 # it doesn't represent a change, and should not be returned.
Martin v. Löwis787354c2003-01-25 15:28:29 +0000766 return old1
767 if old2 is not attr:
768 return old2
Fred Drake55c38192000-06-29 19:39:57 +0000769
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000770 setAttributeNodeNS = setAttributeNode
771
Fred Drake1f549022000-09-24 05:21:58 +0000772 def removeAttribute(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000773 try:
774 attr = self._attrs[name]
775 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000776 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000777 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000778
Fred Drake1f549022000-09-24 05:21:58 +0000779 def removeAttributeNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000780 try:
781 attr = self._attrsNS[(namespaceURI, localName)]
782 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000783 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000784 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000785
Fred Drake1f549022000-09-24 05:21:58 +0000786 def removeAttributeNode(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000787 if node is None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000788 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000789 try:
790 self._attrs[node.name]
791 except KeyError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000792 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000793 _clear_id_cache(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000794 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000795 # Restore this since the node is still useful and otherwise
796 # unlinked
797 node.ownerDocument = self.ownerDocument
Fred Drake16f63292000-10-23 18:09:50 +0000798
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000799 removeAttributeNodeNS = removeAttributeNode
800
Martin v. Löwis156c3372000-12-28 18:40:56 +0000801 def hasAttribute(self, name):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000802 return name in self._attrs
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000803
Martin v. Löwis156c3372000-12-28 18:40:56 +0000804 def hasAttributeNS(self, namespaceURI, localName):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000805 return (namespaceURI, localName) in self._attrsNS
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000806
Fred Drake1f549022000-09-24 05:21:58 +0000807 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000808 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000809
Fred Drake1f549022000-09-24 05:21:58 +0000810 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000811 return _get_elements_by_tagName_ns_helper(
812 self, namespaceURI, localName, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000813
Fred Drake1f549022000-09-24 05:21:58 +0000814 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000815 return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000816
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000817 def writexml(self, writer, indent="", addindent="", newl=""):
818 # indent = current indentation
819 # addindent = indentation to add to higher levels
820 # newl = newline string
821 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000822
Fred Drake4ccf4a12000-11-21 22:02:22 +0000823 attrs = self._get_attributes()
Brett Cannon861fd6f2007-02-21 22:05:37 +0000824 a_names = sorted(attrs.keys())
Fred Drake55c38192000-06-29 19:39:57 +0000825
826 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000827 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000828 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000829 writer.write("\"")
830 if self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000831 writer.write(">%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000832 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000833 node.writexml(writer,indent+addindent,addindent,newl)
834 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
Fred Drake55c38192000-06-29 19:39:57 +0000835 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000836 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000837
Fred Drake1f549022000-09-24 05:21:58 +0000838 def _get_attributes(self):
Fred Drake2998a552001-12-06 18:27:48 +0000839 return NamedNodeMap(self._attrs, self._attrsNS, self)
Fred Drake55c38192000-06-29 19:39:57 +0000840
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000841 def hasAttributes(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000842 if self._attrs:
843 return True
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000844 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000845 return False
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000846
Martin v. Löwis787354c2003-01-25 15:28:29 +0000847 # DOM Level 3 attributes, based on the 22 Oct 2002 draft
848
849 def setIdAttribute(self, name):
850 idAttr = self.getAttributeNode(name)
851 self.setIdAttributeNode(idAttr)
852
853 def setIdAttributeNS(self, namespaceURI, localName):
854 idAttr = self.getAttributeNodeNS(namespaceURI, localName)
855 self.setIdAttributeNode(idAttr)
856
857 def setIdAttributeNode(self, idAttr):
858 if idAttr is None or not self.isSameNode(idAttr.ownerElement):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000859 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000860 if _get_containing_entref(self) is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000861 raise xml.dom.NoModificationAllowedErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000862 if not idAttr._is_id:
863 idAttr.__dict__['_is_id'] = True
864 self._magic_id_nodes += 1
865 self.ownerDocument._magic_id_count += 1
866 _clear_id_cache(self)
867
868defproperty(Element, "attributes",
869 doc="NamedNodeMap of attributes on the element.")
870defproperty(Element, "localName",
871 doc="Namespace-local name of this element.")
872
873
874def _set_attribute_node(element, attr):
875 _clear_id_cache(element)
876 element._attrs[attr.name] = attr
877 element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
878
879 # This creates a circular reference, but Element.unlink()
880 # breaks the cycle since the references to the attribute
881 # dictionaries are tossed.
882 attr.__dict__['ownerElement'] = element
883
884
885class Childless:
886 """Mixin that makes childless-ness easy to implement and avoids
887 the complexity of the Node methods that deal with children.
888 """
889
Fred Drake4ccf4a12000-11-21 22:02:22 +0000890 attributes = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000891 childNodes = EmptyNodeList()
892 firstChild = None
893 lastChild = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000894
Martin v. Löwis787354c2003-01-25 15:28:29 +0000895 def _get_firstChild(self):
896 return None
Fred Drake55c38192000-06-29 19:39:57 +0000897
Martin v. Löwis787354c2003-01-25 15:28:29 +0000898 def _get_lastChild(self):
899 return None
Fred Drake1f549022000-09-24 05:21:58 +0000900
Martin v. Löwis787354c2003-01-25 15:28:29 +0000901 def appendChild(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000902 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000903 self.nodeName + " nodes cannot have children")
904
905 def hasChildNodes(self):
906 return False
907
908 def insertBefore(self, newChild, refChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000909 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000910 self.nodeName + " nodes do not have children")
911
912 def removeChild(self, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000913 raise xml.dom.NotFoundErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000914 self.nodeName + " nodes do not have children")
915
916 def replaceChild(self, newChild, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000917 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000918 self.nodeName + " nodes do not have children")
919
920
921class ProcessingInstruction(Childless, Node):
Fred Drake1f549022000-09-24 05:21:58 +0000922 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000923
Fred Drake1f549022000-09-24 05:21:58 +0000924 def __init__(self, target, data):
Fred Drake55c38192000-06-29 19:39:57 +0000925 self.target = self.nodeName = target
926 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000927
Martin v. Löwis787354c2003-01-25 15:28:29 +0000928 def _get_data(self):
929 return self.data
930 def _set_data(self, value):
931 d = self.__dict__
932 d['data'] = d['nodeValue'] = value
933
934 def _get_target(self):
935 return self.target
936 def _set_target(self, value):
937 d = self.__dict__
938 d['target'] = d['nodeName'] = value
939
940 def __setattr__(self, name, value):
941 if name == "data" or name == "nodeValue":
942 self.__dict__['data'] = self.__dict__['nodeValue'] = value
943 elif name == "target" or name == "nodeName":
944 self.__dict__['target'] = self.__dict__['nodeName'] = value
945 else:
946 self.__dict__[name] = value
947
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000948 def writexml(self, writer, indent="", addindent="", newl=""):
949 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000950
Martin v. Löwis787354c2003-01-25 15:28:29 +0000951
952class CharacterData(Childless, Node):
953 def _get_length(self):
954 return len(self.data)
955 __len__ = _get_length
956
957 def _get_data(self):
958 return self.__dict__['data']
959 def _set_data(self, data):
960 d = self.__dict__
961 d['data'] = d['nodeValue'] = data
962
963 _get_nodeValue = _get_data
964 _set_nodeValue = _set_data
965
966 def __setattr__(self, name, value):
967 if name == "data" or name == "nodeValue":
968 self.__dict__['data'] = self.__dict__['nodeValue'] = value
969 else:
970 self.__dict__[name] = value
Fred Drake87432f42001-04-04 14:09:46 +0000971
Fred Drake55c38192000-06-29 19:39:57 +0000972 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000973 data = self.data
974 if len(data) > 10:
Fred Drake1f549022000-09-24 05:21:58 +0000975 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000976 else:
Fred Drake1f549022000-09-24 05:21:58 +0000977 dotdotdot = ""
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000978 return '<DOM %s node "%r%s">' % (
Martin v. Löwis787354c2003-01-25 15:28:29 +0000979 self.__class__.__name__, data[0:10], dotdotdot)
Fred Drake87432f42001-04-04 14:09:46 +0000980
981 def substringData(self, offset, count):
982 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000983 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000984 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000985 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000986 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000987 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000988 return self.data[offset:offset+count]
989
990 def appendData(self, arg):
991 self.data = self.data + arg
Fred Drake87432f42001-04-04 14:09:46 +0000992
993 def insertData(self, offset, arg):
994 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000995 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000996 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000997 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000998 if arg:
999 self.data = "%s%s%s" % (
1000 self.data[:offset], arg, self.data[offset:])
Fred Drake87432f42001-04-04 14:09:46 +00001001
1002 def deleteData(self, offset, count):
1003 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001004 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001005 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001006 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +00001007 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001008 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001009 if count:
1010 self.data = self.data[:offset] + self.data[offset+count:]
Fred Drake87432f42001-04-04 14:09:46 +00001011
1012 def replaceData(self, offset, count, arg):
1013 if offset < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001014 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001015 if offset >= len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001016 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +00001017 if count < 0:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001018 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001019 if count:
1020 self.data = "%s%s%s" % (
1021 self.data[:offset], arg, self.data[offset+count:])
Martin v. Löwis787354c2003-01-25 15:28:29 +00001022
1023defproperty(CharacterData, "length", doc="Length of the string data.")
1024
Fred Drake87432f42001-04-04 14:09:46 +00001025
1026class Text(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001027 # Make sure we don't add an instance __dict__ if we don't already
1028 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001029 # XXX this does not work, CharacterData is an old-style class
1030 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001031
Fred Drake87432f42001-04-04 14:09:46 +00001032 nodeType = Node.TEXT_NODE
1033 nodeName = "#text"
1034 attributes = None
Fred Drake55c38192000-06-29 19:39:57 +00001035
Fred Drakef7cf40d2000-12-14 18:16:11 +00001036 def splitText(self, offset):
1037 if offset < 0 or offset > len(self.data):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001038 raise xml.dom.IndexSizeErr("illegal offset value")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001039 newText = self.__class__()
1040 newText.data = self.data[offset:]
1041 newText.ownerDocument = self.ownerDocument
Fred Drakef7cf40d2000-12-14 18:16:11 +00001042 next = self.nextSibling
1043 if self.parentNode and self in self.parentNode.childNodes:
1044 if next is None:
1045 self.parentNode.appendChild(newText)
1046 else:
1047 self.parentNode.insertBefore(newText, next)
1048 self.data = self.data[:offset]
1049 return newText
1050
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001051 def writexml(self, writer, indent="", addindent="", newl=""):
1052 _write_data(writer, "%s%s%s"%(indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001053
Martin v. Löwis787354c2003-01-25 15:28:29 +00001054 # DOM Level 3 (WD 9 April 2002)
1055
1056 def _get_wholeText(self):
1057 L = [self.data]
1058 n = self.previousSibling
1059 while n is not None:
1060 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1061 L.insert(0, n.data)
1062 n = n.previousSibling
1063 else:
1064 break
1065 n = self.nextSibling
1066 while n is not None:
1067 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1068 L.append(n.data)
1069 n = n.nextSibling
1070 else:
1071 break
1072 return ''.join(L)
1073
1074 def replaceWholeText(self, content):
1075 # XXX This needs to be seriously changed if minidom ever
1076 # supports EntityReference nodes.
1077 parent = self.parentNode
1078 n = self.previousSibling
1079 while n is not None:
1080 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1081 next = n.previousSibling
1082 parent.removeChild(n)
1083 n = next
1084 else:
1085 break
1086 n = self.nextSibling
1087 if not content:
1088 parent.removeChild(self)
1089 while n is not None:
1090 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1091 next = n.nextSibling
1092 parent.removeChild(n)
1093 n = next
1094 else:
1095 break
1096 if content:
1097 d = self.__dict__
1098 d['data'] = content
1099 d['nodeValue'] = content
1100 return self
1101 else:
1102 return None
1103
1104 def _get_isWhitespaceInElementContent(self):
1105 if self.data.strip():
1106 return False
1107 elem = _get_containing_element(self)
1108 if elem is None:
1109 return False
1110 info = self.ownerDocument._get_elem_info(elem)
1111 if info is None:
1112 return False
1113 else:
1114 return info.isElementContent()
1115
1116defproperty(Text, "isWhitespaceInElementContent",
1117 doc="True iff this text node contains only whitespace"
1118 " and is in element content.")
1119defproperty(Text, "wholeText",
1120 doc="The text of all logically-adjacent text nodes.")
1121
1122
1123def _get_containing_element(node):
1124 c = node.parentNode
1125 while c is not None:
1126 if c.nodeType == Node.ELEMENT_NODE:
1127 return c
1128 c = c.parentNode
1129 return None
1130
1131def _get_containing_entref(node):
1132 c = node.parentNode
1133 while c is not None:
1134 if c.nodeType == Node.ENTITY_REFERENCE_NODE:
1135 return c
1136 c = c.parentNode
1137 return None
1138
1139
Alex Martelli0ee43512006-08-21 19:53:20 +00001140class Comment(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001141 nodeType = Node.COMMENT_NODE
1142 nodeName = "#comment"
1143
1144 def __init__(self, data):
1145 self.data = self.nodeValue = data
1146
1147 def writexml(self, writer, indent="", addindent="", newl=""):
Benjamin Peterson2b7411d2008-05-26 17:36:47 +00001148 if "--" in self.data:
1149 raise ValueError("'--' is not allowed in a comment node")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001150 writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
1151
Fred Drake87432f42001-04-04 14:09:46 +00001152
1153class CDATASection(Text):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001154 # Make sure we don't add an instance __dict__ if we don't already
1155 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001156 # XXX this does not work, Text is an old-style class
1157 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001158
Fred Drake87432f42001-04-04 14:09:46 +00001159 nodeType = Node.CDATA_SECTION_NODE
1160 nodeName = "#cdata-section"
1161
1162 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001163 if self.data.find("]]>") >= 0:
1164 raise ValueError("']]>' not allowed in a CDATA section")
Guido van Rossum5b5e0b92001-09-19 13:28:25 +00001165 writer.write("<![CDATA[%s]]>" % self.data)
Fred Drake87432f42001-04-04 14:09:46 +00001166
1167
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001168class ReadOnlySequentialNamedNodeMap(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001169 __slots__ = '_seq',
1170
1171 def __init__(self, seq=()):
1172 # seq should be a list or tuple
1173 self._seq = seq
1174
1175 def __len__(self):
1176 return len(self._seq)
1177
1178 def _get_length(self):
1179 return len(self._seq)
1180
1181 def getNamedItem(self, name):
1182 for n in self._seq:
1183 if n.nodeName == name:
1184 return n
1185
1186 def getNamedItemNS(self, namespaceURI, localName):
1187 for n in self._seq:
1188 if n.namespaceURI == namespaceURI and n.localName == localName:
1189 return n
1190
1191 def __getitem__(self, name_or_tuple):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001192 if isinstance(name_or_tuple, tuple):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001193 node = self.getNamedItemNS(*name_or_tuple)
1194 else:
1195 node = self.getNamedItem(name_or_tuple)
1196 if node is None:
Collin Winter70e79802007-08-24 18:57:22 +00001197 raise KeyError(name_or_tuple)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001198 return node
1199
1200 def item(self, index):
1201 if index < 0:
1202 return None
1203 try:
1204 return self._seq[index]
1205 except IndexError:
1206 return None
1207
1208 def removeNamedItem(self, name):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001209 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001210 "NamedNodeMap instance is read-only")
1211
1212 def removeNamedItemNS(self, namespaceURI, localName):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001213 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001214 "NamedNodeMap instance is read-only")
1215
1216 def setNamedItem(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001217 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001218 "NamedNodeMap instance is read-only")
1219
1220 def setNamedItemNS(self, node):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001221 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001222 "NamedNodeMap instance is read-only")
1223
1224 def __getstate__(self):
1225 return [self._seq]
1226
1227 def __setstate__(self, state):
1228 self._seq = state[0]
1229
1230defproperty(ReadOnlySequentialNamedNodeMap, "length",
1231 doc="Number of entries in the NamedNodeMap.")
Paul Prescod73678da2000-07-01 04:58:47 +00001232
Fred Drakef7cf40d2000-12-14 18:16:11 +00001233
Martin v. Löwis787354c2003-01-25 15:28:29 +00001234class Identified:
1235 """Mix-in class that supports the publicId and systemId attributes."""
1236
Martin v. Löwis995359c2003-01-26 08:59:32 +00001237 # XXX this does not work, this is an old-style class
1238 # __slots__ = 'publicId', 'systemId'
Martin v. Löwis787354c2003-01-25 15:28:29 +00001239
1240 def _identified_mixin_init(self, publicId, systemId):
1241 self.publicId = publicId
1242 self.systemId = systemId
1243
1244 def _get_publicId(self):
1245 return self.publicId
1246
1247 def _get_systemId(self):
1248 return self.systemId
1249
1250class DocumentType(Identified, Childless, Node):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001251 nodeType = Node.DOCUMENT_TYPE_NODE
1252 nodeValue = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001253 name = None
1254 publicId = None
1255 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +00001256 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001257
1258 def __init__(self, qualifiedName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001259 self.entities = ReadOnlySequentialNamedNodeMap()
1260 self.notations = ReadOnlySequentialNamedNodeMap()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001261 if qualifiedName:
1262 prefix, localname = _nssplit(qualifiedName)
1263 self.name = localname
Martin v. Löwis787354c2003-01-25 15:28:29 +00001264 self.nodeName = self.name
1265
1266 def _get_internalSubset(self):
1267 return self.internalSubset
1268
1269 def cloneNode(self, deep):
1270 if self.ownerDocument is None:
1271 # it's ok
1272 clone = DocumentType(None)
1273 clone.name = self.name
1274 clone.nodeName = self.name
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001275 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001276 if deep:
1277 clone.entities._seq = []
1278 clone.notations._seq = []
1279 for n in self.notations._seq:
1280 notation = Notation(n.nodeName, n.publicId, n.systemId)
1281 clone.notations._seq.append(notation)
1282 n._call_user_data_handler(operation, n, notation)
1283 for e in self.entities._seq:
1284 entity = Entity(e.nodeName, e.publicId, e.systemId,
1285 e.notationName)
1286 entity.actualEncoding = e.actualEncoding
1287 entity.encoding = e.encoding
1288 entity.version = e.version
1289 clone.entities._seq.append(entity)
1290 e._call_user_data_handler(operation, n, entity)
1291 self._call_user_data_handler(operation, self, clone)
1292 return clone
1293 else:
1294 return None
1295
1296 def writexml(self, writer, indent="", addindent="", newl=""):
1297 writer.write("<!DOCTYPE ")
1298 writer.write(self.name)
1299 if self.publicId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001300 writer.write("%s PUBLIC '%s'%s '%s'"
1301 % (newl, self.publicId, newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001302 elif self.systemId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001303 writer.write("%s SYSTEM '%s'" % (newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001304 if self.internalSubset is not None:
1305 writer.write(" [")
1306 writer.write(self.internalSubset)
1307 writer.write("]")
Georg Brandl175a7dc2005-08-25 22:02:43 +00001308 writer.write(">"+newl)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001309
1310class Entity(Identified, Node):
1311 attributes = None
1312 nodeType = Node.ENTITY_NODE
1313 nodeValue = None
1314
1315 actualEncoding = None
1316 encoding = None
1317 version = None
1318
1319 def __init__(self, name, publicId, systemId, notation):
1320 self.nodeName = name
1321 self.notationName = notation
1322 self.childNodes = NodeList()
1323 self._identified_mixin_init(publicId, systemId)
1324
1325 def _get_actualEncoding(self):
1326 return self.actualEncoding
1327
1328 def _get_encoding(self):
1329 return self.encoding
1330
1331 def _get_version(self):
1332 return self.version
1333
1334 def appendChild(self, newChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001335 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001336 "cannot append children to an entity node")
1337
1338 def insertBefore(self, newChild, refChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001339 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001340 "cannot insert children below an entity node")
1341
1342 def removeChild(self, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001343 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001344 "cannot remove children from an entity node")
1345
1346 def replaceChild(self, newChild, oldChild):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001347 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001348 "cannot replace children of an entity node")
1349
1350class Notation(Identified, Childless, Node):
1351 nodeType = Node.NOTATION_NODE
1352 nodeValue = None
1353
1354 def __init__(self, name, publicId, systemId):
1355 self.nodeName = name
1356 self._identified_mixin_init(publicId, systemId)
Fred Drakef7cf40d2000-12-14 18:16:11 +00001357
1358
Martin v. Löwis787354c2003-01-25 15:28:29 +00001359class DOMImplementation(DOMImplementationLS):
1360 _features = [("core", "1.0"),
1361 ("core", "2.0"),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001362 ("core", None),
1363 ("xml", "1.0"),
1364 ("xml", "2.0"),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001365 ("xml", None),
1366 ("ls-load", "3.0"),
1367 ("ls-load", None),
1368 ]
1369
Fred Drakef7cf40d2000-12-14 18:16:11 +00001370 def hasFeature(self, feature, version):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001371 if version == "":
1372 version = None
1373 return (feature.lower(), version) in self._features
Fred Drakef7cf40d2000-12-14 18:16:11 +00001374
1375 def createDocument(self, namespaceURI, qualifiedName, doctype):
1376 if doctype and doctype.parentNode is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001377 raise xml.dom.WrongDocumentErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001378 "doctype object owned by another DOM tree")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001379 doc = self._create_document()
1380
1381 add_root_element = not (namespaceURI is None
1382 and qualifiedName is None
1383 and doctype is None)
1384
1385 if not qualifiedName and add_root_element:
Martin v. Löwisb417be22001-02-06 01:16:06 +00001386 # The spec is unclear what to raise here; SyntaxErr
1387 # would be the other obvious candidate. Since Xerces raises
1388 # InvalidCharacterErr, and since SyntaxErr is not listed
1389 # for createDocument, that seems to be the better choice.
1390 # XXX: need to check for illegal characters here and in
1391 # createElement.
Martin v. Löwis787354c2003-01-25 15:28:29 +00001392
1393 # DOM Level III clears this up when talking about the return value
1394 # of this function. If namespaceURI, qName and DocType are
1395 # Null the document is returned without a document element
1396 # Otherwise if doctype or namespaceURI are not None
1397 # Then we go back to the above problem
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001398 raise xml.dom.InvalidCharacterErr("Element with no name")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001399
1400 if add_root_element:
1401 prefix, localname = _nssplit(qualifiedName)
1402 if prefix == "xml" \
1403 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001404 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001405 if prefix and not namespaceURI:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001406 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001407 "illegal use of prefix without namespaces")
1408 element = doc.createElementNS(namespaceURI, qualifiedName)
1409 if doctype:
1410 doc.appendChild(doctype)
1411 doc.appendChild(element)
1412
1413 if doctype:
1414 doctype.parentNode = doctype.ownerDocument = doc
1415
Fred Drakef7cf40d2000-12-14 18:16:11 +00001416 doc.doctype = doctype
1417 doc.implementation = self
1418 return doc
1419
1420 def createDocumentType(self, qualifiedName, publicId, systemId):
1421 doctype = DocumentType(qualifiedName)
1422 doctype.publicId = publicId
1423 doctype.systemId = systemId
1424 return doctype
1425
Martin v. Löwis787354c2003-01-25 15:28:29 +00001426 # DOM Level 3 (WD 9 April 2002)
1427
1428 def getInterface(self, feature):
1429 if self.hasFeature(feature, None):
1430 return self
1431 else:
1432 return None
1433
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001434 # internal
Martin v. Löwis787354c2003-01-25 15:28:29 +00001435 def _create_document(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001436 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001437
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001438class ElementInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001439 """Object that represents content-model information for an element.
1440
1441 This implementation is not expected to be used in practice; DOM
1442 builders should provide implementations which do the right thing
1443 using information available to it.
1444
1445 """
1446
1447 __slots__ = 'tagName',
1448
1449 def __init__(self, name):
1450 self.tagName = name
1451
1452 def getAttributeType(self, aname):
1453 return _no_type
1454
1455 def getAttributeTypeNS(self, namespaceURI, localName):
1456 return _no_type
1457
1458 def isElementContent(self):
1459 return False
1460
1461 def isEmpty(self):
1462 """Returns true iff this element is declared to have an EMPTY
1463 content model."""
1464 return False
1465
1466 def isId(self, aname):
Ezio Melotti42da6632011-03-15 05:18:48 +02001467 """Returns true iff the named attribute is a DTD-style ID."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001468 return False
1469
1470 def isIdNS(self, namespaceURI, localName):
1471 """Returns true iff the identified attribute is a DTD-style ID."""
1472 return False
1473
1474 def __getstate__(self):
1475 return self.tagName
1476
1477 def __setstate__(self, state):
1478 self.tagName = state
1479
1480def _clear_id_cache(node):
1481 if node.nodeType == Node.DOCUMENT_NODE:
1482 node._id_cache.clear()
1483 node._id_search_stack = None
1484 elif _in_document(node):
1485 node.ownerDocument._id_cache.clear()
1486 node.ownerDocument._id_search_stack= None
1487
1488class Document(Node, DocumentLS):
1489 _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
1490 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
1491
Fred Drake1f549022000-09-24 05:21:58 +00001492 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +00001493 nodeName = "#document"
1494 nodeValue = None
1495 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001496 doctype = None
1497 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001498 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001499
1500 implementation = DOMImplementation()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001501
1502 # Document attributes from Level 3 (WD 9 April 2002)
1503
1504 actualEncoding = None
1505 encoding = None
1506 standalone = None
1507 version = None
1508 strictErrorChecking = False
1509 errorHandler = None
1510 documentURI = None
1511
1512 _magic_id_count = 0
1513
1514 def __init__(self):
1515 self.childNodes = NodeList()
1516 # mapping of (namespaceURI, localName) -> ElementInfo
1517 # and tagName -> ElementInfo
1518 self._elem_info = {}
1519 self._id_cache = {}
1520 self._id_search_stack = None
1521
1522 def _get_elem_info(self, element):
1523 if element.namespaceURI:
1524 key = element.namespaceURI, element.localName
1525 else:
1526 key = element.tagName
1527 return self._elem_info.get(key)
1528
1529 def _get_actualEncoding(self):
1530 return self.actualEncoding
1531
1532 def _get_doctype(self):
1533 return self.doctype
1534
1535 def _get_documentURI(self):
1536 return self.documentURI
1537
1538 def _get_encoding(self):
1539 return self.encoding
1540
1541 def _get_errorHandler(self):
1542 return self.errorHandler
1543
1544 def _get_standalone(self):
1545 return self.standalone
1546
1547 def _get_strictErrorChecking(self):
1548 return self.strictErrorChecking
1549
1550 def _get_version(self):
1551 return self.version
Fred Drake55c38192000-06-29 19:39:57 +00001552
Fred Drake1f549022000-09-24 05:21:58 +00001553 def appendChild(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001554 if node.nodeType not in self._child_node_types:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001555 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001556 "%s cannot be child of %s" % (repr(node), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001557 if node.parentNode is not None:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001558 # This needs to be done before the next test since this
1559 # may *be* the document element, in which case it should
1560 # end up re-ordered to the end.
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001561 node.parentNode.removeChild(node)
1562
Fred Drakef7cf40d2000-12-14 18:16:11 +00001563 if node.nodeType == Node.ELEMENT_NODE \
1564 and self._get_documentElement():
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001565 raise xml.dom.HierarchyRequestErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001566 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +00001567 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +00001568
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001569 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001570 try:
1571 self.childNodes.remove(oldChild)
1572 except ValueError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001573 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001574 oldChild.nextSibling = oldChild.previousSibling = None
1575 oldChild.parentNode = None
1576 if self.documentElement is oldChild:
1577 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +00001578
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001579 return oldChild
1580
Fred Drakef7cf40d2000-12-14 18:16:11 +00001581 def _get_documentElement(self):
1582 for node in self.childNodes:
1583 if node.nodeType == Node.ELEMENT_NODE:
1584 return node
1585
1586 def unlink(self):
1587 if self.doctype is not None:
1588 self.doctype.unlink()
1589 self.doctype = None
1590 Node.unlink(self)
1591
Martin v. Löwis787354c2003-01-25 15:28:29 +00001592 def cloneNode(self, deep):
1593 if not deep:
1594 return None
1595 clone = self.implementation.createDocument(None, None, None)
1596 clone.encoding = self.encoding
1597 clone.standalone = self.standalone
1598 clone.version = self.version
1599 for n in self.childNodes:
1600 childclone = _clone_node(n, deep, clone)
1601 assert childclone.ownerDocument.isSameNode(clone)
1602 clone.childNodes.append(childclone)
1603 if childclone.nodeType == Node.DOCUMENT_NODE:
1604 assert clone.documentElement is None
1605 elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
1606 assert clone.doctype is None
1607 clone.doctype = childclone
1608 childclone.parentNode = clone
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001609 self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
Martin v. Löwis787354c2003-01-25 15:28:29 +00001610 self, clone)
1611 return clone
1612
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001613 def createDocumentFragment(self):
1614 d = DocumentFragment()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001615 d.ownerDocument = self
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001616 return d
Fred Drake55c38192000-06-29 19:39:57 +00001617
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001618 def createElement(self, tagName):
1619 e = Element(tagName)
1620 e.ownerDocument = self
1621 return e
Fred Drake55c38192000-06-29 19:39:57 +00001622
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001623 def createTextNode(self, data):
Christian Heimesc9543e42007-11-28 08:28:28 +00001624 if not isinstance(data, str):
Collin Winter70e79802007-08-24 18:57:22 +00001625 raise TypeError("node contents must be a string")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001626 t = Text()
1627 t.data = data
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001628 t.ownerDocument = self
1629 return t
Fred Drake55c38192000-06-29 19:39:57 +00001630
Fred Drake87432f42001-04-04 14:09:46 +00001631 def createCDATASection(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 c = CDATASection()
1635 c.data = data
Fred Drake87432f42001-04-04 14:09:46 +00001636 c.ownerDocument = self
1637 return c
1638
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001639 def createComment(self, data):
1640 c = Comment(data)
1641 c.ownerDocument = self
1642 return c
Fred Drake55c38192000-06-29 19:39:57 +00001643
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001644 def createProcessingInstruction(self, target, data):
1645 p = ProcessingInstruction(target, data)
1646 p.ownerDocument = self
1647 return p
1648
1649 def createAttribute(self, qName):
1650 a = Attr(qName)
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
1655 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001656 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001657 e = Element(qualifiedName, namespaceURI, prefix)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001658 e.ownerDocument = self
1659 return e
Fred Drake55c38192000-06-29 19:39:57 +00001660
1661 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001662 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001663 a = Attr(qualifiedName, namespaceURI, localName, prefix)
1664 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001665 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001666 return a
Fred Drake55c38192000-06-29 19:39:57 +00001667
Martin v. Löwis787354c2003-01-25 15:28:29 +00001668 # A couple of implementation-specific helpers to create node types
1669 # not supported by the W3C DOM specs:
1670
1671 def _create_entity(self, name, publicId, systemId, notationName):
1672 e = Entity(name, publicId, systemId, notationName)
1673 e.ownerDocument = self
1674 return e
1675
1676 def _create_notation(self, name, publicId, systemId):
1677 n = Notation(name, publicId, systemId)
1678 n.ownerDocument = self
1679 return n
1680
1681 def getElementById(self, id):
Guido van Rossum1b01e5c2006-08-19 02:45:06 +00001682 if id in self._id_cache:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001683 return self._id_cache[id]
1684 if not (self._elem_info or self._magic_id_count):
1685 return None
1686
1687 stack = self._id_search_stack
1688 if stack is None:
1689 # we never searched before, or the cache has been cleared
1690 stack = [self.documentElement]
1691 self._id_search_stack = stack
1692 elif not stack:
1693 # Previous search was completed and cache is still valid;
1694 # no matching node.
1695 return None
1696
1697 result = None
1698 while stack:
1699 node = stack.pop()
1700 # add child elements to stack for continued searching
1701 stack.extend([child for child in node.childNodes
1702 if child.nodeType in _nodeTypes_with_children])
1703 # check this node
1704 info = self._get_elem_info(node)
1705 if info:
1706 # We have to process all ID attributes before
1707 # returning in order to get all the attributes set to
1708 # be IDs using Element.setIdAttribute*().
1709 for attr in node.attributes.values():
1710 if attr.namespaceURI:
1711 if info.isIdNS(attr.namespaceURI, attr.localName):
1712 self._id_cache[attr.value] = node
1713 if attr.value == id:
1714 result = node
1715 elif not node._magic_id_nodes:
1716 break
1717 elif info.isId(attr.name):
1718 self._id_cache[attr.value] = node
1719 if attr.value == id:
1720 result = node
1721 elif not node._magic_id_nodes:
1722 break
1723 elif attr._is_id:
1724 self._id_cache[attr.value] = node
1725 if attr.value == id:
1726 result = node
1727 elif node._magic_id_nodes == 1:
1728 break
1729 elif node._magic_id_nodes:
1730 for attr in node.attributes.values():
1731 if attr._is_id:
1732 self._id_cache[attr.value] = node
1733 if attr.value == id:
1734 result = node
1735 if result is not None:
1736 break
1737 return result
1738
Fred Drake1f549022000-09-24 05:21:58 +00001739 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001740 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drakefbe7b4f2001-07-04 06:25:53 +00001741
1742 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001743 return _get_elements_by_tagName_ns_helper(
1744 self, namespaceURI, localName, NodeList())
1745
1746 def isSupported(self, feature, version):
1747 return self.implementation.hasFeature(feature, version)
1748
1749 def importNode(self, node, deep):
1750 if node.nodeType == Node.DOCUMENT_NODE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001751 raise xml.dom.NotSupportedErr("cannot import document nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001752 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001753 raise xml.dom.NotSupportedErr("cannot import document type nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001754 return _clone_node(node, deep, self)
Fred Drake55c38192000-06-29 19:39:57 +00001755
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001756 def writexml(self, writer, indent="", addindent="", newl="",
1757 encoding = None):
1758 if encoding is None:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001759 writer.write('<?xml version="1.0" ?>'+newl)
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001760 else:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001761 writer.write('<?xml version="1.0" encoding="%s"?>%s' % (encoding, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001762 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001763 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +00001764
Martin v. Löwis787354c2003-01-25 15:28:29 +00001765 # DOM Level 3 (WD 9 April 2002)
1766
1767 def renameNode(self, n, namespaceURI, name):
1768 if n.ownerDocument is not self:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001769 raise xml.dom.WrongDocumentErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001770 "cannot rename nodes from other documents;\n"
1771 "expected %s,\nfound %s" % (self, n.ownerDocument))
1772 if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001773 raise xml.dom.NotSupportedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001774 "renameNode() only applies to element and attribute nodes")
1775 if namespaceURI != EMPTY_NAMESPACE:
1776 if ':' in name:
1777 prefix, localName = name.split(':', 1)
1778 if ( prefix == "xmlns"
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001779 and namespaceURI != xml.dom.XMLNS_NAMESPACE):
1780 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001781 "illegal use of 'xmlns' prefix")
1782 else:
1783 if ( name == "xmlns"
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001784 and namespaceURI != xml.dom.XMLNS_NAMESPACE
Martin v. Löwis787354c2003-01-25 15:28:29 +00001785 and n.nodeType == Node.ATTRIBUTE_NODE):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001786 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001787 "illegal use of the 'xmlns' attribute")
1788 prefix = None
1789 localName = name
1790 else:
1791 prefix = None
1792 localName = None
1793 if n.nodeType == Node.ATTRIBUTE_NODE:
1794 element = n.ownerElement
1795 if element is not None:
1796 is_id = n._is_id
1797 element.removeAttributeNode(n)
1798 else:
1799 element = None
1800 # avoid __setattr__
1801 d = n.__dict__
1802 d['prefix'] = prefix
1803 d['localName'] = localName
1804 d['namespaceURI'] = namespaceURI
1805 d['nodeName'] = name
1806 if n.nodeType == Node.ELEMENT_NODE:
1807 d['tagName'] = name
1808 else:
1809 # attribute node
1810 d['name'] = name
1811 if element is not None:
1812 element.setAttributeNode(n)
1813 if is_id:
1814 element.setIdAttributeNode(n)
1815 # It's not clear from a semantic perspective whether we should
1816 # call the user data handlers for the NODE_RENAMED event since
1817 # we're re-using the existing node. The draft spec has been
1818 # interpreted as meaning "no, don't call the handler unless a
1819 # new node is created."
1820 return n
1821
1822defproperty(Document, "documentElement",
1823 doc="Top-level element of this document.")
1824
1825
1826def _clone_node(node, deep, newOwnerDocument):
1827 """
1828 Clone a node and give it the new owner document.
1829 Called by Node.cloneNode and Document.importNode
1830 """
1831 if node.ownerDocument.isSameNode(newOwnerDocument):
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001832 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001833 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001834 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001835 if node.nodeType == Node.ELEMENT_NODE:
1836 clone = newOwnerDocument.createElementNS(node.namespaceURI,
1837 node.nodeName)
1838 for attr in node.attributes.values():
1839 clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
1840 a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
1841 a.specified = attr.specified
1842
1843 if deep:
1844 for child in node.childNodes:
1845 c = _clone_node(child, deep, newOwnerDocument)
1846 clone.appendChild(c)
1847
1848 elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
1849 clone = newOwnerDocument.createDocumentFragment()
1850 if deep:
1851 for child in node.childNodes:
1852 c = _clone_node(child, deep, newOwnerDocument)
1853 clone.appendChild(c)
1854
1855 elif node.nodeType == Node.TEXT_NODE:
1856 clone = newOwnerDocument.createTextNode(node.data)
1857 elif node.nodeType == Node.CDATA_SECTION_NODE:
1858 clone = newOwnerDocument.createCDATASection(node.data)
1859 elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
1860 clone = newOwnerDocument.createProcessingInstruction(node.target,
1861 node.data)
1862 elif node.nodeType == Node.COMMENT_NODE:
1863 clone = newOwnerDocument.createComment(node.data)
1864 elif node.nodeType == Node.ATTRIBUTE_NODE:
1865 clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
1866 node.nodeName)
1867 clone.specified = True
1868 clone.value = node.value
1869 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
1870 assert node.ownerDocument is not newOwnerDocument
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001871 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001872 clone = newOwnerDocument.implementation.createDocumentType(
1873 node.name, node.publicId, node.systemId)
1874 clone.ownerDocument = newOwnerDocument
1875 if deep:
1876 clone.entities._seq = []
1877 clone.notations._seq = []
1878 for n in node.notations._seq:
1879 notation = Notation(n.nodeName, n.publicId, n.systemId)
1880 notation.ownerDocument = newOwnerDocument
1881 clone.notations._seq.append(notation)
1882 if hasattr(n, '_call_user_data_handler'):
1883 n._call_user_data_handler(operation, n, notation)
1884 for e in node.entities._seq:
1885 entity = Entity(e.nodeName, e.publicId, e.systemId,
1886 e.notationName)
1887 entity.actualEncoding = e.actualEncoding
1888 entity.encoding = e.encoding
1889 entity.version = e.version
1890 entity.ownerDocument = newOwnerDocument
1891 clone.entities._seq.append(entity)
1892 if hasattr(e, '_call_user_data_handler'):
1893 e._call_user_data_handler(operation, n, entity)
1894 else:
1895 # Note the cloning of Document and DocumentType nodes is
1896 # implemenetation specific. minidom handles those cases
1897 # directly in the cloneNode() methods.
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001898 raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001899
1900 # Check for _call_user_data_handler() since this could conceivably
1901 # used with other DOM implementations (one of the FourThought
1902 # DOMs, perhaps?).
1903 if hasattr(node, '_call_user_data_handler'):
1904 node._call_user_data_handler(operation, node, clone)
1905 return clone
1906
1907
1908def _nssplit(qualifiedName):
1909 fields = qualifiedName.split(':', 1)
1910 if len(fields) == 2:
1911 return fields
1912 else:
1913 return (None, fields[0])
1914
1915
Martin v. Löwis787354c2003-01-25 15:28:29 +00001916def _do_pulldom_parse(func, args, kwargs):
Raymond Hettingerff41c482003-04-06 09:01:11 +00001917 events = func(*args, **kwargs)
Fred Drake1f549022000-09-24 05:21:58 +00001918 toktype, rootNode = events.getEvent()
1919 events.expandNode(rootNode)
Martin v. Löwisb417be22001-02-06 01:16:06 +00001920 events.clear()
Fred Drake55c38192000-06-29 19:39:57 +00001921 return rootNode
1922
Martin v. Löwis787354c2003-01-25 15:28:29 +00001923def parse(file, parser=None, bufsize=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001924 """Parse a file into a DOM by filename or file object."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001925 if parser is None and not bufsize:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001926 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001927 return expatbuilder.parse(file)
1928 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001929 from xml.dom import pulldom
Raymond Hettingerff41c482003-04-06 09:01:11 +00001930 return _do_pulldom_parse(pulldom.parse, (file,),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001931 {'parser': parser, 'bufsize': bufsize})
Fred Drake55c38192000-06-29 19:39:57 +00001932
Martin v. Löwis787354c2003-01-25 15:28:29 +00001933def parseString(string, parser=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001934 """Parse a file into a DOM from a string."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001935 if parser is None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001936 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001937 return expatbuilder.parseString(string)
1938 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001939 from xml.dom import pulldom
Martin v. Löwis787354c2003-01-25 15:28:29 +00001940 return _do_pulldom_parse(pulldom.parseString, (string,),
1941 {'parser': parser})
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001942
Martin v. Löwis787354c2003-01-25 15:28:29 +00001943def getDOMImplementation(features=None):
1944 if features:
Christian Heimesc9543e42007-11-28 08:28:28 +00001945 if isinstance(features, str):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001946 features = domreg._parse_feature_string(features)
1947 for f, v in features:
1948 if not Document.implementation.hasFeature(f, v):
1949 return None
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001950 return Document.implementation