blob: f8ed232fb2e16af1763fae97c55bc5933086dc0f [file] [log] [blame]
Ezio Melottif5da3ec2013-01-22 22:47:57 +02001"""Simple implementation of the Level 1 DOM.
2
3Namespaces and other minor Level 2 features are also supported.
Fred Drake55c38192000-06-29 19:39:57 +00004
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00005parse("foo.xml")
Paul Prescod623511b2000-07-21 22:05:49 +00006
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00007parseString("<foo><bar/></foo>")
Paul Prescod623511b2000-07-21 22:05:49 +00008
Fred Drake55c38192000-06-29 19:39:57 +00009Todo:
10=====
11 * convenience methods for getting elements and text.
12 * more testing
13 * bring some of the writer and linearizer code into conformance with this
14 interface
15 * SAX 2 namespaces
16"""
17
Fred Drakefbdeaad2006-07-29 16:56:15 +000018import xml.dom
Fred Drake55c38192000-06-29 19:39:57 +000019
Fred Drakefbdeaad2006-07-29 16:56:15 +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#
Fred Drakefbdeaad2006-07-29 16:56:15 +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
Fred Drakefbdeaad2006-07-29 16:56:15 +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
Fred Drake1f549022000-09-24 05:21:58 +000042 def __nonzero__(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
Martin v. Löwis7d650ca2002-06-30 15:05:00 +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
51 writer = _get_StringIO()
Martin v. Löwis7d650ca2002-06-30 15:05:00 +000052 if encoding is not None:
53 import codecs
54 # Can't use codecs.getwriter to preserve 2.0 compatibility
55 writer = codecs.lookup(encoding)[3](writer)
56 if self.nodeType == Node.DOCUMENT_NODE:
57 # Can pass encoding only to document, to put it into XML header
58 self.writexml(writer, "", indent, newl, encoding)
59 else:
60 self.writexml(writer, "", indent, newl)
Martin v. Löwiscb67ea12001-03-31 16:30:40 +000061 return writer.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:
Fred Drakefbdeaad2006-07-29 16:56:15 +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:
Fred Drakefbdeaad2006-07-29 16:56:15 +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:
Fred Drakefbdeaad2006-07-29 16:56:15 +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:
Fred Drakefbdeaad2006-07-29 16:56:15 +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:
Fred Drakefbdeaad2006-07-29 16:56:15 +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:
Fred Drakefbdeaad2006-07-29 16:56:15 +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:
R. David Murray0374a822009-04-09 21:54:50 +0000181 if not child.data:
182 # empty text node; discard
183 if L:
184 L[-1].nextSibling = child.nextSibling
185 if child.nextSibling:
186 child.nextSibling.previousSibling = child.previousSibling
187 child.unlink()
188 elif L and L[-1].nodeType == child.nodeType:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000189 # collapse text node
190 node = L[-1]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000191 node.data = node.data + child.data
Fred Drake4ccf4a12000-11-21 22:02:22 +0000192 node.nextSibling = child.nextSibling
R. David Murray0374a822009-04-09 21:54:50 +0000193 if child.nextSibling:
194 child.nextSibling.previousSibling = node
Fred Drake4ccf4a12000-11-21 22:02:22 +0000195 child.unlink()
R. David Murray0374a822009-04-09 21:54:50 +0000196 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000197 L.append(child)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000198 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000199 L.append(child)
200 if child.nodeType == Node.ELEMENT_NODE:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000201 child.normalize()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000202 self.childNodes[:] = L
Paul Prescod73678da2000-07-01 04:58:47 +0000203
Fred Drake1f549022000-09-24 05:21:58 +0000204 def cloneNode(self, deep):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000205 return _clone_node(self, deep, self.ownerDocument or self)
Fred Drake55c38192000-06-29 19:39:57 +0000206
Martin v. Löwis787354c2003-01-25 15:28:29 +0000207 def isSupported(self, feature, version):
208 return self.ownerDocument.implementation.hasFeature(feature, version)
209
210 def _get_localName(self):
211 # Overridden in Element and Attr where localName can be Non-Null
212 return None
213
214 # Node interfaces from Level 3 (WD 9 April 2002)
Fred Drake25239772001-02-02 19:40:19 +0000215
216 def isSameNode(self, other):
217 return self is other
218
Martin v. Löwis787354c2003-01-25 15:28:29 +0000219 def getInterface(self, feature):
220 if self.isSupported(feature, None):
221 return self
222 else:
223 return None
224
225 # The "user data" functions use a dictionary that is only present
226 # if some user data has been set, so be careful not to assume it
227 # exists.
228
229 def getUserData(self, key):
230 try:
231 return self._user_data[key][0]
232 except (AttributeError, KeyError):
233 return None
234
235 def setUserData(self, key, data, handler):
236 old = None
237 try:
238 d = self._user_data
239 except AttributeError:
240 d = {}
241 self._user_data = d
Brett Cannon5dd504d2008-08-04 00:23:58 +0000242 if key in d:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000243 old = d[key][0]
244 if data is None:
245 # ignore handlers passed for None
246 handler = None
247 if old is not None:
248 del d[key]
249 else:
250 d[key] = (data, handler)
251 return old
252
253 def _call_user_data_handler(self, operation, src, dst):
254 if hasattr(self, "_user_data"):
255 for key, (data, handler) in self._user_data.items():
256 if handler is not None:
257 handler.handle(operation, key, data, src, dst)
258
Fred Drake25239772001-02-02 19:40:19 +0000259 # minidom-specific API:
260
Fred Drake1f549022000-09-24 05:21:58 +0000261 def unlink(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000262 self.parentNode = self.ownerDocument = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000263 if self.childNodes:
264 for child in self.childNodes:
265 child.unlink()
266 self.childNodes = NodeList()
Paul Prescod4221ff02000-10-13 20:11:42 +0000267 self.previousSibling = None
268 self.nextSibling = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000269
270defproperty(Node, "firstChild", doc="First child node, or None.")
271defproperty(Node, "lastChild", doc="Last child node, or None.")
272defproperty(Node, "localName", doc="Namespace-local name of this node.")
273
274
275def _append_child(self, node):
276 # fast path with less checks; usable by DOM builders if careful
277 childNodes = self.childNodes
278 if childNodes:
279 last = childNodes[-1]
280 node.__dict__["previousSibling"] = last
281 last.__dict__["nextSibling"] = node
282 childNodes.append(node)
283 node.__dict__["parentNode"] = self
284
285def _in_document(node):
286 # return True iff node is part of a document tree
287 while node is not None:
288 if node.nodeType == Node.DOCUMENT_NODE:
289 return True
290 node = node.parentNode
291 return False
Fred Drake55c38192000-06-29 19:39:57 +0000292
Fred Drake1f549022000-09-24 05:21:58 +0000293def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000294 "Writes datachars to writer."
Georg Brandl5ded7912010-11-26 07:35:31 +0000295 if data:
296 data = data.replace("&", "&amp;").replace("<", "&lt;"). \
297 replace("\"", "&quot;").replace(">", "&gt;")
298 writer.write(data)
Fred Drake55c38192000-06-29 19:39:57 +0000299
Martin v. Löwis787354c2003-01-25 15:28:29 +0000300def _get_elements_by_tagName_helper(parent, name, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000301 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000302 if node.nodeType == Node.ELEMENT_NODE and \
303 (name == "*" or node.tagName == name):
304 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000305 _get_elements_by_tagName_helper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000306 return rc
307
Martin v. Löwis787354c2003-01-25 15:28:29 +0000308def _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000309 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000310 if node.nodeType == Node.ELEMENT_NODE:
Martin v. Löwised525fb2001-06-03 14:06:42 +0000311 if ((localName == "*" or node.localName == localName) and
Fred Drake1f549022000-09-24 05:21:58 +0000312 (nsURI == "*" or node.namespaceURI == nsURI)):
313 rc.append(node)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000314 _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000315 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000316
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000317class DocumentFragment(Node):
318 nodeType = Node.DOCUMENT_FRAGMENT_NODE
319 nodeName = "#document-fragment"
320 nodeValue = None
321 attributes = None
322 parentNode = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000323 _child_node_types = (Node.ELEMENT_NODE,
324 Node.TEXT_NODE,
325 Node.CDATA_SECTION_NODE,
326 Node.ENTITY_REFERENCE_NODE,
327 Node.PROCESSING_INSTRUCTION_NODE,
328 Node.COMMENT_NODE,
329 Node.NOTATION_NODE)
330
331 def __init__(self):
332 self.childNodes = NodeList()
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000333
334
Fred Drake55c38192000-06-29 19:39:57 +0000335class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000336 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000337 attributes = None
338 ownerElement = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000339 specified = False
340 _is_id = False
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000341
Martin v. Löwis787354c2003-01-25 15:28:29 +0000342 _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
343
344 def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
345 prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000346 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000347 d = self.__dict__
Fred Drake4ccf4a12000-11-21 22:02:22 +0000348 d["nodeName"] = d["name"] = qName
349 d["namespaceURI"] = namespaceURI
350 d["prefix"] = prefix
Martin v. Löwis787354c2003-01-25 15:28:29 +0000351 d['childNodes'] = NodeList()
352
353 # Add the single child node that represents the value of the attr
354 self.childNodes.append(Text())
355
Paul Prescod73678da2000-07-01 04:58:47 +0000356 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000357
Martin v. Löwis787354c2003-01-25 15:28:29 +0000358 def _get_localName(self):
359 return self.nodeName.split(":", 1)[-1]
360
361 def _get_name(self):
362 return self.name
363
364 def _get_specified(self):
365 return self.specified
366
Fred Drake1f549022000-09-24 05:21:58 +0000367 def __setattr__(self, name, value):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000368 d = self.__dict__
Fred Drake1f549022000-09-24 05:21:58 +0000369 if name in ("value", "nodeValue"):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000370 d["value"] = d["nodeValue"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000371 d2 = self.childNodes[0].__dict__
372 d2["data"] = d2["nodeValue"] = value
373 if self.ownerElement is not None:
374 _clear_id_cache(self.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000375 elif name in ("name", "nodeName"):
376 d["name"] = d["nodeName"] = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000377 if self.ownerElement is not None:
378 _clear_id_cache(self.ownerElement)
Fred Drake55c38192000-06-29 19:39:57 +0000379 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000380 d[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000381
Martin v. Löwis995359c2003-01-26 08:59:32 +0000382 def _set_prefix(self, prefix):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000383 nsuri = self.namespaceURI
Martin v. Löwis995359c2003-01-26 08:59:32 +0000384 if prefix == "xmlns":
385 if nsuri and nsuri != XMLNS_NAMESPACE:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000386 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000387 "illegal use of 'xmlns' prefix for the wrong namespace")
388 d = self.__dict__
389 d['prefix'] = prefix
390 if prefix is None:
391 newName = self.localName
392 else:
Martin v. Löwis995359c2003-01-26 08:59:32 +0000393 newName = "%s:%s" % (prefix, self.localName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000394 if self.ownerElement:
395 _clear_id_cache(self.ownerElement)
396 d['nodeName'] = d['name'] = newName
397
398 def _set_value(self, value):
399 d = self.__dict__
400 d['value'] = d['nodeValue'] = value
401 if self.ownerElement:
402 _clear_id_cache(self.ownerElement)
403 self.childNodes[0].data = value
404
405 def unlink(self):
406 # This implementation does not call the base implementation
407 # since most of that is not needed, and the expense of the
408 # method call is not warranted. We duplicate the removal of
409 # children, but that's all we needed from the base class.
410 elem = self.ownerElement
411 if elem is not None:
412 del elem._attrs[self.nodeName]
413 del elem._attrsNS[(self.namespaceURI, self.localName)]
414 if self._is_id:
415 self._is_id = False
416 elem._magic_id_nodes -= 1
417 self.ownerDocument._magic_id_count -= 1
418 for child in self.childNodes:
419 child.unlink()
420 del self.childNodes[:]
421
422 def _get_isId(self):
423 if self._is_id:
424 return True
425 doc = self.ownerDocument
426 elem = self.ownerElement
427 if doc is None or elem is None:
428 return False
429
430 info = doc._get_elem_info(elem)
431 if info is None:
432 return False
433 if self.namespaceURI:
434 return info.isIdNS(self.namespaceURI, self.localName)
435 else:
436 return info.isId(self.nodeName)
437
438 def _get_schemaType(self):
439 doc = self.ownerDocument
440 elem = self.ownerElement
441 if doc is None or elem is None:
442 return _no_type
443
444 info = doc._get_elem_info(elem)
445 if info is None:
446 return _no_type
447 if self.namespaceURI:
448 return info.getAttributeTypeNS(self.namespaceURI, self.localName)
449 else:
450 return info.getAttributeType(self.nodeName)
451
452defproperty(Attr, "isId", doc="True if this attribute is an ID.")
453defproperty(Attr, "localName", doc="Namespace-local name of this attribute.")
454defproperty(Attr, "schemaType", doc="Schema type for this attribute.")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000455
Fred Drakef7cf40d2000-12-14 18:16:11 +0000456
Fred Drake9ea179f2006-04-06 01:29:04 +0000457class NamedNodeMap(object):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000458 """The attribute list is a transient interface to the underlying
459 dictionaries. Mutations here will change the underlying element's
Fred Drakef7cf40d2000-12-14 18:16:11 +0000460 dictionary.
461
462 Ordering is imposed artificially and does not reflect the order of
463 attributes as found in an input document.
464 """
Fred Drake4ccf4a12000-11-21 22:02:22 +0000465
Martin v. Löwis787354c2003-01-25 15:28:29 +0000466 __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
467
Fred Drake2998a552001-12-06 18:27:48 +0000468 def __init__(self, attrs, attrsNS, ownerElement):
Fred Drake1f549022000-09-24 05:21:58 +0000469 self._attrs = attrs
470 self._attrsNS = attrsNS
Fred Drake2998a552001-12-06 18:27:48 +0000471 self._ownerElement = ownerElement
Fred Drakef7cf40d2000-12-14 18:16:11 +0000472
Martin v. Löwis787354c2003-01-25 15:28:29 +0000473 def _get_length(self):
474 return len(self._attrs)
Fred Drake55c38192000-06-29 19:39:57 +0000475
Fred Drake1f549022000-09-24 05:21:58 +0000476 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000477 try:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000478 return self[self._attrs.keys()[index]]
Fred Drake55c38192000-06-29 19:39:57 +0000479 except IndexError:
480 return None
Fred Drake55c38192000-06-29 19:39:57 +0000481
Fred Drake1f549022000-09-24 05:21:58 +0000482 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000483 L = []
484 for node in self._attrs.values():
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000485 L.append((node.nodeName, node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000486 return L
Fred Drake1f549022000-09-24 05:21:58 +0000487
488 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000489 L = []
490 for node in self._attrs.values():
Fred Drake49a5d032001-11-30 22:21:58 +0000491 L.append(((node.namespaceURI, node.localName), node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000492 return L
Fred Drake16f63292000-10-23 18:09:50 +0000493
Martin v. Löwis787354c2003-01-25 15:28:29 +0000494 def has_key(self, key):
495 if isinstance(key, StringTypes):
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000496 return key in self._attrs
Martin v. Löwis787354c2003-01-25 15:28:29 +0000497 else:
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000498 return key in self._attrsNS
Martin v. Löwis787354c2003-01-25 15:28:29 +0000499
Fred Drake1f549022000-09-24 05:21:58 +0000500 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000501 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000502
Fred Drake1f549022000-09-24 05:21:58 +0000503 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000504 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000505
Fred Drake1f549022000-09-24 05:21:58 +0000506 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000507 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000508
Martin v. Löwis787354c2003-01-25 15:28:29 +0000509 def get(self, name, value=None):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000510 return self._attrs.get(name, value)
511
Martin v. Löwis787354c2003-01-25 15:28:29 +0000512 __len__ = _get_length
Fred Drake55c38192000-06-29 19:39:57 +0000513
Nick Coghlan48361f52008-08-11 15:45:58 +0000514 __hash__ = None # Mutable type can't be correctly hashed
Fred Drake1f549022000-09-24 05:21:58 +0000515 def __cmp__(self, other):
516 if self._attrs is getattr(other, "_attrs", None):
Fred Drake55c38192000-06-29 19:39:57 +0000517 return 0
Fred Drake16f63292000-10-23 18:09:50 +0000518 else:
Fred Drake1f549022000-09-24 05:21:58 +0000519 return cmp(id(self), id(other))
Fred Drake55c38192000-06-29 19:39:57 +0000520
Fred Drake1f549022000-09-24 05:21:58 +0000521 def __getitem__(self, attname_or_tuple):
Fred Drake70d044b2006-04-06 01:32:26 +0000522 if isinstance(attname_or_tuple, tuple):
Paul Prescod73678da2000-07-01 04:58:47 +0000523 return self._attrsNS[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000524 else:
Paul Prescod73678da2000-07-01 04:58:47 +0000525 return self._attrs[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000526
Paul Prescod1e688272000-07-01 19:21:47 +0000527 # same as set
Fred Drake1f549022000-09-24 05:21:58 +0000528 def __setitem__(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000529 if isinstance(value, StringTypes):
530 try:
531 node = self._attrs[attname]
532 except KeyError:
533 node = Attr(attname)
534 node.ownerDocument = self._ownerElement.ownerDocument
Martin v. Löwis995359c2003-01-26 08:59:32 +0000535 self.setNamedItem(node)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000536 node.value = value
Paul Prescod1e688272000-07-01 19:21:47 +0000537 else:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000538 if not isinstance(value, Attr):
539 raise TypeError, "value must be a string or Attr object"
Fred Drake1f549022000-09-24 05:21:58 +0000540 node = value
Martin v. Löwis787354c2003-01-25 15:28:29 +0000541 self.setNamedItem(node)
542
543 def getNamedItem(self, name):
544 try:
545 return self._attrs[name]
546 except KeyError:
547 return None
548
549 def getNamedItemNS(self, namespaceURI, localName):
550 try:
551 return self._attrsNS[(namespaceURI, localName)]
552 except KeyError:
553 return None
554
555 def removeNamedItem(self, name):
556 n = self.getNamedItem(name)
557 if n is not None:
558 _clear_id_cache(self._ownerElement)
559 del self._attrs[n.nodeName]
560 del self._attrsNS[(n.namespaceURI, n.localName)]
Brett Cannon5dd504d2008-08-04 00:23:58 +0000561 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000562 n.__dict__['ownerElement'] = None
563 return n
564 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000565 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000566
567 def removeNamedItemNS(self, namespaceURI, localName):
568 n = self.getNamedItemNS(namespaceURI, localName)
569 if n is not None:
570 _clear_id_cache(self._ownerElement)
571 del self._attrsNS[(n.namespaceURI, n.localName)]
572 del self._attrs[n.nodeName]
Brett Cannon5dd504d2008-08-04 00:23:58 +0000573 if 'ownerElement' in n.__dict__:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000574 n.__dict__['ownerElement'] = None
575 return n
576 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000577 raise xml.dom.NotFoundErr()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000578
579 def setNamedItem(self, node):
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000580 if not isinstance(node, Attr):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000581 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000582 "%s cannot be child of %s" % (repr(node), repr(self)))
Fred Drakef7cf40d2000-12-14 18:16:11 +0000583 old = self._attrs.get(node.name)
Paul Prescod1e688272000-07-01 19:21:47 +0000584 if old:
585 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000586 self._attrs[node.name] = node
587 self._attrsNS[(node.namespaceURI, node.localName)] = node
Fred Drake2998a552001-12-06 18:27:48 +0000588 node.ownerElement = self._ownerElement
Martin v. Löwis787354c2003-01-25 15:28:29 +0000589 _clear_id_cache(node.ownerElement)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000590 return old
591
592 def setNamedItemNS(self, node):
593 return self.setNamedItem(node)
Paul Prescod73678da2000-07-01 04:58:47 +0000594
Fred Drake1f549022000-09-24 05:21:58 +0000595 def __delitem__(self, attname_or_tuple):
596 node = self[attname_or_tuple]
Martin v. Löwis787354c2003-01-25 15:28:29 +0000597 _clear_id_cache(node.ownerElement)
Paul Prescod73678da2000-07-01 04:58:47 +0000598 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000599
600 def __getstate__(self):
601 return self._attrs, self._attrsNS, self._ownerElement
602
603 def __setstate__(self, state):
604 self._attrs, self._attrsNS, self._ownerElement = state
605
606defproperty(NamedNodeMap, "length",
607 doc="Number of nodes in the NamedNodeMap.")
Fred Drakef7cf40d2000-12-14 18:16:11 +0000608
609AttributeList = NamedNodeMap
610
Fred Drake1f549022000-09-24 05:21:58 +0000611
Fred Drake9ea179f2006-04-06 01:29:04 +0000612class TypeInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000613 __slots__ = 'namespace', 'name'
614
615 def __init__(self, namespace, name):
616 self.namespace = namespace
617 self.name = name
618
619 def __repr__(self):
620 if self.namespace:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000621 return "<TypeInfo %r (from %r)>" % (self.name, self.namespace)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000622 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000623 return "<TypeInfo %r>" % self.name
Martin v. Löwis787354c2003-01-25 15:28:29 +0000624
625 def _get_name(self):
626 return self.name
627
628 def _get_namespace(self):
629 return self.namespace
630
631_no_type = TypeInfo(None, None)
632
Martin v. Löwisa2fda0d2000-10-07 12:10:28 +0000633class Element(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000634 nodeType = Node.ELEMENT_NODE
Martin v. Löwis787354c2003-01-25 15:28:29 +0000635 nodeValue = None
636 schemaType = _no_type
637
638 _magic_id_nodes = 0
639
640 _child_node_types = (Node.ELEMENT_NODE,
641 Node.PROCESSING_INSTRUCTION_NODE,
642 Node.COMMENT_NODE,
643 Node.TEXT_NODE,
644 Node.CDATA_SECTION_NODE,
645 Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000646
Fred Drake49a5d032001-11-30 22:21:58 +0000647 def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
Fred Drake1f549022000-09-24 05:21:58 +0000648 localName=None):
Fred Drake55c38192000-06-29 19:39:57 +0000649 self.tagName = self.nodeName = tagName
Fred Drake1f549022000-09-24 05:21:58 +0000650 self.prefix = prefix
651 self.namespaceURI = namespaceURI
Martin v. Löwis787354c2003-01-25 15:28:29 +0000652 self.childNodes = NodeList()
Fred Drake55c38192000-06-29 19:39:57 +0000653
Fred Drake4ccf4a12000-11-21 22:02:22 +0000654 self._attrs = {} # attributes are double-indexed:
655 self._attrsNS = {} # tagName -> Attribute
656 # URI,localName -> Attribute
657 # in the future: consider lazy generation
658 # of attribute objects this is too tricky
659 # for now because of headaches with
660 # namespaces.
661
Martin v. Löwis787354c2003-01-25 15:28:29 +0000662 def _get_localName(self):
663 return self.tagName.split(":", 1)[-1]
664
665 def _get_tagName(self):
666 return self.tagName
Fred Drake4ccf4a12000-11-21 22:02:22 +0000667
668 def unlink(self):
669 for attr in self._attrs.values():
670 attr.unlink()
671 self._attrs = None
672 self._attrsNS = None
673 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000674
Fred Drake1f549022000-09-24 05:21:58 +0000675 def getAttribute(self, attname):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000676 try:
677 return self._attrs[attname].value
678 except KeyError:
679 return ""
Fred Drake55c38192000-06-29 19:39:57 +0000680
Fred Drake1f549022000-09-24 05:21:58 +0000681 def getAttributeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000682 try:
683 return self._attrsNS[(namespaceURI, localName)].value
684 except KeyError:
685 return ""
Fred Drake1f549022000-09-24 05:21:58 +0000686
687 def setAttribute(self, attname, value):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000688 attr = self.getAttributeNode(attname)
689 if attr is None:
690 attr = Attr(attname)
691 # for performance
692 d = attr.__dict__
693 d["value"] = d["nodeValue"] = value
694 d["ownerDocument"] = self.ownerDocument
695 self.setAttributeNode(attr)
696 elif value != attr.value:
697 d = attr.__dict__
698 d["value"] = d["nodeValue"] = value
699 if attr.isId:
700 _clear_id_cache(self)
Fred Drake55c38192000-06-29 19:39:57 +0000701
Fred Drake1f549022000-09-24 05:21:58 +0000702 def setAttributeNS(self, namespaceURI, qualifiedName, value):
703 prefix, localname = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +0000704 attr = self.getAttributeNodeNS(namespaceURI, localname)
705 if attr is None:
706 # for performance
707 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
708 d = attr.__dict__
709 d["prefix"] = prefix
710 d["nodeName"] = qualifiedName
711 d["value"] = d["nodeValue"] = value
712 d["ownerDocument"] = self.ownerDocument
713 self.setAttributeNode(attr)
714 else:
715 d = attr.__dict__
716 if value != attr.value:
717 d["value"] = d["nodeValue"] = value
718 if attr.isId:
719 _clear_id_cache(self)
720 if attr.prefix != prefix:
721 d["prefix"] = prefix
722 d["nodeName"] = qualifiedName
Fred Drake55c38192000-06-29 19:39:57 +0000723
Fred Drake1f549022000-09-24 05:21:58 +0000724 def getAttributeNode(self, attrname):
725 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000726
Fred Drake1f549022000-09-24 05:21:58 +0000727 def getAttributeNodeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000728 return self._attrsNS.get((namespaceURI, localName))
Paul Prescod73678da2000-07-01 04:58:47 +0000729
Fred Drake1f549022000-09-24 05:21:58 +0000730 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000731 if attr.ownerElement not in (None, self):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000732 raise xml.dom.InuseAttributeErr("attribute node already owned")
Martin v. Löwis787354c2003-01-25 15:28:29 +0000733 old1 = self._attrs.get(attr.name, None)
734 if old1 is not None:
735 self.removeAttributeNode(old1)
736 old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
737 if old2 is not None and old2 is not old1:
738 self.removeAttributeNode(old2)
739 _set_attribute_node(self, attr)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000740
Martin v. Löwis787354c2003-01-25 15:28:29 +0000741 if old1 is not attr:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000742 # It might have already been part of this node, in which case
743 # it doesn't represent a change, and should not be returned.
Martin v. Löwis787354c2003-01-25 15:28:29 +0000744 return old1
745 if old2 is not attr:
746 return old2
Fred Drake55c38192000-06-29 19:39:57 +0000747
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000748 setAttributeNodeNS = setAttributeNode
749
Fred Drake1f549022000-09-24 05:21:58 +0000750 def removeAttribute(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000751 try:
752 attr = self._attrs[name]
753 except KeyError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000754 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000755 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000756
Fred Drake1f549022000-09-24 05:21:58 +0000757 def removeAttributeNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000758 try:
759 attr = self._attrsNS[(namespaceURI, localName)]
760 except KeyError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000761 raise xml.dom.NotFoundErr()
Fred Drake1f549022000-09-24 05:21:58 +0000762 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000763
Fred Drake1f549022000-09-24 05:21:58 +0000764 def removeAttributeNode(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000765 if node is None:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000766 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000767 try:
768 self._attrs[node.name]
769 except KeyError:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000770 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000771 _clear_id_cache(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000772 node.unlink()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000773 # Restore this since the node is still useful and otherwise
774 # unlinked
775 node.ownerDocument = self.ownerDocument
Fred Drake16f63292000-10-23 18:09:50 +0000776
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000777 removeAttributeNodeNS = removeAttributeNode
778
Martin v. Löwis156c3372000-12-28 18:40:56 +0000779 def hasAttribute(self, name):
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000780 return name in self._attrs
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000781
Martin v. Löwis156c3372000-12-28 18:40:56 +0000782 def hasAttributeNS(self, namespaceURI, localName):
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000783 return (namespaceURI, localName) in self._attrsNS
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000784
Fred Drake1f549022000-09-24 05:21:58 +0000785 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000786 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000787
Fred Drake1f549022000-09-24 05:21:58 +0000788 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000789 return _get_elements_by_tagName_ns_helper(
790 self, namespaceURI, localName, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000791
Fred Drake1f549022000-09-24 05:21:58 +0000792 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000793 return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000794
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000795 def writexml(self, writer, indent="", addindent="", newl=""):
796 # indent = current indentation
797 # addindent = indentation to add to higher levels
798 # newl = newline string
799 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000800
Fred Drake4ccf4a12000-11-21 22:02:22 +0000801 attrs = self._get_attributes()
802 a_names = attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000803 a_names.sort()
804
805 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000806 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000807 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000808 writer.write("\"")
809 if self.childNodes:
R David Murrayc8faf9b2011-10-01 16:49:25 -0400810 writer.write(">")
Ezio Melotti93bbb6a2011-11-18 17:30:28 +0200811 if (len(self.childNodes) == 1 and
812 self.childNodes[0].nodeType == Node.TEXT_NODE):
813 self.childNodes[0].writexml(writer, '', '', '')
814 else:
R David Murrayc8faf9b2011-10-01 16:49:25 -0400815 writer.write(newl)
Ezio Melotti93bbb6a2011-11-18 17:30:28 +0200816 for node in self.childNodes:
817 node.writexml(writer, indent+addindent, addindent, newl)
818 writer.write(indent)
819 writer.write("</%s>%s" % (self.tagName, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000820 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000821 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000822
Fred Drake1f549022000-09-24 05:21:58 +0000823 def _get_attributes(self):
Fred Drake2998a552001-12-06 18:27:48 +0000824 return NamedNodeMap(self._attrs, self._attrsNS, self)
Fred Drake55c38192000-06-29 19:39:57 +0000825
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000826 def hasAttributes(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000827 if self._attrs:
828 return True
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000829 else:
Martin v. Löwis787354c2003-01-25 15:28:29 +0000830 return False
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000831
Martin v. Löwis787354c2003-01-25 15:28:29 +0000832 # DOM Level 3 attributes, based on the 22 Oct 2002 draft
833
834 def setIdAttribute(self, name):
835 idAttr = self.getAttributeNode(name)
836 self.setIdAttributeNode(idAttr)
837
838 def setIdAttributeNS(self, namespaceURI, localName):
839 idAttr = self.getAttributeNodeNS(namespaceURI, localName)
840 self.setIdAttributeNode(idAttr)
841
842 def setIdAttributeNode(self, idAttr):
843 if idAttr is None or not self.isSameNode(idAttr.ownerElement):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000844 raise xml.dom.NotFoundErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000845 if _get_containing_entref(self) is not None:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000846 raise xml.dom.NoModificationAllowedErr()
Martin v. Löwis787354c2003-01-25 15:28:29 +0000847 if not idAttr._is_id:
848 idAttr.__dict__['_is_id'] = True
849 self._magic_id_nodes += 1
850 self.ownerDocument._magic_id_count += 1
851 _clear_id_cache(self)
852
853defproperty(Element, "attributes",
854 doc="NamedNodeMap of attributes on the element.")
855defproperty(Element, "localName",
856 doc="Namespace-local name of this element.")
857
858
859def _set_attribute_node(element, attr):
860 _clear_id_cache(element)
861 element._attrs[attr.name] = attr
862 element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
863
864 # This creates a circular reference, but Element.unlink()
865 # breaks the cycle since the references to the attribute
866 # dictionaries are tossed.
867 attr.__dict__['ownerElement'] = element
868
869
870class Childless:
871 """Mixin that makes childless-ness easy to implement and avoids
872 the complexity of the Node methods that deal with children.
873 """
874
Fred Drake4ccf4a12000-11-21 22:02:22 +0000875 attributes = None
Martin v. Löwis787354c2003-01-25 15:28:29 +0000876 childNodes = EmptyNodeList()
877 firstChild = None
878 lastChild = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000879
Martin v. Löwis787354c2003-01-25 15:28:29 +0000880 def _get_firstChild(self):
881 return None
Fred Drake55c38192000-06-29 19:39:57 +0000882
Martin v. Löwis787354c2003-01-25 15:28:29 +0000883 def _get_lastChild(self):
884 return None
Fred Drake1f549022000-09-24 05:21:58 +0000885
Martin v. Löwis787354c2003-01-25 15:28:29 +0000886 def appendChild(self, node):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000887 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000888 self.nodeName + " nodes cannot have children")
889
890 def hasChildNodes(self):
891 return False
892
893 def insertBefore(self, newChild, refChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000894 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000895 self.nodeName + " nodes do not have children")
896
897 def removeChild(self, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000898 raise xml.dom.NotFoundErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000899 self.nodeName + " nodes do not have children")
900
Andrew M. Kuchling53f94d02010-07-25 23:49:57 +0000901 def normalize(self):
902 # For childless nodes, normalize() has nothing to do.
903 pass
904
Martin v. Löwis787354c2003-01-25 15:28:29 +0000905 def replaceChild(self, newChild, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000906 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +0000907 self.nodeName + " nodes do not have children")
908
909
910class ProcessingInstruction(Childless, Node):
Fred Drake1f549022000-09-24 05:21:58 +0000911 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000912
Fred Drake1f549022000-09-24 05:21:58 +0000913 def __init__(self, target, data):
Fred Drake55c38192000-06-29 19:39:57 +0000914 self.target = self.nodeName = target
915 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000916
Martin v. Löwis787354c2003-01-25 15:28:29 +0000917 def _get_data(self):
918 return self.data
919 def _set_data(self, value):
920 d = self.__dict__
921 d['data'] = d['nodeValue'] = value
922
923 def _get_target(self):
924 return self.target
925 def _set_target(self, value):
926 d = self.__dict__
927 d['target'] = d['nodeName'] = value
928
929 def __setattr__(self, name, value):
930 if name == "data" or name == "nodeValue":
931 self.__dict__['data'] = self.__dict__['nodeValue'] = value
932 elif name == "target" or name == "nodeName":
933 self.__dict__['target'] = self.__dict__['nodeName'] = value
934 else:
935 self.__dict__[name] = value
936
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000937 def writexml(self, writer, indent="", addindent="", newl=""):
938 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000939
Martin v. Löwis787354c2003-01-25 15:28:29 +0000940
941class CharacterData(Childless, Node):
942 def _get_length(self):
943 return len(self.data)
944 __len__ = _get_length
945
946 def _get_data(self):
947 return self.__dict__['data']
948 def _set_data(self, data):
949 d = self.__dict__
950 d['data'] = d['nodeValue'] = data
951
952 _get_nodeValue = _get_data
953 _set_nodeValue = _set_data
954
955 def __setattr__(self, name, value):
956 if name == "data" or name == "nodeValue":
957 self.__dict__['data'] = self.__dict__['nodeValue'] = value
958 else:
959 self.__dict__[name] = value
Fred Drake87432f42001-04-04 14:09:46 +0000960
Fred Drake55c38192000-06-29 19:39:57 +0000961 def __repr__(self):
Martin v. Löwis787354c2003-01-25 15:28:29 +0000962 data = self.data
963 if len(data) > 10:
Fred Drake1f549022000-09-24 05:21:58 +0000964 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000965 else:
Fred Drake1f549022000-09-24 05:21:58 +0000966 dotdotdot = ""
Facundo Batistaf5ade632007-10-24 19:11:08 +0000967 return '<DOM %s node "%r%s">' % (
Martin v. Löwis787354c2003-01-25 15:28:29 +0000968 self.__class__.__name__, data[0:10], dotdotdot)
Fred Drake87432f42001-04-04 14:09:46 +0000969
970 def substringData(self, offset, count):
971 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000972 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000973 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000974 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000975 if count < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000976 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000977 return self.data[offset:offset+count]
978
979 def appendData(self, arg):
980 self.data = self.data + arg
Fred Drake87432f42001-04-04 14:09:46 +0000981
982 def insertData(self, offset, arg):
983 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000984 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000985 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000986 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000987 if arg:
988 self.data = "%s%s%s" % (
989 self.data[:offset], arg, self.data[offset:])
Fred Drake87432f42001-04-04 14:09:46 +0000990
991 def deleteData(self, offset, count):
992 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000993 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000994 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +0000995 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +0000996 if count < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +0000997 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +0000998 if count:
999 self.data = self.data[:offset] + self.data[offset+count:]
Fred Drake87432f42001-04-04 14:09:46 +00001000
1001 def replaceData(self, offset, count, arg):
1002 if offset < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001003 raise xml.dom.IndexSizeErr("offset cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001004 if offset >= len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001005 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
Fred Drake87432f42001-04-04 14:09:46 +00001006 if count < 0:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001007 raise xml.dom.IndexSizeErr("count cannot be negative")
Fred Drake87432f42001-04-04 14:09:46 +00001008 if count:
1009 self.data = "%s%s%s" % (
1010 self.data[:offset], arg, self.data[offset+count:])
Martin v. Löwis787354c2003-01-25 15:28:29 +00001011
1012defproperty(CharacterData, "length", doc="Length of the string data.")
1013
Fred Drake87432f42001-04-04 14:09:46 +00001014
1015class Text(CharacterData):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001016 # Make sure we don't add an instance __dict__ if we don't already
1017 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001018 # XXX this does not work, CharacterData is an old-style class
1019 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001020
Fred Drake87432f42001-04-04 14:09:46 +00001021 nodeType = Node.TEXT_NODE
1022 nodeName = "#text"
1023 attributes = None
Fred Drake55c38192000-06-29 19:39:57 +00001024
Fred Drakef7cf40d2000-12-14 18:16:11 +00001025 def splitText(self, offset):
1026 if offset < 0 or offset > len(self.data):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001027 raise xml.dom.IndexSizeErr("illegal offset value")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001028 newText = self.__class__()
1029 newText.data = self.data[offset:]
1030 newText.ownerDocument = self.ownerDocument
Fred Drakef7cf40d2000-12-14 18:16:11 +00001031 next = self.nextSibling
1032 if self.parentNode and self in self.parentNode.childNodes:
1033 if next is None:
1034 self.parentNode.appendChild(newText)
1035 else:
1036 self.parentNode.insertBefore(newText, next)
1037 self.data = self.data[:offset]
1038 return newText
1039
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001040 def writexml(self, writer, indent="", addindent="", newl=""):
Ezio Melotti93bbb6a2011-11-18 17:30:28 +02001041 _write_data(writer, "%s%s%s" % (indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001042
Martin v. Löwis787354c2003-01-25 15:28:29 +00001043 # DOM Level 3 (WD 9 April 2002)
1044
1045 def _get_wholeText(self):
1046 L = [self.data]
1047 n = self.previousSibling
1048 while n is not None:
1049 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1050 L.insert(0, n.data)
1051 n = n.previousSibling
1052 else:
1053 break
1054 n = self.nextSibling
1055 while n is not None:
1056 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1057 L.append(n.data)
1058 n = n.nextSibling
1059 else:
1060 break
1061 return ''.join(L)
1062
1063 def replaceWholeText(self, content):
1064 # XXX This needs to be seriously changed if minidom ever
1065 # supports EntityReference nodes.
1066 parent = self.parentNode
1067 n = self.previousSibling
1068 while n is not None:
1069 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1070 next = n.previousSibling
1071 parent.removeChild(n)
1072 n = next
1073 else:
1074 break
1075 n = self.nextSibling
1076 if not content:
1077 parent.removeChild(self)
1078 while n is not None:
1079 if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1080 next = n.nextSibling
1081 parent.removeChild(n)
1082 n = next
1083 else:
1084 break
1085 if content:
1086 d = self.__dict__
1087 d['data'] = content
1088 d['nodeValue'] = content
1089 return self
1090 else:
1091 return None
1092
1093 def _get_isWhitespaceInElementContent(self):
1094 if self.data.strip():
1095 return False
1096 elem = _get_containing_element(self)
1097 if elem is None:
1098 return False
1099 info = self.ownerDocument._get_elem_info(elem)
1100 if info is None:
1101 return False
1102 else:
1103 return info.isElementContent()
1104
1105defproperty(Text, "isWhitespaceInElementContent",
1106 doc="True iff this text node contains only whitespace"
1107 " and is in element content.")
1108defproperty(Text, "wholeText",
1109 doc="The text of all logically-adjacent text nodes.")
1110
1111
1112def _get_containing_element(node):
1113 c = node.parentNode
1114 while c is not None:
1115 if c.nodeType == Node.ELEMENT_NODE:
1116 return c
1117 c = c.parentNode
1118 return None
1119
1120def _get_containing_entref(node):
1121 c = node.parentNode
1122 while c is not None:
1123 if c.nodeType == Node.ENTITY_REFERENCE_NODE:
1124 return c
1125 c = c.parentNode
1126 return None
1127
1128
1129class Comment(Childless, CharacterData):
1130 nodeType = Node.COMMENT_NODE
1131 nodeName = "#comment"
1132
1133 def __init__(self, data):
1134 self.data = self.nodeValue = data
1135
1136 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis27e4a172008-05-23 15:18:28 +00001137 if "--" in self.data:
1138 raise ValueError("'--' is not allowed in a comment node")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001139 writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
1140
Fred Drake87432f42001-04-04 14:09:46 +00001141
1142class CDATASection(Text):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001143 # Make sure we don't add an instance __dict__ if we don't already
1144 # have one, at least when that's possible:
Martin v. Löwis995359c2003-01-26 08:59:32 +00001145 # XXX this does not work, Text is an old-style class
1146 # __slots__ = ()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001147
Fred Drake87432f42001-04-04 14:09:46 +00001148 nodeType = Node.CDATA_SECTION_NODE
1149 nodeName = "#cdata-section"
1150
1151 def writexml(self, writer, indent="", addindent="", newl=""):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001152 if self.data.find("]]>") >= 0:
1153 raise ValueError("']]>' not allowed in a CDATA section")
Guido van Rossum5b5e0b92001-09-19 13:28:25 +00001154 writer.write("<![CDATA[%s]]>" % self.data)
Fred Drake87432f42001-04-04 14:09:46 +00001155
1156
Fred Drake9ea179f2006-04-06 01:29:04 +00001157class ReadOnlySequentialNamedNodeMap(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001158 __slots__ = '_seq',
1159
1160 def __init__(self, seq=()):
1161 # seq should be a list or tuple
1162 self._seq = seq
1163
1164 def __len__(self):
1165 return len(self._seq)
1166
1167 def _get_length(self):
1168 return len(self._seq)
1169
1170 def getNamedItem(self, name):
1171 for n in self._seq:
1172 if n.nodeName == name:
1173 return n
1174
1175 def getNamedItemNS(self, namespaceURI, localName):
1176 for n in self._seq:
1177 if n.namespaceURI == namespaceURI and n.localName == localName:
1178 return n
1179
1180 def __getitem__(self, name_or_tuple):
Fred Drake70d044b2006-04-06 01:32:26 +00001181 if isinstance(name_or_tuple, tuple):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001182 node = self.getNamedItemNS(*name_or_tuple)
1183 else:
1184 node = self.getNamedItem(name_or_tuple)
1185 if node is None:
1186 raise KeyError, name_or_tuple
1187 return node
1188
1189 def item(self, index):
1190 if index < 0:
1191 return None
1192 try:
1193 return self._seq[index]
1194 except IndexError:
1195 return None
1196
1197 def removeNamedItem(self, name):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001198 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001199 "NamedNodeMap instance is read-only")
1200
1201 def removeNamedItemNS(self, namespaceURI, localName):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001202 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001203 "NamedNodeMap instance is read-only")
1204
1205 def setNamedItem(self, node):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001206 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001207 "NamedNodeMap instance is read-only")
1208
1209 def setNamedItemNS(self, node):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001210 raise xml.dom.NoModificationAllowedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001211 "NamedNodeMap instance is read-only")
1212
1213 def __getstate__(self):
1214 return [self._seq]
1215
1216 def __setstate__(self, state):
1217 self._seq = state[0]
1218
1219defproperty(ReadOnlySequentialNamedNodeMap, "length",
1220 doc="Number of entries in the NamedNodeMap.")
Paul Prescod73678da2000-07-01 04:58:47 +00001221
Fred Drakef7cf40d2000-12-14 18:16:11 +00001222
Martin v. Löwis787354c2003-01-25 15:28:29 +00001223class Identified:
1224 """Mix-in class that supports the publicId and systemId attributes."""
1225
Martin v. Löwis995359c2003-01-26 08:59:32 +00001226 # XXX this does not work, this is an old-style class
1227 # __slots__ = 'publicId', 'systemId'
Martin v. Löwis787354c2003-01-25 15:28:29 +00001228
1229 def _identified_mixin_init(self, publicId, systemId):
1230 self.publicId = publicId
1231 self.systemId = systemId
1232
1233 def _get_publicId(self):
1234 return self.publicId
1235
1236 def _get_systemId(self):
1237 return self.systemId
1238
1239class DocumentType(Identified, Childless, Node):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001240 nodeType = Node.DOCUMENT_TYPE_NODE
1241 nodeValue = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001242 name = None
1243 publicId = None
1244 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +00001245 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001246
1247 def __init__(self, qualifiedName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001248 self.entities = ReadOnlySequentialNamedNodeMap()
1249 self.notations = ReadOnlySequentialNamedNodeMap()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001250 if qualifiedName:
1251 prefix, localname = _nssplit(qualifiedName)
1252 self.name = localname
Martin v. Löwis787354c2003-01-25 15:28:29 +00001253 self.nodeName = self.name
1254
1255 def _get_internalSubset(self):
1256 return self.internalSubset
1257
1258 def cloneNode(self, deep):
1259 if self.ownerDocument is None:
1260 # it's ok
1261 clone = DocumentType(None)
1262 clone.name = self.name
1263 clone.nodeName = self.name
Fred Drakefbdeaad2006-07-29 16:56:15 +00001264 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001265 if deep:
1266 clone.entities._seq = []
1267 clone.notations._seq = []
1268 for n in self.notations._seq:
1269 notation = Notation(n.nodeName, n.publicId, n.systemId)
1270 clone.notations._seq.append(notation)
1271 n._call_user_data_handler(operation, n, notation)
1272 for e in self.entities._seq:
1273 entity = Entity(e.nodeName, e.publicId, e.systemId,
1274 e.notationName)
1275 entity.actualEncoding = e.actualEncoding
1276 entity.encoding = e.encoding
1277 entity.version = e.version
1278 clone.entities._seq.append(entity)
1279 e._call_user_data_handler(operation, n, entity)
1280 self._call_user_data_handler(operation, self, clone)
1281 return clone
1282 else:
1283 return None
1284
1285 def writexml(self, writer, indent="", addindent="", newl=""):
1286 writer.write("<!DOCTYPE ")
1287 writer.write(self.name)
1288 if self.publicId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001289 writer.write("%s PUBLIC '%s'%s '%s'"
1290 % (newl, self.publicId, newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001291 elif self.systemId:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001292 writer.write("%s SYSTEM '%s'" % (newl, self.systemId))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001293 if self.internalSubset is not None:
1294 writer.write(" [")
1295 writer.write(self.internalSubset)
1296 writer.write("]")
Georg Brandl175a7dc2005-08-25 22:02:43 +00001297 writer.write(">"+newl)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001298
1299class Entity(Identified, Node):
1300 attributes = None
1301 nodeType = Node.ENTITY_NODE
1302 nodeValue = None
1303
1304 actualEncoding = None
1305 encoding = None
1306 version = None
1307
1308 def __init__(self, name, publicId, systemId, notation):
1309 self.nodeName = name
1310 self.notationName = notation
1311 self.childNodes = NodeList()
1312 self._identified_mixin_init(publicId, systemId)
1313
1314 def _get_actualEncoding(self):
1315 return self.actualEncoding
1316
1317 def _get_encoding(self):
1318 return self.encoding
1319
1320 def _get_version(self):
1321 return self.version
1322
1323 def appendChild(self, newChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001324 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001325 "cannot append children to an entity node")
1326
1327 def insertBefore(self, newChild, refChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001328 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001329 "cannot insert children below an entity node")
1330
1331 def removeChild(self, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001332 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001333 "cannot remove children from an entity node")
1334
1335 def replaceChild(self, newChild, oldChild):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001336 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001337 "cannot replace children of an entity node")
1338
1339class Notation(Identified, Childless, Node):
1340 nodeType = Node.NOTATION_NODE
1341 nodeValue = None
1342
1343 def __init__(self, name, publicId, systemId):
1344 self.nodeName = name
1345 self._identified_mixin_init(publicId, systemId)
Fred Drakef7cf40d2000-12-14 18:16:11 +00001346
1347
Martin v. Löwis787354c2003-01-25 15:28:29 +00001348class DOMImplementation(DOMImplementationLS):
1349 _features = [("core", "1.0"),
1350 ("core", "2.0"),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001351 ("core", None),
1352 ("xml", "1.0"),
1353 ("xml", "2.0"),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001354 ("xml", None),
1355 ("ls-load", "3.0"),
1356 ("ls-load", None),
1357 ]
1358
Fred Drakef7cf40d2000-12-14 18:16:11 +00001359 def hasFeature(self, feature, version):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001360 if version == "":
1361 version = None
1362 return (feature.lower(), version) in self._features
Fred Drakef7cf40d2000-12-14 18:16:11 +00001363
1364 def createDocument(self, namespaceURI, qualifiedName, doctype):
1365 if doctype and doctype.parentNode is not None:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001366 raise xml.dom.WrongDocumentErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001367 "doctype object owned by another DOM tree")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001368 doc = self._create_document()
1369
1370 add_root_element = not (namespaceURI is None
1371 and qualifiedName is None
1372 and doctype is None)
1373
1374 if not qualifiedName and add_root_element:
Martin v. Löwisb417be22001-02-06 01:16:06 +00001375 # The spec is unclear what to raise here; SyntaxErr
1376 # would be the other obvious candidate. Since Xerces raises
1377 # InvalidCharacterErr, and since SyntaxErr is not listed
1378 # for createDocument, that seems to be the better choice.
1379 # XXX: need to check for illegal characters here and in
1380 # createElement.
Martin v. Löwis787354c2003-01-25 15:28:29 +00001381
1382 # DOM Level III clears this up when talking about the return value
1383 # of this function. If namespaceURI, qName and DocType are
1384 # Null the document is returned without a document element
1385 # Otherwise if doctype or namespaceURI are not None
1386 # Then we go back to the above problem
Fred Drakefbdeaad2006-07-29 16:56:15 +00001387 raise xml.dom.InvalidCharacterErr("Element with no name")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001388
1389 if add_root_element:
1390 prefix, localname = _nssplit(qualifiedName)
1391 if prefix == "xml" \
1392 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
Fred Drakefbdeaad2006-07-29 16:56:15 +00001393 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001394 if prefix and not namespaceURI:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001395 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001396 "illegal use of prefix without namespaces")
1397 element = doc.createElementNS(namespaceURI, qualifiedName)
1398 if doctype:
1399 doc.appendChild(doctype)
1400 doc.appendChild(element)
1401
1402 if doctype:
1403 doctype.parentNode = doctype.ownerDocument = doc
1404
Fred Drakef7cf40d2000-12-14 18:16:11 +00001405 doc.doctype = doctype
1406 doc.implementation = self
1407 return doc
1408
1409 def createDocumentType(self, qualifiedName, publicId, systemId):
1410 doctype = DocumentType(qualifiedName)
1411 doctype.publicId = publicId
1412 doctype.systemId = systemId
1413 return doctype
1414
Martin v. Löwis787354c2003-01-25 15:28:29 +00001415 # DOM Level 3 (WD 9 April 2002)
1416
1417 def getInterface(self, feature):
1418 if self.hasFeature(feature, None):
1419 return self
1420 else:
1421 return None
1422
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001423 # internal
Martin v. Löwis787354c2003-01-25 15:28:29 +00001424 def _create_document(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001425 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +00001426
Fred Drake9ea179f2006-04-06 01:29:04 +00001427class ElementInfo(object):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001428 """Object that represents content-model information for an element.
1429
1430 This implementation is not expected to be used in practice; DOM
1431 builders should provide implementations which do the right thing
1432 using information available to it.
1433
1434 """
1435
1436 __slots__ = 'tagName',
1437
1438 def __init__(self, name):
1439 self.tagName = name
1440
1441 def getAttributeType(self, aname):
1442 return _no_type
1443
1444 def getAttributeTypeNS(self, namespaceURI, localName):
1445 return _no_type
1446
1447 def isElementContent(self):
1448 return False
1449
1450 def isEmpty(self):
1451 """Returns true iff this element is declared to have an EMPTY
1452 content model."""
1453 return False
1454
1455 def isId(self, aname):
Ezio Melotti24b07bc2011-03-15 18:55:01 +02001456 """Returns true iff the named attribute is a DTD-style ID."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001457 return False
1458
1459 def isIdNS(self, namespaceURI, localName):
1460 """Returns true iff the identified attribute is a DTD-style ID."""
1461 return False
1462
1463 def __getstate__(self):
1464 return self.tagName
1465
1466 def __setstate__(self, state):
1467 self.tagName = state
1468
1469def _clear_id_cache(node):
1470 if node.nodeType == Node.DOCUMENT_NODE:
1471 node._id_cache.clear()
1472 node._id_search_stack = None
1473 elif _in_document(node):
1474 node.ownerDocument._id_cache.clear()
1475 node.ownerDocument._id_search_stack= None
1476
1477class Document(Node, DocumentLS):
1478 _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
1479 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
1480
Fred Drake1f549022000-09-24 05:21:58 +00001481 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +00001482 nodeName = "#document"
1483 nodeValue = None
1484 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001485 doctype = None
1486 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001487 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +00001488
1489 implementation = DOMImplementation()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001490
1491 # Document attributes from Level 3 (WD 9 April 2002)
1492
1493 actualEncoding = None
1494 encoding = None
1495 standalone = None
1496 version = None
1497 strictErrorChecking = False
1498 errorHandler = None
1499 documentURI = None
1500
1501 _magic_id_count = 0
1502
1503 def __init__(self):
1504 self.childNodes = NodeList()
1505 # mapping of (namespaceURI, localName) -> ElementInfo
1506 # and tagName -> ElementInfo
1507 self._elem_info = {}
1508 self._id_cache = {}
1509 self._id_search_stack = None
1510
1511 def _get_elem_info(self, element):
1512 if element.namespaceURI:
1513 key = element.namespaceURI, element.localName
1514 else:
1515 key = element.tagName
1516 return self._elem_info.get(key)
1517
1518 def _get_actualEncoding(self):
1519 return self.actualEncoding
1520
1521 def _get_doctype(self):
1522 return self.doctype
1523
1524 def _get_documentURI(self):
1525 return self.documentURI
1526
1527 def _get_encoding(self):
1528 return self.encoding
1529
1530 def _get_errorHandler(self):
1531 return self.errorHandler
1532
1533 def _get_standalone(self):
1534 return self.standalone
1535
1536 def _get_strictErrorChecking(self):
1537 return self.strictErrorChecking
1538
1539 def _get_version(self):
1540 return self.version
Fred Drake55c38192000-06-29 19:39:57 +00001541
Fred Drake1f549022000-09-24 05:21:58 +00001542 def appendChild(self, node):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001543 if node.nodeType not in self._child_node_types:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001544 raise xml.dom.HierarchyRequestErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001545 "%s cannot be child of %s" % (repr(node), repr(self)))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001546 if node.parentNode is not None:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001547 # This needs to be done before the next test since this
1548 # may *be* the document element, in which case it should
1549 # end up re-ordered to the end.
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001550 node.parentNode.removeChild(node)
1551
Fred Drakef7cf40d2000-12-14 18:16:11 +00001552 if node.nodeType == Node.ELEMENT_NODE \
1553 and self._get_documentElement():
Fred Drakefbdeaad2006-07-29 16:56:15 +00001554 raise xml.dom.HierarchyRequestErr(
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00001555 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +00001556 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +00001557
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001558 def removeChild(self, oldChild):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001559 try:
1560 self.childNodes.remove(oldChild)
1561 except ValueError:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001562 raise xml.dom.NotFoundErr()
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001563 oldChild.nextSibling = oldChild.previousSibling = None
1564 oldChild.parentNode = None
1565 if self.documentElement is oldChild:
1566 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +00001567
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +00001568 return oldChild
1569
Fred Drakef7cf40d2000-12-14 18:16:11 +00001570 def _get_documentElement(self):
1571 for node in self.childNodes:
1572 if node.nodeType == Node.ELEMENT_NODE:
1573 return node
1574
1575 def unlink(self):
1576 if self.doctype is not None:
1577 self.doctype.unlink()
1578 self.doctype = None
1579 Node.unlink(self)
1580
Martin v. Löwis787354c2003-01-25 15:28:29 +00001581 def cloneNode(self, deep):
1582 if not deep:
1583 return None
1584 clone = self.implementation.createDocument(None, None, None)
1585 clone.encoding = self.encoding
1586 clone.standalone = self.standalone
1587 clone.version = self.version
1588 for n in self.childNodes:
1589 childclone = _clone_node(n, deep, clone)
1590 assert childclone.ownerDocument.isSameNode(clone)
1591 clone.childNodes.append(childclone)
1592 if childclone.nodeType == Node.DOCUMENT_NODE:
1593 assert clone.documentElement is None
1594 elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
1595 assert clone.doctype is None
1596 clone.doctype = childclone
1597 childclone.parentNode = clone
Fred Drakefbdeaad2006-07-29 16:56:15 +00001598 self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
Martin v. Löwis787354c2003-01-25 15:28:29 +00001599 self, clone)
1600 return clone
1601
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001602 def createDocumentFragment(self):
1603 d = DocumentFragment()
Martin v. Löwis787354c2003-01-25 15:28:29 +00001604 d.ownerDocument = self
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001605 return d
Fred Drake55c38192000-06-29 19:39:57 +00001606
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001607 def createElement(self, tagName):
1608 e = Element(tagName)
1609 e.ownerDocument = self
1610 return e
Fred Drake55c38192000-06-29 19:39:57 +00001611
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001612 def createTextNode(self, data):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001613 if not isinstance(data, StringTypes):
1614 raise TypeError, "node contents must be a string"
1615 t = Text()
1616 t.data = data
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001617 t.ownerDocument = self
1618 return t
Fred Drake55c38192000-06-29 19:39:57 +00001619
Fred Drake87432f42001-04-04 14:09:46 +00001620 def createCDATASection(self, data):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001621 if not isinstance(data, StringTypes):
1622 raise TypeError, "node contents must be a string"
1623 c = CDATASection()
1624 c.data = data
Fred Drake87432f42001-04-04 14:09:46 +00001625 c.ownerDocument = self
1626 return c
1627
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001628 def createComment(self, data):
1629 c = Comment(data)
1630 c.ownerDocument = self
1631 return c
Fred Drake55c38192000-06-29 19:39:57 +00001632
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001633 def createProcessingInstruction(self, target, data):
1634 p = ProcessingInstruction(target, data)
1635 p.ownerDocument = self
1636 return p
1637
1638 def createAttribute(self, qName):
1639 a = Attr(qName)
1640 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001641 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001642 return a
Fred Drake55c38192000-06-29 19:39:57 +00001643
1644 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001645 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis787354c2003-01-25 15:28:29 +00001646 e = Element(qualifiedName, namespaceURI, prefix)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001647 e.ownerDocument = self
1648 return e
Fred Drake55c38192000-06-29 19:39:57 +00001649
1650 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +00001651 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001652 a = Attr(qualifiedName, namespaceURI, localName, prefix)
1653 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +00001654 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +00001655 return a
Fred Drake55c38192000-06-29 19:39:57 +00001656
Martin v. Löwis787354c2003-01-25 15:28:29 +00001657 # A couple of implementation-specific helpers to create node types
1658 # not supported by the W3C DOM specs:
1659
1660 def _create_entity(self, name, publicId, systemId, notationName):
1661 e = Entity(name, publicId, systemId, notationName)
1662 e.ownerDocument = self
1663 return e
1664
1665 def _create_notation(self, name, publicId, systemId):
1666 n = Notation(name, publicId, systemId)
1667 n.ownerDocument = self
1668 return n
1669
1670 def getElementById(self, id):
Brett Cannon5dd504d2008-08-04 00:23:58 +00001671 if id in self._id_cache:
Martin v. Löwis787354c2003-01-25 15:28:29 +00001672 return self._id_cache[id]
1673 if not (self._elem_info or self._magic_id_count):
1674 return None
1675
1676 stack = self._id_search_stack
1677 if stack is None:
1678 # we never searched before, or the cache has been cleared
1679 stack = [self.documentElement]
1680 self._id_search_stack = stack
1681 elif not stack:
1682 # Previous search was completed and cache is still valid;
1683 # no matching node.
1684 return None
1685
1686 result = None
1687 while stack:
1688 node = stack.pop()
1689 # add child elements to stack for continued searching
1690 stack.extend([child for child in node.childNodes
1691 if child.nodeType in _nodeTypes_with_children])
1692 # check this node
1693 info = self._get_elem_info(node)
1694 if info:
1695 # We have to process all ID attributes before
1696 # returning in order to get all the attributes set to
1697 # be IDs using Element.setIdAttribute*().
1698 for attr in node.attributes.values():
1699 if attr.namespaceURI:
1700 if info.isIdNS(attr.namespaceURI, attr.localName):
1701 self._id_cache[attr.value] = node
1702 if attr.value == id:
1703 result = node
1704 elif not node._magic_id_nodes:
1705 break
1706 elif info.isId(attr.name):
1707 self._id_cache[attr.value] = node
1708 if attr.value == id:
1709 result = node
1710 elif not node._magic_id_nodes:
1711 break
1712 elif attr._is_id:
1713 self._id_cache[attr.value] = node
1714 if attr.value == id:
1715 result = node
1716 elif node._magic_id_nodes == 1:
1717 break
1718 elif node._magic_id_nodes:
1719 for attr in node.attributes.values():
1720 if attr._is_id:
1721 self._id_cache[attr.value] = node
1722 if attr.value == id:
1723 result = node
1724 if result is not None:
1725 break
1726 return result
1727
Fred Drake1f549022000-09-24 05:21:58 +00001728 def getElementsByTagName(self, name):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001729 return _get_elements_by_tagName_helper(self, name, NodeList())
Fred Drakefbe7b4f2001-07-04 06:25:53 +00001730
1731 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwis787354c2003-01-25 15:28:29 +00001732 return _get_elements_by_tagName_ns_helper(
1733 self, namespaceURI, localName, NodeList())
1734
1735 def isSupported(self, feature, version):
1736 return self.implementation.hasFeature(feature, version)
1737
1738 def importNode(self, node, deep):
1739 if node.nodeType == Node.DOCUMENT_NODE:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001740 raise xml.dom.NotSupportedErr("cannot import document nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001741 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001742 raise xml.dom.NotSupportedErr("cannot import document type nodes")
Martin v. Löwis787354c2003-01-25 15:28:29 +00001743 return _clone_node(node, deep, self)
Fred Drake55c38192000-06-29 19:39:57 +00001744
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001745 def writexml(self, writer, indent="", addindent="", newl="",
1746 encoding = None):
1747 if encoding is None:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001748 writer.write('<?xml version="1.0" ?>'+newl)
Martin v. Löwis7d650ca2002-06-30 15:05:00 +00001749 else:
Georg Brandl175a7dc2005-08-25 22:02:43 +00001750 writer.write('<?xml version="1.0" encoding="%s"?>%s' % (encoding, newl))
Fred Drake55c38192000-06-29 19:39:57 +00001751 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +00001752 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +00001753
Martin v. Löwis787354c2003-01-25 15:28:29 +00001754 # DOM Level 3 (WD 9 April 2002)
1755
1756 def renameNode(self, n, namespaceURI, name):
1757 if n.ownerDocument is not self:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001758 raise xml.dom.WrongDocumentErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001759 "cannot rename nodes from other documents;\n"
1760 "expected %s,\nfound %s" % (self, n.ownerDocument))
1761 if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001762 raise xml.dom.NotSupportedErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001763 "renameNode() only applies to element and attribute nodes")
1764 if namespaceURI != EMPTY_NAMESPACE:
1765 if ':' in name:
1766 prefix, localName = name.split(':', 1)
1767 if ( prefix == "xmlns"
Fred Drakefbdeaad2006-07-29 16:56:15 +00001768 and namespaceURI != xml.dom.XMLNS_NAMESPACE):
1769 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001770 "illegal use of 'xmlns' prefix")
1771 else:
1772 if ( name == "xmlns"
Fred Drakefbdeaad2006-07-29 16:56:15 +00001773 and namespaceURI != xml.dom.XMLNS_NAMESPACE
Martin v. Löwis787354c2003-01-25 15:28:29 +00001774 and n.nodeType == Node.ATTRIBUTE_NODE):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001775 raise xml.dom.NamespaceErr(
Martin v. Löwis787354c2003-01-25 15:28:29 +00001776 "illegal use of the 'xmlns' attribute")
1777 prefix = None
1778 localName = name
1779 else:
1780 prefix = None
1781 localName = None
1782 if n.nodeType == Node.ATTRIBUTE_NODE:
1783 element = n.ownerElement
1784 if element is not None:
1785 is_id = n._is_id
1786 element.removeAttributeNode(n)
1787 else:
1788 element = None
1789 # avoid __setattr__
1790 d = n.__dict__
1791 d['prefix'] = prefix
1792 d['localName'] = localName
1793 d['namespaceURI'] = namespaceURI
1794 d['nodeName'] = name
1795 if n.nodeType == Node.ELEMENT_NODE:
1796 d['tagName'] = name
1797 else:
1798 # attribute node
1799 d['name'] = name
1800 if element is not None:
1801 element.setAttributeNode(n)
1802 if is_id:
1803 element.setIdAttributeNode(n)
1804 # It's not clear from a semantic perspective whether we should
1805 # call the user data handlers for the NODE_RENAMED event since
1806 # we're re-using the existing node. The draft spec has been
1807 # interpreted as meaning "no, don't call the handler unless a
1808 # new node is created."
1809 return n
1810
1811defproperty(Document, "documentElement",
1812 doc="Top-level element of this document.")
1813
1814
1815def _clone_node(node, deep, newOwnerDocument):
1816 """
1817 Clone a node and give it the new owner document.
1818 Called by Node.cloneNode and Document.importNode
1819 """
1820 if node.ownerDocument.isSameNode(newOwnerDocument):
Fred Drakefbdeaad2006-07-29 16:56:15 +00001821 operation = xml.dom.UserDataHandler.NODE_CLONED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001822 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001823 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001824 if node.nodeType == Node.ELEMENT_NODE:
1825 clone = newOwnerDocument.createElementNS(node.namespaceURI,
1826 node.nodeName)
1827 for attr in node.attributes.values():
1828 clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
1829 a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
1830 a.specified = attr.specified
1831
1832 if deep:
1833 for child in node.childNodes:
1834 c = _clone_node(child, deep, newOwnerDocument)
1835 clone.appendChild(c)
1836
1837 elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
1838 clone = newOwnerDocument.createDocumentFragment()
1839 if deep:
1840 for child in node.childNodes:
1841 c = _clone_node(child, deep, newOwnerDocument)
1842 clone.appendChild(c)
1843
1844 elif node.nodeType == Node.TEXT_NODE:
1845 clone = newOwnerDocument.createTextNode(node.data)
1846 elif node.nodeType == Node.CDATA_SECTION_NODE:
1847 clone = newOwnerDocument.createCDATASection(node.data)
1848 elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
1849 clone = newOwnerDocument.createProcessingInstruction(node.target,
1850 node.data)
1851 elif node.nodeType == Node.COMMENT_NODE:
1852 clone = newOwnerDocument.createComment(node.data)
1853 elif node.nodeType == Node.ATTRIBUTE_NODE:
1854 clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
1855 node.nodeName)
1856 clone.specified = True
1857 clone.value = node.value
1858 elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
1859 assert node.ownerDocument is not newOwnerDocument
Fred Drakefbdeaad2006-07-29 16:56:15 +00001860 operation = xml.dom.UserDataHandler.NODE_IMPORTED
Martin v. Löwis787354c2003-01-25 15:28:29 +00001861 clone = newOwnerDocument.implementation.createDocumentType(
1862 node.name, node.publicId, node.systemId)
1863 clone.ownerDocument = newOwnerDocument
1864 if deep:
1865 clone.entities._seq = []
1866 clone.notations._seq = []
1867 for n in node.notations._seq:
1868 notation = Notation(n.nodeName, n.publicId, n.systemId)
1869 notation.ownerDocument = newOwnerDocument
1870 clone.notations._seq.append(notation)
1871 if hasattr(n, '_call_user_data_handler'):
1872 n._call_user_data_handler(operation, n, notation)
1873 for e in node.entities._seq:
1874 entity = Entity(e.nodeName, e.publicId, e.systemId,
1875 e.notationName)
1876 entity.actualEncoding = e.actualEncoding
1877 entity.encoding = e.encoding
1878 entity.version = e.version
1879 entity.ownerDocument = newOwnerDocument
1880 clone.entities._seq.append(entity)
1881 if hasattr(e, '_call_user_data_handler'):
1882 e._call_user_data_handler(operation, n, entity)
1883 else:
1884 # Note the cloning of Document and DocumentType nodes is
Ezio Melottic2077b02011-03-16 12:34:31 +02001885 # implementation specific. minidom handles those cases
Martin v. Löwis787354c2003-01-25 15:28:29 +00001886 # directly in the cloneNode() methods.
Fred Drakefbdeaad2006-07-29 16:56:15 +00001887 raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
Martin v. Löwis787354c2003-01-25 15:28:29 +00001888
1889 # Check for _call_user_data_handler() since this could conceivably
1890 # used with other DOM implementations (one of the FourThought
1891 # DOMs, perhaps?).
1892 if hasattr(node, '_call_user_data_handler'):
1893 node._call_user_data_handler(operation, node, clone)
1894 return clone
1895
1896
1897def _nssplit(qualifiedName):
1898 fields = qualifiedName.split(':', 1)
1899 if len(fields) == 2:
1900 return fields
1901 else:
1902 return (None, fields[0])
1903
1904
Fred Drake4ccf4a12000-11-21 22:02:22 +00001905def _get_StringIO():
Fred Drakef7cf40d2000-12-14 18:16:11 +00001906 # we can't use cStringIO since it doesn't support Unicode strings
1907 from StringIO import StringIO
Fred Drake4ccf4a12000-11-21 22:02:22 +00001908 return StringIO()
1909
Martin v. Löwis787354c2003-01-25 15:28:29 +00001910def _do_pulldom_parse(func, args, kwargs):
Raymond Hettingerff41c482003-04-06 09:01:11 +00001911 events = func(*args, **kwargs)
Fred Drake1f549022000-09-24 05:21:58 +00001912 toktype, rootNode = events.getEvent()
1913 events.expandNode(rootNode)
Martin v. Löwisb417be22001-02-06 01:16:06 +00001914 events.clear()
Fred Drake55c38192000-06-29 19:39:57 +00001915 return rootNode
1916
Martin v. Löwis787354c2003-01-25 15:28:29 +00001917def parse(file, parser=None, bufsize=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001918 """Parse a file into a DOM by filename or file object."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001919 if parser is None and not bufsize:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001920 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001921 return expatbuilder.parse(file)
1922 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001923 from xml.dom import pulldom
Raymond Hettingerff41c482003-04-06 09:01:11 +00001924 return _do_pulldom_parse(pulldom.parse, (file,),
Martin v. Löwis787354c2003-01-25 15:28:29 +00001925 {'parser': parser, 'bufsize': bufsize})
Fred Drake55c38192000-06-29 19:39:57 +00001926
Martin v. Löwis787354c2003-01-25 15:28:29 +00001927def parseString(string, parser=None):
Fred Drakef7cf40d2000-12-14 18:16:11 +00001928 """Parse a file into a DOM from a string."""
Martin v. Löwis787354c2003-01-25 15:28:29 +00001929 if parser is None:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001930 from xml.dom import expatbuilder
Martin v. Löwis787354c2003-01-25 15:28:29 +00001931 return expatbuilder.parseString(string)
1932 else:
Fred Drakefbdeaad2006-07-29 16:56:15 +00001933 from xml.dom import pulldom
Martin v. Löwis787354c2003-01-25 15:28:29 +00001934 return _do_pulldom_parse(pulldom.parseString, (string,),
1935 {'parser': parser})
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001936
Martin v. Löwis787354c2003-01-25 15:28:29 +00001937def getDOMImplementation(features=None):
1938 if features:
1939 if isinstance(features, StringTypes):
1940 features = domreg._parse_feature_string(features)
1941 for f, v in features:
1942 if not Document.implementation.hasFeature(f, v):
1943 return None
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +00001944 return Document.implementation