blob: 59f86a75e733e6a05477f1a3db77b805287f37b6 [file] [log] [blame]
Fred Drake1f549022000-09-24 05:21:58 +00001"""\
Fred Drakef7cf40d2000-12-14 18:16:11 +00002minidom.py -- a lightweight DOM implementation.
Fred Drake55c38192000-06-29 19:39:57 +00003
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00004parse("foo.xml")
Paul Prescod623511b2000-07-21 22:05:49 +00005
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +00006parseString("<foo><bar/></foo>")
Paul Prescod623511b2000-07-21 22:05:49 +00007
Fred Drake55c38192000-06-29 19:39:57 +00008Todo:
9=====
10 * convenience methods for getting elements and text.
11 * more testing
12 * bring some of the writer and linearizer code into conformance with this
13 interface
14 * SAX 2 namespaces
15"""
16
Fred Drake1f549022000-09-24 05:21:58 +000017import string
Fred Drake4ccf4a12000-11-21 22:02:22 +000018_string = string
19del string
20
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +000021from xml.dom import HierarchyRequestErr
22
Fred Drake4ccf4a12000-11-21 22:02:22 +000023# localize the types, and allow support for Unicode values if available:
Fred Drake1f549022000-09-24 05:21:58 +000024import types
Fred Drake4ccf4a12000-11-21 22:02:22 +000025_TupleType = types.TupleType
26try:
27 _StringTypes = (types.StringType, types.UnicodeType)
28except AttributeError:
29 _StringTypes = (types.StringType,)
30del types
31
Fred Drakef7cf40d2000-12-14 18:16:11 +000032import xml.dom
33_Node = xml.dom.Node
Fred Drake55c38192000-06-29 19:39:57 +000034
Fred Drakef7cf40d2000-12-14 18:16:11 +000035class Node(_Node):
Fred Drake1f549022000-09-24 05:21:58 +000036 allnodes = {}
37 _debug = 0
38 _makeParentNodes = 1
39 debug = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +000040 childNodeTypes = ()
Martin v. Löwis126f2f62001-03-13 10:50:13 +000041 namespaceURI = None # this is non-null only for elements and attributes
Martin v. Löwis52ce0d02001-01-27 08:47:37 +000042
Fred Drake1f549022000-09-24 05:21:58 +000043 def __init__(self):
44 self.childNodes = []
Martin v. Löwis126f2f62001-03-13 10:50:13 +000045 self.parentNode = self.ownerDocument = None
Fred Drake16f63292000-10-23 18:09:50 +000046 if Node._debug:
Fred Drake1f549022000-09-24 05:21:58 +000047 index = repr(id(self)) + repr(self.__class__)
48 Node.allnodes[index] = repr(self.__dict__)
49 if Node.debug is None:
Fred Drake4ccf4a12000-11-21 22:02:22 +000050 Node.debug = _get_StringIO()
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +000051 #open("debug4.out", "w")
Fred Drake1f549022000-09-24 05:21:58 +000052 Node.debug.write("create %s\n" % index)
Fred Drake55c38192000-06-29 19:39:57 +000053
Fred Drake1f549022000-09-24 05:21:58 +000054 def __getattr__(self, key):
55 if key[0:2] == "__":
Fred Drakef7cf40d2000-12-14 18:16:11 +000056 raise AttributeError, key
Fred Drake55c38192000-06-29 19:39:57 +000057 # getattr should never call getattr!
Fred Drake16f63292000-10-23 18:09:50 +000058 if self.__dict__.has_key("inGetAttr"):
Fred Drake55c38192000-06-29 19:39:57 +000059 del self.inGetAttr
60 raise AttributeError, key
61
Fred Drake1f549022000-09-24 05:21:58 +000062 prefix, attrname = key[:5], key[5:]
63 if prefix == "_get_":
64 self.inGetAttr = 1
Fred Drake16f63292000-10-23 18:09:50 +000065 if hasattr(self, attrname):
Fred Drake55c38192000-06-29 19:39:57 +000066 del self.inGetAttr
Fred Drake16f63292000-10-23 18:09:50 +000067 return (lambda self=self, attrname=attrname:
Fred Drake1f549022000-09-24 05:21:58 +000068 getattr(self, attrname))
Fred Drake55c38192000-06-29 19:39:57 +000069 else:
70 del self.inGetAttr
71 raise AttributeError, key
72 else:
Fred Drake1f549022000-09-24 05:21:58 +000073 self.inGetAttr = 1
Fred Drake55c38192000-06-29 19:39:57 +000074 try:
Fred Drake1f549022000-09-24 05:21:58 +000075 func = getattr(self, "_get_" + key)
Fred Drake55c38192000-06-29 19:39:57 +000076 except AttributeError:
77 raise AttributeError, key
78 del self.inGetAttr
79 return func()
80
Fred Drake1f549022000-09-24 05:21:58 +000081 def __nonzero__(self):
82 return 1
Fred Drake55c38192000-06-29 19:39:57 +000083
Fred Drake1f549022000-09-24 05:21:58 +000084 def toxml(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000085 writer = _get_StringIO()
Fred Drake1f549022000-09-24 05:21:58 +000086 self.writexml(writer)
Fred Drake55c38192000-06-29 19:39:57 +000087 return writer.getvalue()
88
Martin v. Löwis46fa39a2001-02-06 00:14:08 +000089 def toprettyxml(self, indent="\t", newl="\n"):
Martin v. Löwiscb67ea12001-03-31 16:30:40 +000090 # indent = the indentation string to prepend, per level
91 # newl = the newline string to append
92 writer = _get_StringIO()
93 self.writexml(writer, "", indent, newl)
94 return writer.getvalue()
Martin v. Löwis46fa39a2001-02-06 00:14:08 +000095
Fred Drake1f549022000-09-24 05:21:58 +000096 def hasChildNodes(self):
97 if self.childNodes:
98 return 1
99 else:
100 return 0
Fred Drake55c38192000-06-29 19:39:57 +0000101
Fred Drake1f549022000-09-24 05:21:58 +0000102 def _get_firstChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000103 if self.childNodes:
104 return self.childNodes[0]
Paul Prescod73678da2000-07-01 04:58:47 +0000105
Fred Drake1f549022000-09-24 05:21:58 +0000106 def _get_lastChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000107 if self.childNodes:
108 return self.childNodes[-1]
Paul Prescod73678da2000-07-01 04:58:47 +0000109
Fred Drake1f549022000-09-24 05:21:58 +0000110 def insertBefore(self, newChild, refChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000111 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
112 for c in newChild.childNodes:
113 self.insertBefore(c, refChild)
114 ### The DOM does not clearly specify what to return in this case
115 return newChild
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000116 if newChild.nodeType not in self.childNodeTypes:
117 raise HierarchyRequestErr, \
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000118 "%s cannot be child of %s" % (repr(newChild), repr(self))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000119 if newChild.parentNode is not None:
120 newChild.parentNode.removeChild(newChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000121 if refChild is None:
122 self.appendChild(newChild)
123 else:
124 index = self.childNodes.index(refChild)
125 self.childNodes.insert(index, newChild)
126 newChild.nextSibling = refChild
127 refChild.previousSibling = newChild
128 if index:
129 node = self.childNodes[index-1]
130 node.nextSibling = newChild
131 newChild.previousSibling = node
132 else:
133 newChild.previousSibling = None
134 if self._makeParentNodes:
135 newChild.parentNode = self
136 return newChild
Fred Drake55c38192000-06-29 19:39:57 +0000137
Fred Drake1f549022000-09-24 05:21:58 +0000138 def appendChild(self, node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000139 if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
140 for c in node.childNodes:
141 self.appendChild(c)
142 ### The DOM does not clearly specify what to return in this case
143 return node
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000144 if node.nodeType not in self.childNodeTypes:
145 raise HierarchyRequestErr, \
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000146 "%s cannot be child of %s" % (repr(node), repr(self))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000147 if node.parentNode is not None:
148 node.parentNode.removeChild(node)
Fred Drake13a30692000-10-09 20:04:16 +0000149 if self.childNodes:
150 last = self.lastChild
151 node.previousSibling = last
152 last.nextSibling = node
153 else:
154 node.previousSibling = None
155 node.nextSibling = None
Fred Drake1f549022000-09-24 05:21:58 +0000156 self.childNodes.append(node)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000157 if self._makeParentNodes:
158 node.parentNode = self
Paul Prescod73678da2000-07-01 04:58:47 +0000159 return node
160
Fred Drake1f549022000-09-24 05:21:58 +0000161 def replaceChild(self, newChild, oldChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000162 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
163 refChild = oldChild.nextSibling
164 self.removeChild(oldChild)
165 return self.insertBefore(newChild, refChild)
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000166 if newChild.nodeType not in self.childNodeTypes:
167 raise HierarchyRequestErr, \
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000168 "%s cannot be child of %s" % (repr(newChild), repr(self))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000169 if newChild.parentNode is not None:
170 newChild.parentNode.removeChild(newChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000171 if newChild is oldChild:
172 return
Fred Drake1f549022000-09-24 05:21:58 +0000173 index = self.childNodes.index(oldChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000174 self.childNodes[index] = newChild
175 if self._makeParentNodes:
176 newChild.parentNode = self
177 oldChild.parentNode = None
178 newChild.nextSibling = oldChild.nextSibling
179 newChild.previousSibling = oldChild.previousSibling
Martin v. Löwis156c3372000-12-28 18:40:56 +0000180 oldChild.nextSibling = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000181 oldChild.previousSibling = None
Martin v. Löwis156c3372000-12-28 18:40:56 +0000182 if newChild.previousSibling:
183 newChild.previousSibling.nextSibling = newChild
184 if newChild.nextSibling:
185 newChild.nextSibling.previousSibling = newChild
Fred Drake4ccf4a12000-11-21 22:02:22 +0000186 return oldChild
Paul Prescod73678da2000-07-01 04:58:47 +0000187
Fred Drake1f549022000-09-24 05:21:58 +0000188 def removeChild(self, oldChild):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000189 self.childNodes.remove(oldChild)
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000190 if oldChild.nextSibling is not None:
191 oldChild.nextSibling.previousSibling = oldChild.previousSibling
192 if oldChild.previousSibling is not None:
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000193 oldChild.previousSibling.nextSibling = oldChild.nextSibling
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000194 oldChild.nextSibling = oldChild.previousSibling = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000195
Fred Drake4ccf4a12000-11-21 22:02:22 +0000196 if self._makeParentNodes:
197 oldChild.parentNode = None
198 return oldChild
199
200 def normalize(self):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000201 L = []
202 for child in self.childNodes:
203 if child.nodeType == Node.TEXT_NODE:
204 data = child.data
205 if data and L and L[-1].nodeType == child.nodeType:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000206 # collapse text node
207 node = L[-1]
208 node.data = node.nodeValue = node.data + child.data
209 node.nextSibling = child.nextSibling
210 child.unlink()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000211 elif data:
212 if L:
213 L[-1].nextSibling = child
214 child.previousSibling = L[-1]
215 else:
216 child.previousSibling = None
217 L.append(child)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000218 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000219 # empty text node; discard
220 child.unlink()
221 else:
222 if L:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000223 L[-1].nextSibling = child
224 child.previousSibling = L[-1]
Fred Drakef7cf40d2000-12-14 18:16:11 +0000225 else:
226 child.previousSibling = None
227 L.append(child)
228 if child.nodeType == Node.ELEMENT_NODE:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000229 child.normalize()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000230 self.childNodes[:] = L
Paul Prescod73678da2000-07-01 04:58:47 +0000231
Fred Drake1f549022000-09-24 05:21:58 +0000232 def cloneNode(self, deep):
Paul Prescod73678da2000-07-01 04:58:47 +0000233 import new
Fred Drake4ccf4a12000-11-21 22:02:22 +0000234 clone = new.instance(self.__class__, self.__dict__.copy())
235 if self._makeParentNodes:
236 clone.parentNode = None
237 clone.childNodes = []
238 if deep:
239 for child in self.childNodes:
240 clone.appendChild(child.cloneNode(1))
Paul Prescod73678da2000-07-01 04:58:47 +0000241 return clone
Fred Drake55c38192000-06-29 19:39:57 +0000242
Fred Drake25239772001-02-02 19:40:19 +0000243 # DOM Level 3 (Working Draft 2001-Jan-26)
244
245 def isSameNode(self, other):
246 return self is other
247
248 # minidom-specific API:
249
Fred Drake1f549022000-09-24 05:21:58 +0000250 def unlink(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000251 self.parentNode = self.ownerDocument = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000252 for child in self.childNodes:
253 child.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000254 self.childNodes = None
Paul Prescod4221ff02000-10-13 20:11:42 +0000255 self.previousSibling = None
256 self.nextSibling = None
Paul Prescod73678da2000-07-01 04:58:47 +0000257 if Node._debug:
Fred Drake1f549022000-09-24 05:21:58 +0000258 index = repr(id(self)) + repr(self.__class__)
259 self.debug.write("Deleting: %s\n" % index)
Paul Prescod73678da2000-07-01 04:58:47 +0000260 del Node.allnodes[index]
Fred Drake55c38192000-06-29 19:39:57 +0000261
Fred Drake1f549022000-09-24 05:21:58 +0000262def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000263 "Writes datachars to writer."
Fred Drake4ccf4a12000-11-21 22:02:22 +0000264 replace = _string.replace
265 data = replace(data, "&", "&amp;")
266 data = replace(data, "<", "&lt;")
267 data = replace(data, "\"", "&quot;")
268 data = replace(data, ">", "&gt;")
Fred Drake55c38192000-06-29 19:39:57 +0000269 writer.write(data)
270
Fred Drake1f549022000-09-24 05:21:58 +0000271def _getElementsByTagNameHelper(parent, name, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000272 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000273 if node.nodeType == Node.ELEMENT_NODE and \
274 (name == "*" or node.tagName == name):
275 rc.append(node)
276 _getElementsByTagNameHelper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000277 return rc
278
Fred Drake1f549022000-09-24 05:21:58 +0000279def _getElementsByTagNameNSHelper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000280 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000281 if node.nodeType == Node.ELEMENT_NODE:
Martin v. Löwised525fb2001-06-03 14:06:42 +0000282 if ((localName == "*" or node.localName == localName) and
Fred Drake1f549022000-09-24 05:21:58 +0000283 (nsURI == "*" or node.namespaceURI == nsURI)):
284 rc.append(node)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000285 _getElementsByTagNameNSHelper(node, nsURI, localName, rc)
286 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000287
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000288class DocumentFragment(Node):
289 nodeType = Node.DOCUMENT_FRAGMENT_NODE
290 nodeName = "#document-fragment"
291 nodeValue = None
292 attributes = None
293 parentNode = None
294 childNodeTypes = (Node.ELEMENT_NODE,
295 Node.TEXT_NODE,
296 Node.CDATA_SECTION_NODE,
297 Node.ENTITY_REFERENCE_NODE,
298 Node.PROCESSING_INSTRUCTION_NODE,
299 Node.COMMENT_NODE,
300 Node.NOTATION_NODE)
301
302
Fred Drake55c38192000-06-29 19:39:57 +0000303class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000304 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000305 attributes = None
306 ownerElement = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000307 childNodeTypes = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000308
Fred Drake1f549022000-09-24 05:21:58 +0000309 def __init__(self, qName, namespaceURI="", localName=None, prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000310 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000311 d = self.__dict__
312 d["localName"] = localName or qName
313 d["nodeName"] = d["name"] = qName
314 d["namespaceURI"] = namespaceURI
315 d["prefix"] = prefix
Fred Drake1f549022000-09-24 05:21:58 +0000316 Node.__init__(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000317 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000318
Fred Drake1f549022000-09-24 05:21:58 +0000319 def __setattr__(self, name, value):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000320 d = self.__dict__
Fred Drake1f549022000-09-24 05:21:58 +0000321 if name in ("value", "nodeValue"):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000322 d["value"] = d["nodeValue"] = value
323 elif name in ("name", "nodeName"):
324 d["name"] = d["nodeName"] = value
Fred Drake55c38192000-06-29 19:39:57 +0000325 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000326 d[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000327
Fred Drake4ccf4a12000-11-21 22:02:22 +0000328 def cloneNode(self, deep):
329 clone = Node.cloneNode(self, deep)
330 if clone.__dict__.has_key("ownerElement"):
331 del clone.ownerElement
332 return clone
333
Fred Drakef7cf40d2000-12-14 18:16:11 +0000334
335class NamedNodeMap:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000336 """The attribute list is a transient interface to the underlying
337 dictionaries. Mutations here will change the underlying element's
Fred Drakef7cf40d2000-12-14 18:16:11 +0000338 dictionary.
339
340 Ordering is imposed artificially and does not reflect the order of
341 attributes as found in an input document.
342 """
Fred Drake4ccf4a12000-11-21 22:02:22 +0000343
Fred Drake1f549022000-09-24 05:21:58 +0000344 def __init__(self, attrs, attrsNS):
345 self._attrs = attrs
346 self._attrsNS = attrsNS
Fred Drakef7cf40d2000-12-14 18:16:11 +0000347
348 def __getattr__(self, name):
349 if name == "length":
350 return len(self._attrs)
351 raise AttributeError, name
Fred Drake55c38192000-06-29 19:39:57 +0000352
Fred Drake1f549022000-09-24 05:21:58 +0000353 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000354 try:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000355 return self[self._attrs.keys()[index]]
Fred Drake55c38192000-06-29 19:39:57 +0000356 except IndexError:
357 return None
Fred Drake55c38192000-06-29 19:39:57 +0000358
Fred Drake1f549022000-09-24 05:21:58 +0000359 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000360 L = []
361 for node in self._attrs.values():
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000362 L.append((node.nodeName, node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000363 return L
Fred Drake1f549022000-09-24 05:21:58 +0000364
365 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000366 L = []
367 for node in self._attrs.values():
368 L.append(((node.URI, node.localName), node.value))
369 return L
Fred Drake16f63292000-10-23 18:09:50 +0000370
Fred Drake1f549022000-09-24 05:21:58 +0000371 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000372 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000373
Fred Drake1f549022000-09-24 05:21:58 +0000374 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000375 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000376
Fred Drake1f549022000-09-24 05:21:58 +0000377 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000378 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000379
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000380 def get(self, name, value = None):
381 return self._attrs.get(name, value)
382
Fred Drake1f549022000-09-24 05:21:58 +0000383 def __len__(self):
Fred Drake55c38192000-06-29 19:39:57 +0000384 return self.length
385
Fred Drake1f549022000-09-24 05:21:58 +0000386 def __cmp__(self, other):
387 if self._attrs is getattr(other, "_attrs", None):
Fred Drake55c38192000-06-29 19:39:57 +0000388 return 0
Fred Drake16f63292000-10-23 18:09:50 +0000389 else:
Fred Drake1f549022000-09-24 05:21:58 +0000390 return cmp(id(self), id(other))
Fred Drake55c38192000-06-29 19:39:57 +0000391
392 #FIXME: is it appropriate to return .value?
Fred Drake1f549022000-09-24 05:21:58 +0000393 def __getitem__(self, attname_or_tuple):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000394 if type(attname_or_tuple) is _TupleType:
Paul Prescod73678da2000-07-01 04:58:47 +0000395 return self._attrsNS[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000396 else:
Paul Prescod73678da2000-07-01 04:58:47 +0000397 return self._attrs[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000398
Paul Prescod1e688272000-07-01 19:21:47 +0000399 # same as set
Fred Drake1f549022000-09-24 05:21:58 +0000400 def __setitem__(self, attname, value):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000401 if type(value) in _StringTypes:
Fred Drake1f549022000-09-24 05:21:58 +0000402 node = Attr(attname)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000403 node.value = value
Paul Prescod1e688272000-07-01 19:21:47 +0000404 else:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000405 if not isinstance(value, Attr):
406 raise TypeError, "value must be a string or Attr object"
Fred Drake1f549022000-09-24 05:21:58 +0000407 node = value
Fred Drakef7cf40d2000-12-14 18:16:11 +0000408 self.setNamedItem(node)
409
410 def setNamedItem(self, node):
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000411 if not isinstance(node, Attr):
412 raise HierarchyRequestErr, \
413 "%s cannot be child of %s" % (repr(node), repr(self))
Fred Drakef7cf40d2000-12-14 18:16:11 +0000414 old = self._attrs.get(node.name)
Paul Prescod1e688272000-07-01 19:21:47 +0000415 if old:
416 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000417 self._attrs[node.name] = node
418 self._attrsNS[(node.namespaceURI, node.localName)] = node
Fred Drakef7cf40d2000-12-14 18:16:11 +0000419 return old
420
421 def setNamedItemNS(self, node):
422 return self.setNamedItem(node)
Paul Prescod73678da2000-07-01 04:58:47 +0000423
Fred Drake1f549022000-09-24 05:21:58 +0000424 def __delitem__(self, attname_or_tuple):
425 node = self[attname_or_tuple]
Paul Prescod73678da2000-07-01 04:58:47 +0000426 node.unlink()
427 del self._attrs[node.name]
428 del self._attrsNS[(node.namespaceURI, node.localName)]
Fred Drakef7cf40d2000-12-14 18:16:11 +0000429 self.length = len(self._attrs)
430
431AttributeList = NamedNodeMap
432
Fred Drake1f549022000-09-24 05:21:58 +0000433
Martin v. Löwisa2fda0d2000-10-07 12:10:28 +0000434class Element(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000435 nodeType = Node.ELEMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000436 nextSibling = None
437 previousSibling = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000438 childNodeTypes = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
439 Node.COMMENT_NODE, Node.TEXT_NODE,
440 Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000441
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000442 def __init__(self, tagName, namespaceURI=None, prefix="",
Fred Drake1f549022000-09-24 05:21:58 +0000443 localName=None):
444 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000445 self.tagName = self.nodeName = tagName
Fred Drake1f549022000-09-24 05:21:58 +0000446 self.localName = localName or tagName
447 self.prefix = prefix
448 self.namespaceURI = namespaceURI
449 self.nodeValue = None
Fred Drake55c38192000-06-29 19:39:57 +0000450
Fred Drake4ccf4a12000-11-21 22:02:22 +0000451 self._attrs = {} # attributes are double-indexed:
452 self._attrsNS = {} # tagName -> Attribute
453 # URI,localName -> Attribute
454 # in the future: consider lazy generation
455 # of attribute objects this is too tricky
456 # for now because of headaches with
457 # namespaces.
458
459 def cloneNode(self, deep):
460 clone = Node.cloneNode(self, deep)
461 clone._attrs = {}
462 clone._attrsNS = {}
463 for attr in self._attrs.values():
464 node = attr.cloneNode(1)
465 clone._attrs[node.name] = node
466 clone._attrsNS[(node.namespaceURI, node.localName)] = node
467 node.ownerElement = clone
468 return clone
469
470 def unlink(self):
471 for attr in self._attrs.values():
472 attr.unlink()
473 self._attrs = None
474 self._attrsNS = None
475 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000476
Fred Drake1f549022000-09-24 05:21:58 +0000477 def getAttribute(self, attname):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000478 try:
479 return self._attrs[attname].value
480 except KeyError:
481 return ""
Fred Drake55c38192000-06-29 19:39:57 +0000482
Fred Drake1f549022000-09-24 05:21:58 +0000483 def getAttributeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000484 try:
485 return self._attrsNS[(namespaceURI, localName)].value
486 except KeyError:
487 return ""
Fred Drake1f549022000-09-24 05:21:58 +0000488
489 def setAttribute(self, attname, value):
490 attr = Attr(attname)
Fred Drake55c38192000-06-29 19:39:57 +0000491 # for performance
Fred Drake1f549022000-09-24 05:21:58 +0000492 attr.__dict__["value"] = attr.__dict__["nodeValue"] = value
493 self.setAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000494
Fred Drake1f549022000-09-24 05:21:58 +0000495 def setAttributeNS(self, namespaceURI, qualifiedName, value):
496 prefix, localname = _nssplit(qualifiedName)
Fred Drake55c38192000-06-29 19:39:57 +0000497 # for performance
Fred Drake1f549022000-09-24 05:21:58 +0000498 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
499 attr.__dict__["value"] = attr.__dict__["nodeValue"] = value
500 self.setAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000501
Fred Drake1f549022000-09-24 05:21:58 +0000502 def getAttributeNode(self, attrname):
503 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000504
Fred Drake1f549022000-09-24 05:21:58 +0000505 def getAttributeNodeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000506 return self._attrsNS.get((namespaceURI, localName))
Paul Prescod73678da2000-07-01 04:58:47 +0000507
Fred Drake1f549022000-09-24 05:21:58 +0000508 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000509 if attr.ownerElement not in (None, self):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000510 raise xml.dom.InuseAttributeErr("attribute node already owned")
Fred Drake1f549022000-09-24 05:21:58 +0000511 old = self._attrs.get(attr.name, None)
Paul Prescod73678da2000-07-01 04:58:47 +0000512 if old:
513 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000514 self._attrs[attr.name] = attr
515 self._attrsNS[(attr.namespaceURI, attr.localName)] = attr
Fred Drake4ccf4a12000-11-21 22:02:22 +0000516
517 # This creates a circular reference, but Element.unlink()
518 # breaks the cycle since the references to the attribute
519 # dictionaries are tossed.
520 attr.ownerElement = self
521
522 if old is not attr:
523 # It might have already been part of this node, in which case
524 # it doesn't represent a change, and should not be returned.
525 return old
Fred Drake55c38192000-06-29 19:39:57 +0000526
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000527 setAttributeNodeNS = setAttributeNode
528
Fred Drake1f549022000-09-24 05:21:58 +0000529 def removeAttribute(self, name):
Paul Prescod73678da2000-07-01 04:58:47 +0000530 attr = self._attrs[name]
Fred Drake1f549022000-09-24 05:21:58 +0000531 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000532
Fred Drake1f549022000-09-24 05:21:58 +0000533 def removeAttributeNS(self, namespaceURI, localName):
Paul Prescod73678da2000-07-01 04:58:47 +0000534 attr = self._attrsNS[(namespaceURI, localName)]
Fred Drake1f549022000-09-24 05:21:58 +0000535 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000536
Fred Drake1f549022000-09-24 05:21:58 +0000537 def removeAttributeNode(self, node):
Paul Prescod73678da2000-07-01 04:58:47 +0000538 node.unlink()
539 del self._attrs[node.name]
540 del self._attrsNS[(node.namespaceURI, node.localName)]
Fred Drake16f63292000-10-23 18:09:50 +0000541
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000542 removeAttributeNodeNS = removeAttributeNode
543
Martin v. Löwis156c3372000-12-28 18:40:56 +0000544 def hasAttribute(self, name):
545 return self._attrs.has_key(name)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000546
Martin v. Löwis156c3372000-12-28 18:40:56 +0000547 def hasAttributeNS(self, namespaceURI, localName):
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000548 return self._attrsNS.has_key((namespaceURI, localName))
549
Fred Drake1f549022000-09-24 05:21:58 +0000550 def getElementsByTagName(self, name):
551 return _getElementsByTagNameHelper(self, name, [])
Fred Drake55c38192000-06-29 19:39:57 +0000552
Fred Drake1f549022000-09-24 05:21:58 +0000553 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwised525fb2001-06-03 14:06:42 +0000554 rc = []
555 _getElementsByTagNameNSHelper(self, namespaceURI, localName, rc)
556 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000557
Fred Drake1f549022000-09-24 05:21:58 +0000558 def __repr__(self):
559 return "<DOM Element: %s at %s>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000560
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000561 def writexml(self, writer, indent="", addindent="", newl=""):
562 # indent = current indentation
563 # addindent = indentation to add to higher levels
564 # newl = newline string
565 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000566
Fred Drake4ccf4a12000-11-21 22:02:22 +0000567 attrs = self._get_attributes()
568 a_names = attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000569 a_names.sort()
570
571 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000572 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000573 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000574 writer.write("\"")
575 if self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000576 writer.write(">%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000577 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000578 node.writexml(writer,indent+addindent,addindent,newl)
579 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
Fred Drake55c38192000-06-29 19:39:57 +0000580 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000581 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000582
Fred Drake1f549022000-09-24 05:21:58 +0000583 def _get_attributes(self):
584 return AttributeList(self._attrs, self._attrsNS)
Fred Drake55c38192000-06-29 19:39:57 +0000585
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000586 def hasAttributes(self):
587 if self._attrs or self._attrsNS:
588 return 1
589 else:
590 return 0
591
Fred Drake1f549022000-09-24 05:21:58 +0000592class Comment(Node):
593 nodeType = Node.COMMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000594 nodeName = "#comment"
595 attributes = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000596 childNodeTypes = ()
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000597
Fred Drake1f549022000-09-24 05:21:58 +0000598 def __init__(self, data):
599 Node.__init__(self)
600 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000601
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000602 def writexml(self, writer, indent="", addindent="", newl=""):
603 writer.write("%s<!--%s-->%s" % (indent,self.data,newl))
Fred Drake1f549022000-09-24 05:21:58 +0000604
605class ProcessingInstruction(Node):
606 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000607 attributes = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000608 childNodeTypes = ()
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000609
Fred Drake1f549022000-09-24 05:21:58 +0000610 def __init__(self, target, data):
611 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000612 self.target = self.nodeName = target
613 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000614
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000615 def writexml(self, writer, indent="", addindent="", newl=""):
616 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000617
Fred Drake87432f42001-04-04 14:09:46 +0000618class CharacterData(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000619 def __init__(self, data):
Fred Drakedaa823a2001-01-08 04:04:34 +0000620 if type(data) not in _StringTypes:
621 raise TypeError, "node contents must be a string"
Fred Drake1f549022000-09-24 05:21:58 +0000622 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000623 self.data = self.nodeValue = data
Fred Drake33d2b842001-04-04 15:15:18 +0000624 self.length = len(data)
Fred Drake87432f42001-04-04 14:09:46 +0000625
Fred Drake55c38192000-06-29 19:39:57 +0000626 def __repr__(self):
Fred Drake1f549022000-09-24 05:21:58 +0000627 if len(self.data) > 10:
628 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000629 else:
Fred Drake1f549022000-09-24 05:21:58 +0000630 dotdotdot = ""
Fred Drake87432f42001-04-04 14:09:46 +0000631 return "<DOM %s node \"%s%s\">" % (
632 self.__class__.__name__, self.data[0:10], dotdotdot)
633
634 def substringData(self, offset, count):
635 if offset < 0:
636 raise xml.dom.IndexSizeErr("offset cannot be negative")
637 if offset >= len(self.data):
638 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
639 if count < 0:
640 raise xml.dom.IndexSizeErr("count cannot be negative")
641 return self.data[offset:offset+count]
642
643 def appendData(self, arg):
644 self.data = self.data + arg
645 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000646 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000647
648 def insertData(self, offset, arg):
649 if offset < 0:
650 raise xml.dom.IndexSizeErr("offset cannot be negative")
651 if offset >= len(self.data):
652 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
653 if arg:
654 self.data = "%s%s%s" % (
655 self.data[:offset], arg, self.data[offset:])
656 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000657 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000658
659 def deleteData(self, offset, count):
660 if offset < 0:
661 raise xml.dom.IndexSizeErr("offset cannot be negative")
662 if offset >= len(self.data):
663 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
664 if count < 0:
665 raise xml.dom.IndexSizeErr("count cannot be negative")
666 if count:
667 self.data = self.data[:offset] + self.data[offset+count:]
668 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000669 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000670
671 def replaceData(self, offset, count, arg):
672 if offset < 0:
673 raise xml.dom.IndexSizeErr("offset cannot be negative")
674 if offset >= len(self.data):
675 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
676 if count < 0:
677 raise xml.dom.IndexSizeErr("count cannot be negative")
678 if count:
679 self.data = "%s%s%s" % (
680 self.data[:offset], arg, self.data[offset+count:])
681 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000682 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000683
684class Text(CharacterData):
685 nodeType = Node.TEXT_NODE
686 nodeName = "#text"
687 attributes = None
688 childNodeTypes = ()
Fred Drake55c38192000-06-29 19:39:57 +0000689
Fred Drakef7cf40d2000-12-14 18:16:11 +0000690 def splitText(self, offset):
691 if offset < 0 or offset > len(self.data):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000692 raise xml.dom.IndexSizeErr("illegal offset value")
Fred Drakef7cf40d2000-12-14 18:16:11 +0000693 newText = Text(self.data[offset:])
694 next = self.nextSibling
695 if self.parentNode and self in self.parentNode.childNodes:
696 if next is None:
697 self.parentNode.appendChild(newText)
698 else:
699 self.parentNode.insertBefore(newText, next)
700 self.data = self.data[:offset]
Fred Drake33d2b842001-04-04 15:15:18 +0000701 self.nodeValue = self.data
702 self.length = len(self.data)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000703 return newText
704
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000705 def writexml(self, writer, indent="", addindent="", newl=""):
706 _write_data(writer, "%s%s%s"%(indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000707
Fred Drake87432f42001-04-04 14:09:46 +0000708
709class CDATASection(Text):
710 nodeType = Node.CDATA_SECTION_NODE
711 nodeName = "#cdata-section"
712
713 def writexml(self, writer, indent="", addindent="", newl=""):
714 _write_data(writer, "<![CDATA[%s]]>" % self.data)
715
716
Fred Drake1f549022000-09-24 05:21:58 +0000717def _nssplit(qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000718 fields = _string.split(qualifiedName, ':', 1)
Paul Prescod73678da2000-07-01 04:58:47 +0000719 if len(fields) == 2:
720 return fields
721 elif len(fields) == 1:
Fred Drake1f549022000-09-24 05:21:58 +0000722 return ('', fields[0])
Paul Prescod73678da2000-07-01 04:58:47 +0000723
Fred Drakef7cf40d2000-12-14 18:16:11 +0000724
725class DocumentType(Node):
726 nodeType = Node.DOCUMENT_TYPE_NODE
727 nodeValue = None
728 attributes = None
729 name = None
730 publicId = None
731 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +0000732 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000733 entities = None
734 notations = None
735
736 def __init__(self, qualifiedName):
737 Node.__init__(self)
738 if qualifiedName:
739 prefix, localname = _nssplit(qualifiedName)
740 self.name = localname
741
742
743class DOMImplementation:
744 def hasFeature(self, feature, version):
745 if version not in ("1.0", "2.0"):
746 return 0
747 feature = _string.lower(feature)
748 return feature == "core"
749
750 def createDocument(self, namespaceURI, qualifiedName, doctype):
751 if doctype and doctype.parentNode is not None:
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000752 raise xml.dom.WrongDocumentErr(
753 "doctype object owned by another DOM tree")
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000754 doc = self._createDocument()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000755 if doctype is None:
756 doctype = self.createDocumentType(qualifiedName, None, None)
Martin v. Löwisb417be22001-02-06 01:16:06 +0000757 if not qualifiedName:
758 # The spec is unclear what to raise here; SyntaxErr
759 # would be the other obvious candidate. Since Xerces raises
760 # InvalidCharacterErr, and since SyntaxErr is not listed
761 # for createDocument, that seems to be the better choice.
762 # XXX: need to check for illegal characters here and in
763 # createElement.
764 raise xml.dom.InvalidCharacterErr("Element with no name")
765 prefix, localname = _nssplit(qualifiedName)
766 if prefix == "xml" \
767 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
768 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
769 if prefix and not namespaceURI:
770 raise xml.dom.NamespaceErr(
771 "illegal use of prefix without namespaces")
772 element = doc.createElementNS(namespaceURI, qualifiedName)
773 doc.appendChild(element)
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000774 doctype.parentNode = doctype.ownerDocument = doc
Fred Drakef7cf40d2000-12-14 18:16:11 +0000775 doc.doctype = doctype
776 doc.implementation = self
777 return doc
778
779 def createDocumentType(self, qualifiedName, publicId, systemId):
780 doctype = DocumentType(qualifiedName)
781 doctype.publicId = publicId
782 doctype.systemId = systemId
783 return doctype
784
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000785 # internal
786 def _createDocument(self):
787 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000788
Fred Drake1f549022000-09-24 05:21:58 +0000789class Document(Node):
790 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000791 nodeName = "#document"
792 nodeValue = None
793 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000794 doctype = None
795 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000796 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000797
798 implementation = DOMImplementation()
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000799 childNodeTypes = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
800 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
Fred Drake55c38192000-06-29 19:39:57 +0000801
Fred Drake1f549022000-09-24 05:21:58 +0000802 def appendChild(self, node):
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000803 if node.nodeType not in self.childNodeTypes:
804 raise HierarchyRequestErr, \
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000805 "%s cannot be child of %s" % (repr(node), repr(self))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000806 if node.parentNode is not None:
807 node.parentNode.removeChild(node)
808
Fred Drakef7cf40d2000-12-14 18:16:11 +0000809 if node.nodeType == Node.ELEMENT_NODE \
810 and self._get_documentElement():
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000811 raise xml.dom.HierarchyRequestErr(
812 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000813 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +0000814
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000815 def removeChild(self, oldChild):
816 self.childNodes.remove(oldChild)
817 oldChild.nextSibling = oldChild.previousSibling = None
818 oldChild.parentNode = None
819 if self.documentElement is oldChild:
820 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000821
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000822 return oldChild
823
Fred Drakef7cf40d2000-12-14 18:16:11 +0000824 def _get_documentElement(self):
825 for node in self.childNodes:
826 if node.nodeType == Node.ELEMENT_NODE:
827 return node
828
829 def unlink(self):
830 if self.doctype is not None:
831 self.doctype.unlink()
832 self.doctype = None
833 Node.unlink(self)
834
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000835 def createDocumentFragment(self):
836 d = DocumentFragment()
837 d.ownerDoc = self
838 return d
Fred Drake55c38192000-06-29 19:39:57 +0000839
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000840 def createElement(self, tagName):
841 e = Element(tagName)
842 e.ownerDocument = self
843 return e
Fred Drake55c38192000-06-29 19:39:57 +0000844
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000845 def createTextNode(self, data):
846 t = Text(data)
847 t.ownerDocument = self
848 return t
Fred Drake55c38192000-06-29 19:39:57 +0000849
Fred Drake87432f42001-04-04 14:09:46 +0000850 def createCDATASection(self, data):
851 c = CDATASection(data)
852 c.ownerDocument = self
853 return c
854
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000855 def createComment(self, data):
856 c = Comment(data)
857 c.ownerDocument = self
858 return c
Fred Drake55c38192000-06-29 19:39:57 +0000859
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000860 def createProcessingInstruction(self, target, data):
861 p = ProcessingInstruction(target, data)
862 p.ownerDocument = self
863 return p
864
865 def createAttribute(self, qName):
866 a = Attr(qName)
867 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +0000868 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000869 return a
Fred Drake55c38192000-06-29 19:39:57 +0000870
871 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000872 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000873 e = Element(qualifiedName, namespaceURI, prefix, localName)
874 e.ownerDocument = self
875 return e
Fred Drake55c38192000-06-29 19:39:57 +0000876
877 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000878 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000879 a = Attr(qualifiedName, namespaceURI, localName, prefix)
880 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +0000881 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000882 return a
Fred Drake55c38192000-06-29 19:39:57 +0000883
Fred Drake1f549022000-09-24 05:21:58 +0000884 def getElementsByTagNameNS(self, namespaceURI, localName):
Martin v. Löwised525fb2001-06-03 14:06:42 +0000885 rc = []
886 _getElementsByTagNameNSHelper(self, namespaceURI, localName, rc)
887 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000888
Fred Drake1f549022000-09-24 05:21:58 +0000889 def getElementsByTagName(self, name):
890 rc = []
891 _getElementsByTagNameHelper(self, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000892 return rc
893
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000894 def writexml(self, writer, indent="", addindent="", newl=""):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000895 writer.write('<?xml version="1.0" ?>\n')
Fred Drake55c38192000-06-29 19:39:57 +0000896 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000897 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +0000898
Fred Drake4ccf4a12000-11-21 22:02:22 +0000899def _get_StringIO():
Fred Drakef7cf40d2000-12-14 18:16:11 +0000900 # we can't use cStringIO since it doesn't support Unicode strings
901 from StringIO import StringIO
Fred Drake4ccf4a12000-11-21 22:02:22 +0000902 return StringIO()
903
Fred Drake1f549022000-09-24 05:21:58 +0000904def _doparse(func, args, kwargs):
905 events = apply(func, args, kwargs)
906 toktype, rootNode = events.getEvent()
907 events.expandNode(rootNode)
Martin v. Löwisb417be22001-02-06 01:16:06 +0000908 events.clear()
Fred Drake55c38192000-06-29 19:39:57 +0000909 return rootNode
910
Fred Drake1f549022000-09-24 05:21:58 +0000911def parse(*args, **kwargs):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000912 """Parse a file into a DOM by filename or file object."""
Fred Drake4ccf4a12000-11-21 22:02:22 +0000913 from xml.dom import pulldom
Fred Drake1f549022000-09-24 05:21:58 +0000914 return _doparse(pulldom.parse, args, kwargs)
Fred Drake55c38192000-06-29 19:39:57 +0000915
Fred Drake1f549022000-09-24 05:21:58 +0000916def parseString(*args, **kwargs):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000917 """Parse a file into a DOM from a string."""
Fred Drake4ccf4a12000-11-21 22:02:22 +0000918 from xml.dom import pulldom
Fred Drake1f549022000-09-24 05:21:58 +0000919 return _doparse(pulldom.parseString, args, kwargs)
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +0000920
921def getDOMImplementation():
922 return Document.implementation