blob: cb2c4d2d1a6e140a0b4d47c94ff9c949b7d626c7 [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 Drake49a5d032001-11-30 22:21:58 +000017from xml.dom import HierarchyRequestErr, EMPTY_NAMESPACE
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +000018
Fred Drake4ccf4a12000-11-21 22:02:22 +000019# localize the types, and allow support for Unicode values if available:
Fred Drake1f549022000-09-24 05:21:58 +000020import types
Fred Drake4ccf4a12000-11-21 22:02:22 +000021_TupleType = types.TupleType
22try:
23 _StringTypes = (types.StringType, types.UnicodeType)
24except AttributeError:
25 _StringTypes = (types.StringType,)
26del types
27
Fred Drakef7cf40d2000-12-14 18:16:11 +000028import xml.dom
Fred Drake55c38192000-06-29 19:39:57 +000029
Fred Drake3ac6a092001-09-28 04:33:06 +000030
31if list is type([]):
32 class NodeList(list):
33 def item(self, index):
34 if 0 <= index < len(self):
35 return self[index]
36
Fred Drake575712e2001-09-28 20:25:45 +000037 length = property(lambda self: len(self),
38 doc="The number of nodes in the NodeList.")
Fred Drake3ac6a092001-09-28 04:33:06 +000039
40else:
41 def NodeList():
42 return []
Martin v. Löwis95700f72002-03-15 13:51:59 +000043
Fred Drake3ac6a092001-09-28 04:33:06 +000044
Fred Drake575712e2001-09-28 20:25:45 +000045class Node(xml.dom.Node):
Fred Drake1f549022000-09-24 05:21:58 +000046 allnodes = {}
47 _debug = 0
48 _makeParentNodes = 1
49 debug = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +000050 childNodeTypes = ()
Martin v. Löwis126f2f62001-03-13 10:50:13 +000051 namespaceURI = None # this is non-null only for elements and attributes
Fred Drake575712e2001-09-28 20:25:45 +000052 parentNode = None
53 ownerDocument = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +000054
Fred Drake1f549022000-09-24 05:21:58 +000055 def __init__(self):
Fred Drake3ac6a092001-09-28 04:33:06 +000056 self.childNodes = NodeList()
Fred Drake16f63292000-10-23 18:09:50 +000057 if Node._debug:
Fred Drake1f549022000-09-24 05:21:58 +000058 index = repr(id(self)) + repr(self.__class__)
59 Node.allnodes[index] = repr(self.__dict__)
60 if Node.debug is None:
Fred Drake4ccf4a12000-11-21 22:02:22 +000061 Node.debug = _get_StringIO()
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +000062 #open("debug4.out", "w")
Fred Drake1f549022000-09-24 05:21:58 +000063 Node.debug.write("create %s\n" % index)
Fred Drake55c38192000-06-29 19:39:57 +000064
Fred Drake1f549022000-09-24 05:21:58 +000065 def __nonzero__(self):
66 return 1
Fred Drake55c38192000-06-29 19:39:57 +000067
Fred Drake1f549022000-09-24 05:21:58 +000068 def toxml(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000069 writer = _get_StringIO()
Fred Drake1f549022000-09-24 05:21:58 +000070 self.writexml(writer)
Fred Drake55c38192000-06-29 19:39:57 +000071 return writer.getvalue()
72
Martin v. Löwis46fa39a2001-02-06 00:14:08 +000073 def toprettyxml(self, indent="\t", newl="\n"):
Martin v. Löwiscb67ea12001-03-31 16:30:40 +000074 # indent = the indentation string to prepend, per level
75 # newl = the newline string to append
76 writer = _get_StringIO()
77 self.writexml(writer, "", indent, newl)
78 return writer.getvalue()
Martin v. Löwis46fa39a2001-02-06 00:14:08 +000079
Fred Drake1f549022000-09-24 05:21:58 +000080 def hasChildNodes(self):
81 if self.childNodes:
82 return 1
83 else:
84 return 0
Fred Drake55c38192000-06-29 19:39:57 +000085
Fred Drake1f549022000-09-24 05:21:58 +000086 def _get_firstChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000087 if self.childNodes:
88 return self.childNodes[0]
Paul Prescod73678da2000-07-01 04:58:47 +000089
Fred Drake1f549022000-09-24 05:21:58 +000090 def _get_lastChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000091 if self.childNodes:
92 return self.childNodes[-1]
Paul Prescod73678da2000-07-01 04:58:47 +000093
Fred Draked1572372001-09-29 04:58:32 +000094 try:
95 property
96 except NameError:
97 def __getattr__(self, key):
98 if key[0:2] == "__":
99 raise AttributeError, key
100 # getattr should never call getattr!
101 if self.__dict__.has_key("inGetAttr"):
102 del self.inGetAttr
103 raise AttributeError, key
104
105 prefix, attrname = key[:5], key[5:]
106 if prefix == "_get_":
107 self.inGetAttr = 1
108 if hasattr(self, attrname):
109 del self.inGetAttr
110 return (lambda self=self, attrname=attrname:
111 getattr(self, attrname))
112 else:
113 del self.inGetAttr
114 raise AttributeError, key
115 else:
116 self.inGetAttr = 1
117 try:
118 func = getattr(self, "_get_" + key)
119 except AttributeError:
120 raise AttributeError, key
121 del self.inGetAttr
122 return func()
123 else:
124 firstChild = property(_get_firstChild,
125 doc="First child node, or None.")
126 lastChild = property(_get_lastChild,
127 doc="Last child node, or None.")
128
Fred Drake1f549022000-09-24 05:21:58 +0000129 def insertBefore(self, newChild, refChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000130 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +0000131 for c in tuple(newChild.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000132 self.insertBefore(c, refChild)
133 ### The DOM does not clearly specify what to return in this case
134 return newChild
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000135 if newChild.nodeType not in self.childNodeTypes:
136 raise HierarchyRequestErr, \
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000137 "%s cannot be child of %s" % (repr(newChild), repr(self))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000138 if newChild.parentNode is not None:
139 newChild.parentNode.removeChild(newChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000140 if refChild is None:
141 self.appendChild(newChild)
142 else:
143 index = self.childNodes.index(refChild)
144 self.childNodes.insert(index, newChild)
145 newChild.nextSibling = refChild
146 refChild.previousSibling = newChild
147 if index:
148 node = self.childNodes[index-1]
149 node.nextSibling = newChild
150 newChild.previousSibling = node
151 else:
152 newChild.previousSibling = None
153 if self._makeParentNodes:
154 newChild.parentNode = self
155 return newChild
Fred Drake55c38192000-06-29 19:39:57 +0000156
Fred Drake1f549022000-09-24 05:21:58 +0000157 def appendChild(self, node):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000158 if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
Fred Drakee50959a2001-12-06 04:32:18 +0000159 for c in tuple(node.childNodes):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000160 self.appendChild(c)
161 ### The DOM does not clearly specify what to return in this case
162 return node
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000163 if node.nodeType not in self.childNodeTypes:
164 raise HierarchyRequestErr, \
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000165 "%s cannot be child of %s" % (repr(node), repr(self))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000166 if node.parentNode is not None:
167 node.parentNode.removeChild(node)
Fred Drake13a30692000-10-09 20:04:16 +0000168 if self.childNodes:
169 last = self.lastChild
170 node.previousSibling = last
171 last.nextSibling = node
172 else:
173 node.previousSibling = None
174 node.nextSibling = None
Fred Drake1f549022000-09-24 05:21:58 +0000175 self.childNodes.append(node)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000176 if self._makeParentNodes:
177 node.parentNode = self
Paul Prescod73678da2000-07-01 04:58:47 +0000178 return node
179
Fred Drake1f549022000-09-24 05:21:58 +0000180 def replaceChild(self, newChild, oldChild):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000181 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
182 refChild = oldChild.nextSibling
183 self.removeChild(oldChild)
184 return self.insertBefore(newChild, refChild)
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000185 if newChild.nodeType not in self.childNodeTypes:
186 raise HierarchyRequestErr, \
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000187 "%s cannot be child of %s" % (repr(newChild), repr(self))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000188 if newChild.parentNode is not None:
189 newChild.parentNode.removeChild(newChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000190 if newChild is oldChild:
191 return
Fred Drake1f549022000-09-24 05:21:58 +0000192 index = self.childNodes.index(oldChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000193 self.childNodes[index] = newChild
194 if self._makeParentNodes:
195 newChild.parentNode = self
196 oldChild.parentNode = None
197 newChild.nextSibling = oldChild.nextSibling
198 newChild.previousSibling = oldChild.previousSibling
Martin v. Löwis156c3372000-12-28 18:40:56 +0000199 oldChild.nextSibling = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000200 oldChild.previousSibling = None
Martin v. Löwis156c3372000-12-28 18:40:56 +0000201 if newChild.previousSibling:
202 newChild.previousSibling.nextSibling = newChild
203 if newChild.nextSibling:
204 newChild.nextSibling.previousSibling = newChild
Fred Drake4ccf4a12000-11-21 22:02:22 +0000205 return oldChild
Paul Prescod73678da2000-07-01 04:58:47 +0000206
Fred Drake1f549022000-09-24 05:21:58 +0000207 def removeChild(self, oldChild):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000208 self.childNodes.remove(oldChild)
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000209 if oldChild.nextSibling is not None:
210 oldChild.nextSibling.previousSibling = oldChild.previousSibling
211 if oldChild.previousSibling is not None:
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000212 oldChild.previousSibling.nextSibling = oldChild.nextSibling
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000213 oldChild.nextSibling = oldChild.previousSibling = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000214
Fred Drake4ccf4a12000-11-21 22:02:22 +0000215 if self._makeParentNodes:
216 oldChild.parentNode = None
217 return oldChild
218
219 def normalize(self):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000220 L = []
221 for child in self.childNodes:
222 if child.nodeType == Node.TEXT_NODE:
223 data = child.data
224 if data and L and L[-1].nodeType == child.nodeType:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000225 # collapse text node
226 node = L[-1]
227 node.data = node.nodeValue = node.data + child.data
228 node.nextSibling = child.nextSibling
229 child.unlink()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000230 elif data:
231 if L:
232 L[-1].nextSibling = child
233 child.previousSibling = L[-1]
234 else:
235 child.previousSibling = None
236 L.append(child)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000237 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000238 # empty text node; discard
239 child.unlink()
240 else:
241 if L:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000242 L[-1].nextSibling = child
243 child.previousSibling = L[-1]
Fred Drakef7cf40d2000-12-14 18:16:11 +0000244 else:
245 child.previousSibling = None
246 L.append(child)
247 if child.nodeType == Node.ELEMENT_NODE:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000248 child.normalize()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000249 self.childNodes[:] = L
Paul Prescod73678da2000-07-01 04:58:47 +0000250
Fred Drake1f549022000-09-24 05:21:58 +0000251 def cloneNode(self, deep):
Paul Prescod73678da2000-07-01 04:58:47 +0000252 import new
Fred Drake4ccf4a12000-11-21 22:02:22 +0000253 clone = new.instance(self.__class__, self.__dict__.copy())
254 if self._makeParentNodes:
255 clone.parentNode = None
Fred Drake3ac6a092001-09-28 04:33:06 +0000256 clone.childNodes = NodeList()
Fred Drake4ccf4a12000-11-21 22:02:22 +0000257 if deep:
258 for child in self.childNodes:
259 clone.appendChild(child.cloneNode(1))
Paul Prescod73678da2000-07-01 04:58:47 +0000260 return clone
Fred Drake55c38192000-06-29 19:39:57 +0000261
Fred Drake25239772001-02-02 19:40:19 +0000262 # DOM Level 3 (Working Draft 2001-Jan-26)
263
264 def isSameNode(self, other):
265 return self is other
266
267 # minidom-specific API:
268
Fred Drake1f549022000-09-24 05:21:58 +0000269 def unlink(self):
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000270 self.parentNode = self.ownerDocument = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000271 for child in self.childNodes:
272 child.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000273 self.childNodes = None
Paul Prescod4221ff02000-10-13 20:11:42 +0000274 self.previousSibling = None
275 self.nextSibling = None
Paul Prescod73678da2000-07-01 04:58:47 +0000276 if Node._debug:
Fred Drake1f549022000-09-24 05:21:58 +0000277 index = repr(id(self)) + repr(self.__class__)
278 self.debug.write("Deleting: %s\n" % index)
Paul Prescod73678da2000-07-01 04:58:47 +0000279 del Node.allnodes[index]
Fred Drake55c38192000-06-29 19:39:57 +0000280
Fred Drake1f549022000-09-24 05:21:58 +0000281def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000282 "Writes datachars to writer."
Neal Norwitzab199622002-05-31 20:46:39 +0000283 data = data.replace("&", "&amp;")
284 data = data.replace("<", "&lt;")
285 data = data.replace("\"", "&quot;")
286 data = data.replace(">", "&gt;")
Fred Drake55c38192000-06-29 19:39:57 +0000287 writer.write(data)
288
Fred Drake1f549022000-09-24 05:21:58 +0000289def _getElementsByTagNameHelper(parent, name, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000290 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000291 if node.nodeType == Node.ELEMENT_NODE and \
292 (name == "*" or node.tagName == name):
293 rc.append(node)
294 _getElementsByTagNameHelper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000295 return rc
296
Fred Drake1f549022000-09-24 05:21:58 +0000297def _getElementsByTagNameNSHelper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000298 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000299 if node.nodeType == Node.ELEMENT_NODE:
Martin v. Löwised525fb2001-06-03 14:06:42 +0000300 if ((localName == "*" or node.localName == localName) and
Fred Drake1f549022000-09-24 05:21:58 +0000301 (nsURI == "*" or node.namespaceURI == nsURI)):
302 rc.append(node)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000303 _getElementsByTagNameNSHelper(node, nsURI, localName, rc)
304 return rc
Fred Drake55c38192000-06-29 19:39:57 +0000305
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000306class DocumentFragment(Node):
307 nodeType = Node.DOCUMENT_FRAGMENT_NODE
308 nodeName = "#document-fragment"
309 nodeValue = None
310 attributes = None
311 parentNode = None
312 childNodeTypes = (Node.ELEMENT_NODE,
313 Node.TEXT_NODE,
314 Node.CDATA_SECTION_NODE,
315 Node.ENTITY_REFERENCE_NODE,
316 Node.PROCESSING_INSTRUCTION_NODE,
317 Node.COMMENT_NODE,
318 Node.NOTATION_NODE)
319
320
Fred Drake55c38192000-06-29 19:39:57 +0000321class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000322 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000323 attributes = None
324 ownerElement = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000325 childNodeTypes = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000326
Fred Drake49a5d032001-11-30 22:21:58 +0000327 def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None, prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000328 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000329 d = self.__dict__
330 d["localName"] = localName or qName
331 d["nodeName"] = d["name"] = qName
332 d["namespaceURI"] = namespaceURI
333 d["prefix"] = prefix
Fred Drake1f549022000-09-24 05:21:58 +0000334 Node.__init__(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000335 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000336
Fred Drake1f549022000-09-24 05:21:58 +0000337 def __setattr__(self, name, value):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000338 d = self.__dict__
Fred Drake1f549022000-09-24 05:21:58 +0000339 if name in ("value", "nodeValue"):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000340 d["value"] = d["nodeValue"] = value
341 elif name in ("name", "nodeName"):
342 d["name"] = d["nodeName"] = value
Fred Drake55c38192000-06-29 19:39:57 +0000343 else:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000344 d[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000345
Fred Drake4ccf4a12000-11-21 22:02:22 +0000346 def cloneNode(self, deep):
347 clone = Node.cloneNode(self, deep)
348 if clone.__dict__.has_key("ownerElement"):
349 del clone.ownerElement
350 return clone
351
Fred Drakef7cf40d2000-12-14 18:16:11 +0000352
353class NamedNodeMap:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000354 """The attribute list is a transient interface to the underlying
355 dictionaries. Mutations here will change the underlying element's
Fred Drakef7cf40d2000-12-14 18:16:11 +0000356 dictionary.
357
358 Ordering is imposed artificially and does not reflect the order of
359 attributes as found in an input document.
360 """
Fred Drake4ccf4a12000-11-21 22:02:22 +0000361
Fred Drake2998a552001-12-06 18:27:48 +0000362 def __init__(self, attrs, attrsNS, ownerElement):
Fred Drake1f549022000-09-24 05:21:58 +0000363 self._attrs = attrs
364 self._attrsNS = attrsNS
Fred Drake2998a552001-12-06 18:27:48 +0000365 self._ownerElement = ownerElement
Fred Drakef7cf40d2000-12-14 18:16:11 +0000366
Fred Draked1572372001-09-29 04:58:32 +0000367 try:
368 property
369 except NameError:
370 def __getattr__(self, name):
371 if name == "length":
372 return len(self._attrs)
373 raise AttributeError, name
374 else:
375 length = property(lambda self: len(self._attrs),
376 doc="Number of nodes in the NamedNodeMap.")
Fred Drake55c38192000-06-29 19:39:57 +0000377
Fred Drake1f549022000-09-24 05:21:58 +0000378 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000379 try:
Fred Drakef7cf40d2000-12-14 18:16:11 +0000380 return self[self._attrs.keys()[index]]
Fred Drake55c38192000-06-29 19:39:57 +0000381 except IndexError:
382 return None
Fred Drake55c38192000-06-29 19:39:57 +0000383
Fred Drake1f549022000-09-24 05:21:58 +0000384 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000385 L = []
386 for node in self._attrs.values():
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000387 L.append((node.nodeName, node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000388 return L
Fred Drake1f549022000-09-24 05:21:58 +0000389
390 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000391 L = []
392 for node in self._attrs.values():
Fred Drake49a5d032001-11-30 22:21:58 +0000393 L.append(((node.namespaceURI, node.localName), node.value))
Fred Drake4ccf4a12000-11-21 22:02:22 +0000394 return L
Fred Drake16f63292000-10-23 18:09:50 +0000395
Fred Drake1f549022000-09-24 05:21:58 +0000396 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000397 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000398
Fred Drake1f549022000-09-24 05:21:58 +0000399 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000400 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000401
Fred Drake1f549022000-09-24 05:21:58 +0000402 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000403 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000404
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000405 def get(self, name, value = None):
406 return self._attrs.get(name, value)
407
Fred Drake1f549022000-09-24 05:21:58 +0000408 def __len__(self):
Fred Drake55c38192000-06-29 19:39:57 +0000409 return self.length
410
Fred Drake1f549022000-09-24 05:21:58 +0000411 def __cmp__(self, other):
412 if self._attrs is getattr(other, "_attrs", None):
Fred Drake55c38192000-06-29 19:39:57 +0000413 return 0
Fred Drake16f63292000-10-23 18:09:50 +0000414 else:
Fred Drake1f549022000-09-24 05:21:58 +0000415 return cmp(id(self), id(other))
Fred Drake55c38192000-06-29 19:39:57 +0000416
417 #FIXME: is it appropriate to return .value?
Fred Drake1f549022000-09-24 05:21:58 +0000418 def __getitem__(self, attname_or_tuple):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000419 if type(attname_or_tuple) is _TupleType:
Paul Prescod73678da2000-07-01 04:58:47 +0000420 return self._attrsNS[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000421 else:
Paul Prescod73678da2000-07-01 04:58:47 +0000422 return self._attrs[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000423
Paul Prescod1e688272000-07-01 19:21:47 +0000424 # same as set
Fred Drake1f549022000-09-24 05:21:58 +0000425 def __setitem__(self, attname, value):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000426 if type(value) in _StringTypes:
Fred Drake1f549022000-09-24 05:21:58 +0000427 node = Attr(attname)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000428 node.value = value
Fred Drake2998a552001-12-06 18:27:48 +0000429 node.ownerDocument = self._ownerElement.ownerDocument
Paul Prescod1e688272000-07-01 19:21:47 +0000430 else:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000431 if not isinstance(value, Attr):
432 raise TypeError, "value must be a string or Attr object"
Fred Drake1f549022000-09-24 05:21:58 +0000433 node = value
Fred Drakef7cf40d2000-12-14 18:16:11 +0000434 self.setNamedItem(node)
435
436 def setNamedItem(self, node):
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000437 if not isinstance(node, Attr):
438 raise HierarchyRequestErr, \
439 "%s cannot be child of %s" % (repr(node), repr(self))
Fred Drakef7cf40d2000-12-14 18:16:11 +0000440 old = self._attrs.get(node.name)
Paul Prescod1e688272000-07-01 19:21:47 +0000441 if old:
442 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000443 self._attrs[node.name] = node
444 self._attrsNS[(node.namespaceURI, node.localName)] = node
Fred Drake2998a552001-12-06 18:27:48 +0000445 node.ownerElement = self._ownerElement
Fred Drakef7cf40d2000-12-14 18:16:11 +0000446 return old
447
448 def setNamedItemNS(self, node):
449 return self.setNamedItem(node)
Paul Prescod73678da2000-07-01 04:58:47 +0000450
Fred Drake1f549022000-09-24 05:21:58 +0000451 def __delitem__(self, attname_or_tuple):
452 node = self[attname_or_tuple]
Paul Prescod73678da2000-07-01 04:58:47 +0000453 node.unlink()
454 del self._attrs[node.name]
455 del self._attrsNS[(node.namespaceURI, node.localName)]
Fred Drakef7cf40d2000-12-14 18:16:11 +0000456 self.length = len(self._attrs)
457
458AttributeList = NamedNodeMap
459
Fred Drake1f549022000-09-24 05:21:58 +0000460
Martin v. Löwisa2fda0d2000-10-07 12:10:28 +0000461class Element(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000462 nodeType = Node.ELEMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000463 nextSibling = None
464 previousSibling = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000465 childNodeTypes = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
466 Node.COMMENT_NODE, Node.TEXT_NODE,
467 Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000468
Fred Drake49a5d032001-11-30 22:21:58 +0000469 def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
Fred Drake1f549022000-09-24 05:21:58 +0000470 localName=None):
471 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000472 self.tagName = self.nodeName = tagName
Fred Drake1f549022000-09-24 05:21:58 +0000473 self.localName = localName or tagName
474 self.prefix = prefix
475 self.namespaceURI = namespaceURI
476 self.nodeValue = None
Fred Drake55c38192000-06-29 19:39:57 +0000477
Fred Drake4ccf4a12000-11-21 22:02:22 +0000478 self._attrs = {} # attributes are double-indexed:
479 self._attrsNS = {} # tagName -> Attribute
480 # URI,localName -> Attribute
481 # in the future: consider lazy generation
482 # of attribute objects this is too tricky
483 # for now because of headaches with
484 # namespaces.
485
486 def cloneNode(self, deep):
487 clone = Node.cloneNode(self, deep)
488 clone._attrs = {}
489 clone._attrsNS = {}
490 for attr in self._attrs.values():
491 node = attr.cloneNode(1)
492 clone._attrs[node.name] = node
493 clone._attrsNS[(node.namespaceURI, node.localName)] = node
494 node.ownerElement = clone
495 return clone
496
497 def unlink(self):
498 for attr in self._attrs.values():
499 attr.unlink()
500 self._attrs = None
501 self._attrsNS = None
502 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000503
Fred Drake1f549022000-09-24 05:21:58 +0000504 def getAttribute(self, attname):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000505 try:
506 return self._attrs[attname].value
507 except KeyError:
508 return ""
Fred Drake55c38192000-06-29 19:39:57 +0000509
Fred Drake1f549022000-09-24 05:21:58 +0000510 def getAttributeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000511 try:
512 return self._attrsNS[(namespaceURI, localName)].value
513 except KeyError:
514 return ""
Fred Drake1f549022000-09-24 05:21:58 +0000515
516 def setAttribute(self, attname, value):
517 attr = Attr(attname)
Fred Drake55c38192000-06-29 19:39:57 +0000518 # for performance
Fred Drake2998a552001-12-06 18:27:48 +0000519 d = attr.__dict__
520 d["value"] = d["nodeValue"] = value
521 d["ownerDocument"] = self.ownerDocument
Fred Drake1f549022000-09-24 05:21:58 +0000522 self.setAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000523
Fred Drake1f549022000-09-24 05:21:58 +0000524 def setAttributeNS(self, namespaceURI, qualifiedName, value):
525 prefix, localname = _nssplit(qualifiedName)
Fred Drake55c38192000-06-29 19:39:57 +0000526 # for performance
Fred Drake1f549022000-09-24 05:21:58 +0000527 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
Fred Drake2998a552001-12-06 18:27:48 +0000528 d = attr.__dict__
529 d["value"] = d["nodeValue"] = value
530 d["ownerDocument"] = self.ownerDocument
Fred Drake1f549022000-09-24 05:21:58 +0000531 self.setAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000532
Fred Drake1f549022000-09-24 05:21:58 +0000533 def getAttributeNode(self, attrname):
534 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000535
Fred Drake1f549022000-09-24 05:21:58 +0000536 def getAttributeNodeNS(self, namespaceURI, localName):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000537 return self._attrsNS.get((namespaceURI, localName))
Paul Prescod73678da2000-07-01 04:58:47 +0000538
Fred Drake1f549022000-09-24 05:21:58 +0000539 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000540 if attr.ownerElement not in (None, self):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000541 raise xml.dom.InuseAttributeErr("attribute node already owned")
Fred Drake1f549022000-09-24 05:21:58 +0000542 old = self._attrs.get(attr.name, None)
Paul Prescod73678da2000-07-01 04:58:47 +0000543 if old:
544 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000545 self._attrs[attr.name] = attr
546 self._attrsNS[(attr.namespaceURI, attr.localName)] = attr
Fred Drake4ccf4a12000-11-21 22:02:22 +0000547
548 # This creates a circular reference, but Element.unlink()
549 # breaks the cycle since the references to the attribute
550 # dictionaries are tossed.
551 attr.ownerElement = self
552
553 if old is not attr:
554 # It might have already been part of this node, in which case
555 # it doesn't represent a change, and should not be returned.
556 return old
Fred Drake55c38192000-06-29 19:39:57 +0000557
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000558 setAttributeNodeNS = setAttributeNode
559
Fred Drake1f549022000-09-24 05:21:58 +0000560 def removeAttribute(self, name):
Paul Prescod73678da2000-07-01 04:58:47 +0000561 attr = self._attrs[name]
Fred Drake1f549022000-09-24 05:21:58 +0000562 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000563
Fred Drake1f549022000-09-24 05:21:58 +0000564 def removeAttributeNS(self, namespaceURI, localName):
Paul Prescod73678da2000-07-01 04:58:47 +0000565 attr = self._attrsNS[(namespaceURI, localName)]
Fred Drake1f549022000-09-24 05:21:58 +0000566 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000567
Fred Drake1f549022000-09-24 05:21:58 +0000568 def removeAttributeNode(self, node):
Paul Prescod73678da2000-07-01 04:58:47 +0000569 node.unlink()
570 del self._attrs[node.name]
571 del self._attrsNS[(node.namespaceURI, node.localName)]
Fred Drake16f63292000-10-23 18:09:50 +0000572
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000573 removeAttributeNodeNS = removeAttributeNode
574
Martin v. Löwis156c3372000-12-28 18:40:56 +0000575 def hasAttribute(self, name):
576 return self._attrs.has_key(name)
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000577
Martin v. Löwis156c3372000-12-28 18:40:56 +0000578 def hasAttributeNS(self, namespaceURI, localName):
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000579 return self._attrsNS.has_key((namespaceURI, localName))
580
Fred Drake1f549022000-09-24 05:21:58 +0000581 def getElementsByTagName(self, name):
Martin v. Löwis95700f72002-03-15 13:51:59 +0000582 return _getElementsByTagNameHelper(self, name, NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000583
Fred Drake1f549022000-09-24 05:21:58 +0000584 def getElementsByTagNameNS(self, namespaceURI, localName):
Fred Drake15b68932002-03-15 14:37:23 +0000585 return _getElementsByTagNameNSHelper(self, namespaceURI, localName,
586 NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000587
Fred Drake1f549022000-09-24 05:21:58 +0000588 def __repr__(self):
589 return "<DOM Element: %s at %s>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000590
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000591 def writexml(self, writer, indent="", addindent="", newl=""):
592 # indent = current indentation
593 # addindent = indentation to add to higher levels
594 # newl = newline string
595 writer.write(indent+"<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000596
Fred Drake4ccf4a12000-11-21 22:02:22 +0000597 attrs = self._get_attributes()
598 a_names = attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000599 a_names.sort()
600
601 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000602 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000603 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000604 writer.write("\"")
605 if self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000606 writer.write(">%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000607 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000608 node.writexml(writer,indent+addindent,addindent,newl)
609 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
Fred Drake55c38192000-06-29 19:39:57 +0000610 else:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000611 writer.write("/>%s"%(newl))
Fred Drake55c38192000-06-29 19:39:57 +0000612
Fred Drake1f549022000-09-24 05:21:58 +0000613 def _get_attributes(self):
Fred Drake2998a552001-12-06 18:27:48 +0000614 return NamedNodeMap(self._attrs, self._attrsNS, self)
Fred Drake55c38192000-06-29 19:39:57 +0000615
Fred Draked1572372001-09-29 04:58:32 +0000616 try:
617 property
618 except NameError:
619 pass
620 else:
621 attributes = property(_get_attributes,
622 doc="NamedNodeMap of attributes on the element.")
623
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000624 def hasAttributes(self):
625 if self._attrs or self._attrsNS:
626 return 1
627 else:
628 return 0
629
Fred Drake1f549022000-09-24 05:21:58 +0000630class Comment(Node):
631 nodeType = Node.COMMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000632 nodeName = "#comment"
633 attributes = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000634 childNodeTypes = ()
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000635
Fred Drake1f549022000-09-24 05:21:58 +0000636 def __init__(self, data):
637 Node.__init__(self)
638 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000639
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000640 def writexml(self, writer, indent="", addindent="", newl=""):
641 writer.write("%s<!--%s-->%s" % (indent,self.data,newl))
Fred Drake1f549022000-09-24 05:21:58 +0000642
643class ProcessingInstruction(Node):
644 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000645 attributes = None
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000646 childNodeTypes = ()
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000647
Fred Drake1f549022000-09-24 05:21:58 +0000648 def __init__(self, target, data):
649 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000650 self.target = self.nodeName = target
651 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000652
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000653 def writexml(self, writer, indent="", addindent="", newl=""):
654 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000655
Fred Drake87432f42001-04-04 14:09:46 +0000656class CharacterData(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000657 def __init__(self, data):
Fred Drakedaa823a2001-01-08 04:04:34 +0000658 if type(data) not in _StringTypes:
659 raise TypeError, "node contents must be a string"
Fred Drake1f549022000-09-24 05:21:58 +0000660 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000661 self.data = self.nodeValue = data
Fred Drake33d2b842001-04-04 15:15:18 +0000662 self.length = len(data)
Fred Drake87432f42001-04-04 14:09:46 +0000663
Fred Drake55c38192000-06-29 19:39:57 +0000664 def __repr__(self):
Fred Drake1f549022000-09-24 05:21:58 +0000665 if len(self.data) > 10:
666 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000667 else:
Fred Drake1f549022000-09-24 05:21:58 +0000668 dotdotdot = ""
Fred Drake87432f42001-04-04 14:09:46 +0000669 return "<DOM %s node \"%s%s\">" % (
670 self.__class__.__name__, self.data[0:10], dotdotdot)
671
672 def substringData(self, offset, count):
673 if offset < 0:
674 raise xml.dom.IndexSizeErr("offset cannot be negative")
675 if offset >= len(self.data):
676 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
677 if count < 0:
678 raise xml.dom.IndexSizeErr("count cannot be negative")
679 return self.data[offset:offset+count]
680
681 def appendData(self, arg):
682 self.data = self.data + arg
683 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000684 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000685
686 def insertData(self, offset, arg):
687 if offset < 0:
688 raise xml.dom.IndexSizeErr("offset cannot be negative")
689 if offset >= len(self.data):
690 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
691 if arg:
692 self.data = "%s%s%s" % (
693 self.data[:offset], arg, self.data[offset:])
694 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000695 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000696
697 def deleteData(self, offset, count):
698 if offset < 0:
699 raise xml.dom.IndexSizeErr("offset cannot be negative")
700 if offset >= len(self.data):
701 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
702 if count < 0:
703 raise xml.dom.IndexSizeErr("count cannot be negative")
704 if count:
705 self.data = self.data[:offset] + self.data[offset+count:]
706 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000707 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000708
709 def replaceData(self, offset, count, arg):
710 if offset < 0:
711 raise xml.dom.IndexSizeErr("offset cannot be negative")
712 if offset >= len(self.data):
713 raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
714 if count < 0:
715 raise xml.dom.IndexSizeErr("count cannot be negative")
716 if count:
717 self.data = "%s%s%s" % (
718 self.data[:offset], arg, self.data[offset+count:])
719 self.nodeValue = self.data
Fred Drake33d2b842001-04-04 15:15:18 +0000720 self.length = len(self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000721
722class Text(CharacterData):
723 nodeType = Node.TEXT_NODE
724 nodeName = "#text"
725 attributes = None
726 childNodeTypes = ()
Fred Drake55c38192000-06-29 19:39:57 +0000727
Fred Drakef7cf40d2000-12-14 18:16:11 +0000728 def splitText(self, offset):
729 if offset < 0 or offset > len(self.data):
Martin v. Löwisd5fb58f2001-01-27 08:38:34 +0000730 raise xml.dom.IndexSizeErr("illegal offset value")
Fred Drakef7cf40d2000-12-14 18:16:11 +0000731 newText = Text(self.data[offset:])
732 next = self.nextSibling
733 if self.parentNode and self in self.parentNode.childNodes:
734 if next is None:
735 self.parentNode.appendChild(newText)
736 else:
737 self.parentNode.insertBefore(newText, next)
738 self.data = self.data[:offset]
Fred Drake33d2b842001-04-04 15:15:18 +0000739 self.nodeValue = self.data
740 self.length = len(self.data)
Fred Drakef7cf40d2000-12-14 18:16:11 +0000741 return newText
742
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000743 def writexml(self, writer, indent="", addindent="", newl=""):
744 _write_data(writer, "%s%s%s"%(indent, self.data, newl))
Fred Drake55c38192000-06-29 19:39:57 +0000745
Fred Drake87432f42001-04-04 14:09:46 +0000746
747class CDATASection(Text):
748 nodeType = Node.CDATA_SECTION_NODE
749 nodeName = "#cdata-section"
750
751 def writexml(self, writer, indent="", addindent="", newl=""):
Guido van Rossum5b5e0b92001-09-19 13:28:25 +0000752 writer.write("<![CDATA[%s]]>" % self.data)
Fred Drake87432f42001-04-04 14:09:46 +0000753
754
Fred Drake1f549022000-09-24 05:21:58 +0000755def _nssplit(qualifiedName):
Neal Norwitzab199622002-05-31 20:46:39 +0000756 fields = qualifiedName.split(':', 1)
Paul Prescod73678da2000-07-01 04:58:47 +0000757 if len(fields) == 2:
758 return fields
759 elif len(fields) == 1:
Fred Drake49a5d032001-11-30 22:21:58 +0000760 return (None, fields[0])
Paul Prescod73678da2000-07-01 04:58:47 +0000761
Fred Drakef7cf40d2000-12-14 18:16:11 +0000762
763class DocumentType(Node):
764 nodeType = Node.DOCUMENT_TYPE_NODE
765 nodeValue = None
766 attributes = None
767 name = None
768 publicId = None
769 systemId = None
Fred Drakedc806702001-04-05 14:41:30 +0000770 internalSubset = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000771 entities = None
772 notations = None
773
774 def __init__(self, qualifiedName):
775 Node.__init__(self)
776 if qualifiedName:
777 prefix, localname = _nssplit(qualifiedName)
778 self.name = localname
779
780
781class DOMImplementation:
782 def hasFeature(self, feature, version):
783 if version not in ("1.0", "2.0"):
784 return 0
Neal Norwitzab199622002-05-31 20:46:39 +0000785 feature = feature.lower()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000786 return feature == "core"
787
788 def createDocument(self, namespaceURI, qualifiedName, doctype):
789 if doctype and doctype.parentNode is not None:
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000790 raise xml.dom.WrongDocumentErr(
791 "doctype object owned by another DOM tree")
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000792 doc = self._createDocument()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000793 if doctype is None:
794 doctype = self.createDocumentType(qualifiedName, None, None)
Martin v. Löwisb417be22001-02-06 01:16:06 +0000795 if not qualifiedName:
796 # The spec is unclear what to raise here; SyntaxErr
797 # would be the other obvious candidate. Since Xerces raises
798 # InvalidCharacterErr, and since SyntaxErr is not listed
799 # for createDocument, that seems to be the better choice.
800 # XXX: need to check for illegal characters here and in
801 # createElement.
802 raise xml.dom.InvalidCharacterErr("Element with no name")
803 prefix, localname = _nssplit(qualifiedName)
804 if prefix == "xml" \
805 and namespaceURI != "http://www.w3.org/XML/1998/namespace":
806 raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
807 if prefix and not namespaceURI:
808 raise xml.dom.NamespaceErr(
809 "illegal use of prefix without namespaces")
810 element = doc.createElementNS(namespaceURI, qualifiedName)
811 doc.appendChild(element)
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000812 doctype.parentNode = doctype.ownerDocument = doc
Fred Drakef7cf40d2000-12-14 18:16:11 +0000813 doc.doctype = doctype
814 doc.implementation = self
815 return doc
816
817 def createDocumentType(self, qualifiedName, publicId, systemId):
818 doctype = DocumentType(qualifiedName)
819 doctype.publicId = publicId
820 doctype.systemId = systemId
821 return doctype
822
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000823 # internal
824 def _createDocument(self):
825 return Document()
Fred Drakef7cf40d2000-12-14 18:16:11 +0000826
Fred Drake1f549022000-09-24 05:21:58 +0000827class Document(Node):
828 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000829 nodeName = "#document"
830 nodeValue = None
831 attributes = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000832 doctype = None
833 parentNode = None
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000834 previousSibling = nextSibling = None
Fred Drakef7cf40d2000-12-14 18:16:11 +0000835
836 implementation = DOMImplementation()
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000837 childNodeTypes = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
838 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
Fred Drake55c38192000-06-29 19:39:57 +0000839
Fred Drake1f549022000-09-24 05:21:58 +0000840 def appendChild(self, node):
Andrew M. Kuchling291ed4f2000-12-31 03:50:23 +0000841 if node.nodeType not in self.childNodeTypes:
842 raise HierarchyRequestErr, \
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000843 "%s cannot be child of %s" % (repr(node), repr(self))
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000844 if node.parentNode is not None:
845 node.parentNode.removeChild(node)
846
Fred Drakef7cf40d2000-12-14 18:16:11 +0000847 if node.nodeType == Node.ELEMENT_NODE \
848 and self._get_documentElement():
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000849 raise xml.dom.HierarchyRequestErr(
850 "two document elements disallowed")
Fred Drake4ccf4a12000-11-21 22:02:22 +0000851 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +0000852
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000853 def removeChild(self, oldChild):
854 self.childNodes.remove(oldChild)
855 oldChild.nextSibling = oldChild.previousSibling = None
856 oldChild.parentNode = None
857 if self.documentElement is oldChild:
858 self.documentElement = None
Martin v. Löwis52ce0d02001-01-27 08:47:37 +0000859
Andrew M. Kuchling04a45e92000-12-20 14:47:24 +0000860 return oldChild
861
Fred Drakef7cf40d2000-12-14 18:16:11 +0000862 def _get_documentElement(self):
863 for node in self.childNodes:
864 if node.nodeType == Node.ELEMENT_NODE:
865 return node
866
Fred Draked1572372001-09-29 04:58:32 +0000867 try:
868 property
869 except NameError:
870 pass
871 else:
872 documentElement = property(_get_documentElement,
873 doc="Top-level element of this document.")
874
Fred Drakef7cf40d2000-12-14 18:16:11 +0000875 def unlink(self):
876 if self.doctype is not None:
877 self.doctype.unlink()
878 self.doctype = None
879 Node.unlink(self)
880
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000881 def createDocumentFragment(self):
882 d = DocumentFragment()
883 d.ownerDoc = self
884 return d
Fred Drake55c38192000-06-29 19:39:57 +0000885
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000886 def createElement(self, tagName):
887 e = Element(tagName)
888 e.ownerDocument = self
889 return e
Fred Drake55c38192000-06-29 19:39:57 +0000890
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000891 def createTextNode(self, data):
892 t = Text(data)
893 t.ownerDocument = self
894 return t
Fred Drake55c38192000-06-29 19:39:57 +0000895
Fred Drake87432f42001-04-04 14:09:46 +0000896 def createCDATASection(self, data):
897 c = CDATASection(data)
898 c.ownerDocument = self
899 return c
900
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000901 def createComment(self, data):
902 c = Comment(data)
903 c.ownerDocument = self
904 return c
Fred Drake55c38192000-06-29 19:39:57 +0000905
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000906 def createProcessingInstruction(self, target, data):
907 p = ProcessingInstruction(target, data)
908 p.ownerDocument = self
909 return p
910
911 def createAttribute(self, qName):
912 a = Attr(qName)
913 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +0000914 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000915 return a
Fred Drake55c38192000-06-29 19:39:57 +0000916
917 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000918 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000919 e = Element(qualifiedName, namespaceURI, prefix, localName)
920 e.ownerDocument = self
921 return e
Fred Drake55c38192000-06-29 19:39:57 +0000922
923 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000924 prefix, localName = _nssplit(qualifiedName)
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000925 a = Attr(qualifiedName, namespaceURI, localName, prefix)
926 a.ownerDocument = self
Martin v. Löwiscb67ea12001-03-31 16:30:40 +0000927 a.value = ""
Martin v. Löwis126f2f62001-03-13 10:50:13 +0000928 return a
Fred Drake55c38192000-06-29 19:39:57 +0000929
Fred Drake1f549022000-09-24 05:21:58 +0000930 def getElementsByTagName(self, name):
Martin v. Löwis95700f72002-03-15 13:51:59 +0000931 return _getElementsByTagNameHelper(self, name, NodeList())
Fred Drakefbe7b4f2001-07-04 06:25:53 +0000932
933 def getElementsByTagNameNS(self, namespaceURI, localName):
Fred Drake15b68932002-03-15 14:37:23 +0000934 return _getElementsByTagNameNSHelper(self, namespaceURI, localName,
935 NodeList())
Fred Drake55c38192000-06-29 19:39:57 +0000936
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000937 def writexml(self, writer, indent="", addindent="", newl=""):
Guido van Rossum9e1fe1e2001-02-05 19:17:50 +0000938 writer.write('<?xml version="1.0" ?>\n')
Fred Drake55c38192000-06-29 19:39:57 +0000939 for node in self.childNodes:
Martin v. Löwis46fa39a2001-02-06 00:14:08 +0000940 node.writexml(writer, indent, addindent, newl)
Fred Drake55c38192000-06-29 19:39:57 +0000941
Fred Drake4ccf4a12000-11-21 22:02:22 +0000942def _get_StringIO():
Fred Drakef7cf40d2000-12-14 18:16:11 +0000943 # we can't use cStringIO since it doesn't support Unicode strings
944 from StringIO import StringIO
Fred Drake4ccf4a12000-11-21 22:02:22 +0000945 return StringIO()
946
Fred Drake1f549022000-09-24 05:21:58 +0000947def _doparse(func, args, kwargs):
948 events = apply(func, args, kwargs)
949 toktype, rootNode = events.getEvent()
950 events.expandNode(rootNode)
Martin v. Löwisb417be22001-02-06 01:16:06 +0000951 events.clear()
Fred Drake55c38192000-06-29 19:39:57 +0000952 return rootNode
953
Fred Drake1f549022000-09-24 05:21:58 +0000954def parse(*args, **kwargs):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000955 """Parse a file into a DOM by filename or file object."""
Fred Drake4ccf4a12000-11-21 22:02:22 +0000956 from xml.dom import pulldom
Fred Drake1f549022000-09-24 05:21:58 +0000957 return _doparse(pulldom.parse, args, kwargs)
Fred Drake55c38192000-06-29 19:39:57 +0000958
Fred Drake1f549022000-09-24 05:21:58 +0000959def parseString(*args, **kwargs):
Fred Drakef7cf40d2000-12-14 18:16:11 +0000960 """Parse a file into a DOM from a string."""
Fred Drake4ccf4a12000-11-21 22:02:22 +0000961 from xml.dom import pulldom
Fred Drake1f549022000-09-24 05:21:58 +0000962 return _doparse(pulldom.parseString, args, kwargs)
Martin v. Löwis7edbd4f2001-02-22 14:05:50 +0000963
964def getDOMImplementation():
965 return Document.implementation