blob: 9db9ec1f01a7e4c32333b276f34cc354be8fe53c [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):
Fred Drakefbe7b4f2001-07-04 06:25:53 +0000554 return _getElementsByTagNameNSHelper(self, namespaceURI, localName, [])
Fred Drake55c38192000-06-29 19:39:57 +0000555
Fred Drake1f549022000-09-24 05:21:58 +0000556 def __repr__(self):
557 return "<DOM Element: %s at %s>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000558
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000559 def writexml(self, writer, indent="", addindent="", newl=""):
560 # indent = current indentation
561 # addindent = indentation to add to higher levels
562 # newl = newline string
563 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000564
Fred Drake4ccf4a12000-11-21 22:02:22 +0000565 attrs = self._get_attributes()
566 a_names = attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000567 a_names.sort()
568
569 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000570 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000571 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000572 writer.write("\"")
573 if self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000574 writer.write(">%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000575 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000576 node.writexml(writer,indent+addindent,addindent,newl)
577 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
Fred Drake55c38192000-06-29 19:39:57 +0000578 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000579 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000580
Fred Drake1f549022000-09-24 05:21:58 +0000581 def _get_attributes(self):
582 return AttributeList(self._attrs, self._attrsNS)
Fred Drake55c38192000-06-29 19:39:57 +0000583
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000584 def hasAttributes(self):
585 if self._attrs or self._attrsNS:
586 return 1
587 else:
588 return 0
589
Fred Drake1f549022000-09-24 05:21:58 +0000590class Comment(Node):
591 nodeType = Node.COMMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000592 nodeName = "#comment"
593 attributes = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000594 childNodeTypes = ()
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000595
Fred Drake1f549022000-09-24 05:21:58 +0000596 def __init__(self, data):
597 Node.__init__(self)
598 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000599
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000600 def writexml(self, writer, indent="", addindent="", newl=""):
601 writer.write("%s<!--%s-->%s" % (indent,self.data,newl))
Fred Drake1f549022000-09-24 05:21:58 +0000602
603class ProcessingInstruction(Node):
604 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000605 attributes = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000606 childNodeTypes = ()
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000607
Fred Drake1f549022000-09-24 05:21:58 +0000608 def __init__(self, target, data):
609 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000610 self.target = self.nodeName = target
611 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000612
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000613 def writexml(self, writer, indent="", addindent="", newl=""):
614 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000615
Fred Drake87432f42001-04-04 14:09:46 +0000616class CharacterData(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000617 def __init__(self, data):
Fred Drakedaa823a2001-01-08 04:04:34 +0000618 if type(data) not in _StringTypes:
619 raise TypeError, "node contents must be a string"
Fred Drake1f549022000-09-24 05:21:58 +0000620 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000621 self.data = self.nodeValue = data
Fred Drake33d2b842001-04-04 15:15:18 +0000622 self.length = len(data)
Fred Drake87432f42001-04-04 14:09:46 +0000623
Fred Drake55c38192000-06-29 19:39:57 +0000624 def __repr__(self):
Fred Drake1f549022000-09-24 05:21:58 +0000625 if len(self.data) > 10:
626 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000627 else:
Fred Drake1f549022000-09-24 05:21:58 +0000628 dotdotdot = ""
Fred Drake87432f42001-04-04 14:09:46 +0000629 return "<DOM %s node \"%s%s\">" % (
630 self.__class__.__name__, self.data[0:10], dotdotdot)
631
632 def substringData(self, offset, count):
633 if offset < 0:
634 raise xml.dom.IndexSizeErr("offset cannot be negative")
635 if offset >= len(self.data):
636 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
637 if count < 0:
638 raise xml.dom.IndexSizeErr("count cannot be negative")
639 return self.data[offset:offset+count]
640
641 def appendData(self, arg):
642 self.data = self.data + arg
643 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000644 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000645
646 def insertData(self, offset, arg):
647 if offset < 0:
648 raise xml.dom.IndexSizeErr("offset cannot be negative")
649 if offset >= len(self.data):
650 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
651 if arg:
652 self.data = "%s%s%s" % (
653 self.data[:offset], arg, self.data[offset:])
654 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000655 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000656
657 def deleteData(self, offset, count):
658 if offset < 0:
659 raise xml.dom.IndexSizeErr("offset cannot be negative")
660 if offset >= len(self.data):
661 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
662 if count < 0:
663 raise xml.dom.IndexSizeErr("count cannot be negative")
664 if count:
665 self.data = self.data[:offset] + self.data[offset+count:]
666 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000667 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000668
669 def replaceData(self, offset, count, arg):
670 if offset < 0:
671 raise xml.dom.IndexSizeErr("offset cannot be negative")
672 if offset >= len(self.data):
673 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
674 if count < 0:
675 raise xml.dom.IndexSizeErr("count cannot be negative")
676 if count:
677 self.data = "%s%s%s" % (
678 self.data[:offset], arg, self.data[offset+count:])
679 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000680 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000681
682class Text(CharacterData):
683 nodeType = Node.TEXT_NODE
684 nodeName = "#text"
685 attributes = None
686 childNodeTypes = ()
Fred Drake55c38192000-06-29 19:39:57 +0000687
Fred Drakef7cf40d2000-12-14 18:16:11 +0000688 def splitText(self, offset):
689 if offset < 0 or offset > len(self.data):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000690 raise xml.dom.IndexSizeErr("illegal offset value")
Fred Drakef7cf40d2000-12-14 18:16:11 +0000691 newText = Text(self.data[offset:])
692 next = self.nextSibling
693 if self.parentNode and self in self.parentNode.childNodes:
694 if next is None:
695 self.parentNode.appendChild(newText)
696 else:
697 self.parentNode.insertBefore(newText, next)
698 self.data = self.data[:offset]
Fred Drake33d2b842001-04-04 15:15:18 +0000699 self.nodeValue = self.data
700 self.length = len(self.data)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000701 return newText
702
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000703 def writexml(self, writer, indent="", addindent="", newl=""):
704 _write_data(writer, "%s%s%s"%(indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000705
Fred Drake87432f42001-04-04 14:09:46 +0000706
707class CDATASection(Text):
708 nodeType = Node.CDATA_SECTION_NODE
709 nodeName = "#cdata-section"
710
711 def writexml(self, writer, indent="", addindent="", newl=""):
Guido van Rossum5b5e0b92001-09-19 13:28:25 +0000712 writer.write("<![CDATA[%s]]>" % self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000713
714
Fred Drake1f549022000-09-24 05:21:58 +0000715def _nssplit(qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000716 fields = _string.split(qualifiedName, ':', 1)
Paul Prescod73678da2000-07-01 04:58:47 +0000717 if len(fields) == 2:
718 return fields
719 elif len(fields) == 1:
Fred Drake1f549022000-09-24 05:21:58 +0000720 return ('', fields[0])
Paul Prescod73678da2000-07-01 04:58:47 +0000721
Fred Drakef7cf40d2000-12-14 18:16:11 +0000722
723class DocumentType(Node):
724 nodeType = Node.DOCUMENT_TYPE_NODE
725 nodeValue = None
726 attributes = None
727 name = None
728 publicId = None
729 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +0000730 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000731 entities = None
732 notations = None
733
734 def __init__(self, qualifiedName):
735 Node.__init__(self)
736 if qualifiedName:
737 prefix, localname = _nssplit(qualifiedName)
738 self.name = localname
739
740
741class DOMImplementation:
742 def hasFeature(self, feature, version):
743 if version not in ("1.0", "2.0"):
744 return 0
745 feature = _string.lower(feature)
746 return feature == "core"
747
748 def createDocument(self, namespaceURI, qualifiedName, doctype):
749 if doctype and doctype.parentNode is not None:
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000750 raise xml.dom.WrongDocumentErr(
751 "doctype object owned by another DOM tree")
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000752 doc = self._createDocument()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000753 if doctype is None:
754 doctype = self.createDocumentType(qualifiedName, None, None)
Martin v. Löwisb417be22001-02-06 01:16:06 +0000755 if not qualifiedName:
756 # The spec is unclear what to raise here; SyntaxErr
757 # would be the other obvious candidate. Since Xerces raises
758 # InvalidCharacterErr, and since SyntaxErr is not listed
759 # for createDocument, that seems to be the better choice.
760 # XXX: need to check for illegal characters here and in
761 # createElement.
762 raise xml.dom.InvalidCharacterErr("Element with no name")
763 prefix, localname = _nssplit(qualifiedName)
764 if prefix == "xml" \
765 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
766 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
767 if prefix and not namespaceURI:
768 raise xml.dom.NamespaceErr(
769 "illegal use of prefix without namespaces")
770 element = doc.createElementNS(namespaceURI, qualifiedName)
771 doc.appendChild(element)
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000772 doctype.parentNode = doctype.ownerDocument = doc
Fred Drakef7cf40d2000-12-14 18:16:11 +0000773 doc.doctype = doctype
774 doc.implementation = self
775 return doc
776
777 def createDocumentType(self, qualifiedName, publicId, systemId):
778 doctype = DocumentType(qualifiedName)
779 doctype.publicId = publicId
780 doctype.systemId = systemId
781 return doctype
782
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000783 # internal
784 def _createDocument(self):
785 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000786
Fred Drake1f549022000-09-24 05:21:58 +0000787class Document(Node):
788 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000789 nodeName = "#document"
790 nodeValue = None
791 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000792 doctype = None
793 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000794 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000795
796 implementation = DOMImplementation()
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000797 childNodeTypes = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
798 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
Fred Drake55c38192000-06-29 19:39:57 +0000799
Fred Drake1f549022000-09-24 05:21:58 +0000800 def appendChild(self, node):
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000801 if node.nodeType not in self.childNodeTypes:
802 raise HierarchyRequestErr, \
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000803 "%s cannot be child of %s" % (repr(node), repr(self))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000804 if node.parentNode is not None:
805 node.parentNode.removeChild(node)
806
Fred Drakef7cf40d2000-12-14 18:16:11 +0000807 if node.nodeType == Node.ELEMENT_NODE \
808 and self._get_documentElement():
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000809 raise xml.dom.HierarchyRequestErr(
810 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000811 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +0000812
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000813 def removeChild(self, oldChild):
814 self.childNodes.remove(oldChild)
815 oldChild.nextSibling = oldChild.previousSibling = None
816 oldChild.parentNode = None
817 if self.documentElement is oldChild:
818 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000819
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000820 return oldChild
821
Fred Drakef7cf40d2000-12-14 18:16:11 +0000822 def _get_documentElement(self):
823 for node in self.childNodes:
824 if node.nodeType == Node.ELEMENT_NODE:
825 return node
826
827 def unlink(self):
828 if self.doctype is not None:
829 self.doctype.unlink()
830 self.doctype = None
831 Node.unlink(self)
832
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000833 def createDocumentFragment(self):
834 d = DocumentFragment()
835 d.ownerDoc = self
836 return d
Fred Drake55c38192000-06-29 19:39:57 +0000837
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000838 def createElement(self, tagName):
839 e = Element(tagName)
840 e.ownerDocument = self
841 return e
Fred Drake55c38192000-06-29 19:39:57 +0000842
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000843 def createTextNode(self, data):
844 t = Text(data)
845 t.ownerDocument = self
846 return t
Fred Drake55c38192000-06-29 19:39:57 +0000847
Fred Drake87432f42001-04-04 14:09:46 +0000848 def createCDATASection(self, data):
849 c = CDATASection(data)
850 c.ownerDocument = self
851 return c
852
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000853 def createComment(self, data):
854 c = Comment(data)
855 c.ownerDocument = self
856 return c
Fred Drake55c38192000-06-29 19:39:57 +0000857
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000858 def createProcessingInstruction(self, target, data):
859 p = ProcessingInstruction(target, data)
860 p.ownerDocument = self
861 return p
862
863 def createAttribute(self, qName):
864 a = Attr(qName)
865 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +0000866 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000867 return a
Fred Drake55c38192000-06-29 19:39:57 +0000868
869 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000870 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000871 e = Element(qualifiedName, namespaceURI, prefix, localName)
872 e.ownerDocument = self
873 return e
Fred Drake55c38192000-06-29 19:39:57 +0000874
875 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000876 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000877 a = Attr(qualifiedName, namespaceURI, localName, prefix)
878 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +0000879 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000880 return a
Fred Drake55c38192000-06-29 19:39:57 +0000881
Fred Drake1f549022000-09-24 05:21:58 +0000882 def getElementsByTagName(self, name):
Fred Drakefbe7b4f2001-07-04 06:25:53 +0000883 return _getElementsByTagNameHelper(self, name, [])
884
885 def getElementsByTagNameNS(self, namespaceURI, localName):
886 return _getElementsByTagNameNSHelper(self, namespaceURI, localName, [])
Fred Drake55c38192000-06-29 19:39:57 +0000887
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000888 def writexml(self, writer, indent="", addindent="", newl=""):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000889 writer.write('<?xml version="1.0" ?>\n')
Fred Drake55c38192000-06-29 19:39:57 +0000890 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000891 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +0000892
Fred Drake4ccf4a12000-11-21 22:02:22 +0000893def _get_StringIO():
Fred Drakef7cf40d2000-12-14 18:16:11 +0000894 # we can't use cStringIO since it doesn't support Unicode strings
895 from StringIO import StringIO
Fred Drake4ccf4a12000-11-21 22:02:22 +0000896 return StringIO()
897
Fred Drake1f549022000-09-24 05:21:58 +0000898def _doparse(func, args, kwargs):
899 events = apply(func, args, kwargs)
900 toktype, rootNode = events.getEvent()
901 events.expandNode(rootNode)
Martin v. Löwisb417be22001-02-06 01:16:06 +0000902 events.clear()
Fred Drake55c38192000-06-29 19:39:57 +0000903 return rootNode
904
Fred Drake1f549022000-09-24 05:21:58 +0000905def parse(*args, **kwargs):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000906 """Parse a file into a DOM by filename or file object."""
Fred Drake4ccf4a12000-11-21 22:02:22 +0000907 from xml.dom import pulldom
Fred Drake1f549022000-09-24 05:21:58 +0000908 return _doparse(pulldom.parse, args, kwargs)
Fred Drake55c38192000-06-29 19:39:57 +0000909
Fred Drake1f549022000-09-24 05:21:58 +0000910def parseString(*args, **kwargs):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000911 """Parse a file into a DOM from a string."""
Fred Drake4ccf4a12000-11-21 22:02:22 +0000912 from xml.dom import pulldom
Fred Drake1f549022000-09-24 05:21:58 +0000913 return _doparse(pulldom.parseString, args, kwargs)
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +0000914
915def getDOMImplementation():
916 return Document.implementation