blob: bf8166a94ae74a86ae599a4e205dfe130987f223 [file] [log] [blame]
Fred Drake1f549022000-09-24 05:21:58 +00001"""\
Fred Drake55c38192000-06-29 19:39:57 +00002minidom.py -- a lightweight DOM implementation based on SAX.
3
Paul Prescod623511b2000-07-21 22:05:49 +00004parse( "foo.xml" )
5
6parseString( "<foo><bar/></foo>" )
7
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
21# localize the types, and allow support for Unicode values if available:
Fred Drake1f549022000-09-24 05:21:58 +000022import types
Fred Drake4ccf4a12000-11-21 22:02:22 +000023_TupleType = types.TupleType
24try:
25 _StringTypes = (types.StringType, types.UnicodeType)
26except AttributeError:
27 _StringTypes = (types.StringType,)
28del types
29
Fred Drake1f549022000-09-24 05:21:58 +000030
Fred Drake55c38192000-06-29 19:39:57 +000031class Node:
32 ELEMENT_NODE = 1
33 ATTRIBUTE_NODE = 2
34 TEXT_NODE = 3
35 CDATA_SECTION_NODE = 4
36 ENTITY_REFERENCE_NODE = 5
37 ENTITY_NODE = 6
38 PROCESSING_INSTRUCTION_NODE = 7
39 COMMENT_NODE = 8
40 DOCUMENT_NODE = 9
41 DOCUMENT_TYPE_NODE = 10
42 DOCUMENT_FRAGMENT_NODE = 11
43 NOTATION_NODE = 12
44
Fred Drake1f549022000-09-24 05:21:58 +000045 allnodes = {}
46 _debug = 0
47 _makeParentNodes = 1
48 debug = None
Fred Drake55c38192000-06-29 19:39:57 +000049
Fred Drake1f549022000-09-24 05:21:58 +000050 def __init__(self):
51 self.childNodes = []
Fred Drake16f63292000-10-23 18:09:50 +000052 if Node._debug:
Fred Drake1f549022000-09-24 05:21:58 +000053 index = repr(id(self)) + repr(self.__class__)
54 Node.allnodes[index] = repr(self.__dict__)
55 if Node.debug is None:
Fred Drake4ccf4a12000-11-21 22:02:22 +000056 Node.debug = _get_StringIO()
Paul Prescod6c4753f2000-07-04 03:39:33 +000057 #open( "debug4.out", "w" )
Fred Drake1f549022000-09-24 05:21:58 +000058 Node.debug.write("create %s\n" % index)
Fred Drake55c38192000-06-29 19:39:57 +000059
Fred Drake1f549022000-09-24 05:21:58 +000060 def __getattr__(self, key):
61 if key[0:2] == "__":
62 raise AttributeError
Fred Drake55c38192000-06-29 19:39:57 +000063 # getattr should never call getattr!
Fred Drake16f63292000-10-23 18:09:50 +000064 if self.__dict__.has_key("inGetAttr"):
Fred Drake55c38192000-06-29 19:39:57 +000065 del self.inGetAttr
66 raise AttributeError, key
67
Fred Drake1f549022000-09-24 05:21:58 +000068 prefix, attrname = key[:5], key[5:]
69 if prefix == "_get_":
70 self.inGetAttr = 1
Fred Drake16f63292000-10-23 18:09:50 +000071 if hasattr(self, attrname):
Fred Drake55c38192000-06-29 19:39:57 +000072 del self.inGetAttr
Fred Drake16f63292000-10-23 18:09:50 +000073 return (lambda self=self, attrname=attrname:
Fred Drake1f549022000-09-24 05:21:58 +000074 getattr(self, attrname))
Fred Drake55c38192000-06-29 19:39:57 +000075 else:
76 del self.inGetAttr
77 raise AttributeError, key
78 else:
Fred Drake1f549022000-09-24 05:21:58 +000079 self.inGetAttr = 1
Fred Drake55c38192000-06-29 19:39:57 +000080 try:
Fred Drake1f549022000-09-24 05:21:58 +000081 func = getattr(self, "_get_" + key)
Fred Drake55c38192000-06-29 19:39:57 +000082 except AttributeError:
83 raise AttributeError, key
84 del self.inGetAttr
85 return func()
86
Fred Drake1f549022000-09-24 05:21:58 +000087 def __nonzero__(self):
88 return 1
Fred Drake55c38192000-06-29 19:39:57 +000089
Fred Drake1f549022000-09-24 05:21:58 +000090 def toxml(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +000091 writer = _get_StringIO()
Fred Drake1f549022000-09-24 05:21:58 +000092 self.writexml(writer)
Fred Drake55c38192000-06-29 19:39:57 +000093 return writer.getvalue()
94
Fred Drake1f549022000-09-24 05:21:58 +000095 def hasChildNodes(self):
96 if self.childNodes:
97 return 1
98 else:
99 return 0
Fred Drake55c38192000-06-29 19:39:57 +0000100
Fred Drake1f549022000-09-24 05:21:58 +0000101 def _get_firstChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000102 if self.childNodes:
103 return self.childNodes[0]
Paul Prescod73678da2000-07-01 04:58:47 +0000104
Fred Drake1f549022000-09-24 05:21:58 +0000105 def _get_lastChild(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000106 if self.childNodes:
107 return self.childNodes[-1]
Paul Prescod73678da2000-07-01 04:58:47 +0000108
Fred Drake1f549022000-09-24 05:21:58 +0000109 def insertBefore(self, newChild, refChild):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000110 if refChild is None:
111 self.appendChild(newChild)
112 else:
113 index = self.childNodes.index(refChild)
114 self.childNodes.insert(index, newChild)
115 newChild.nextSibling = refChild
116 refChild.previousSibling = newChild
117 if index:
118 node = self.childNodes[index-1]
119 node.nextSibling = newChild
120 newChild.previousSibling = node
121 else:
122 newChild.previousSibling = None
123 if self._makeParentNodes:
124 newChild.parentNode = self
125 return newChild
Fred Drake55c38192000-06-29 19:39:57 +0000126
Fred Drake1f549022000-09-24 05:21:58 +0000127 def appendChild(self, node):
Fred Drake13a30692000-10-09 20:04:16 +0000128 if self.childNodes:
129 last = self.lastChild
130 node.previousSibling = last
131 last.nextSibling = node
132 else:
133 node.previousSibling = None
134 node.nextSibling = None
Fred Drake1f549022000-09-24 05:21:58 +0000135 self.childNodes.append(node)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000136 if self._makeParentNodes:
137 node.parentNode = self
Paul Prescod73678da2000-07-01 04:58:47 +0000138 return node
139
Fred Drake1f549022000-09-24 05:21:58 +0000140 def replaceChild(self, newChild, oldChild):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000141 if newChild is oldChild:
142 return
Fred Drake1f549022000-09-24 05:21:58 +0000143 index = self.childNodes.index(oldChild)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000144 self.childNodes[index] = newChild
145 if self._makeParentNodes:
146 newChild.parentNode = self
147 oldChild.parentNode = None
148 newChild.nextSibling = oldChild.nextSibling
149 newChild.previousSibling = oldChild.previousSibling
150 oldChild.newChild = None
151 oldChild.previousSibling = None
152 return oldChild
Paul Prescod73678da2000-07-01 04:58:47 +0000153
Fred Drake1f549022000-09-24 05:21:58 +0000154 def removeChild(self, oldChild):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000155 self.childNodes.remove(oldChild)
156 if self._makeParentNodes:
157 oldChild.parentNode = None
158 return oldChild
159
160 def normalize(self):
161 if len(self.childNodes) > 1:
162 L = [self.childNodes[0]]
163 for child in self.childNodes[1:]:
164 if ( child.nodeType == Node.TEXT_NODE
165 and L[-1].nodeType == child.nodeType):
166 # collapse text node
167 node = L[-1]
168 node.data = node.nodeValue = node.data + child.data
169 node.nextSibling = child.nextSibling
170 child.unlink()
171 else:
172 L[-1].nextSibling = child
173 child.previousSibling = L[-1]
174 L.append(child)
175 child.normalize()
176 self.childNodes = L
177 elif self.childNodes:
178 # exactly one child -- just recurse
179 self.childNodes[0].normalize()
Paul Prescod73678da2000-07-01 04:58:47 +0000180
Fred Drake1f549022000-09-24 05:21:58 +0000181 def cloneNode(self, deep):
Paul Prescod73678da2000-07-01 04:58:47 +0000182 import new
Fred Drake4ccf4a12000-11-21 22:02:22 +0000183 clone = new.instance(self.__class__, self.__dict__.copy())
184 if self._makeParentNodes:
185 clone.parentNode = None
186 clone.childNodes = []
187 if deep:
188 for child in self.childNodes:
189 clone.appendChild(child.cloneNode(1))
Paul Prescod73678da2000-07-01 04:58:47 +0000190 return clone
Fred Drake55c38192000-06-29 19:39:57 +0000191
Fred Drake1f549022000-09-24 05:21:58 +0000192 def unlink(self):
193 self.parentNode = None
Fred Drake4ccf4a12000-11-21 22:02:22 +0000194 for child in self.childNodes:
195 child.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000196 self.childNodes = None
Paul Prescod4221ff02000-10-13 20:11:42 +0000197 self.previousSibling = None
198 self.nextSibling = None
Paul Prescod73678da2000-07-01 04:58:47 +0000199 if Node._debug:
Fred Drake1f549022000-09-24 05:21:58 +0000200 index = repr(id(self)) + repr(self.__class__)
201 self.debug.write("Deleting: %s\n" % index)
Paul Prescod73678da2000-07-01 04:58:47 +0000202 del Node.allnodes[index]
Fred Drake55c38192000-06-29 19:39:57 +0000203
Fred Drake1f549022000-09-24 05:21:58 +0000204def _write_data(writer, data):
Fred Drake55c38192000-06-29 19:39:57 +0000205 "Writes datachars to writer."
Fred Drake4ccf4a12000-11-21 22:02:22 +0000206 replace = _string.replace
207 data = replace(data, "&", "&amp;")
208 data = replace(data, "<", "&lt;")
209 data = replace(data, "\"", "&quot;")
210 data = replace(data, ">", "&gt;")
Fred Drake55c38192000-06-29 19:39:57 +0000211 writer.write(data)
212
Fred Drake1f549022000-09-24 05:21:58 +0000213def _getElementsByTagNameHelper(parent, name, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000214 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000215 if node.nodeType == Node.ELEMENT_NODE and \
216 (name == "*" or node.tagName == name):
217 rc.append(node)
218 _getElementsByTagNameHelper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000219 return rc
220
Fred Drake1f549022000-09-24 05:21:58 +0000221def _getElementsByTagNameNSHelper(parent, nsURI, localName, rc):
Fred Drake55c38192000-06-29 19:39:57 +0000222 for node in parent.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000223 if node.nodeType == Node.ELEMENT_NODE:
224 if ((localName == "*" or node.tagName == localName) and
225 (nsURI == "*" or node.namespaceURI == nsURI)):
226 rc.append(node)
227 _getElementsByTagNameNSHelper(node, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000228
229class Attr(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000230 nodeType = Node.ATTRIBUTE_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000231 attributes = None
232 ownerElement = None
Fred Drake1f549022000-09-24 05:21:58 +0000233
234 def __init__(self, qName, namespaceURI="", localName=None, prefix=None):
Fred Drake55c38192000-06-29 19:39:57 +0000235 # skip setattr for performance
Fred Drake4ccf4a12000-11-21 22:02:22 +0000236 d = self.__dict__
237 d["localName"] = localName or qName
238 d["nodeName"] = d["name"] = qName
239 d["namespaceURI"] = namespaceURI
240 d["prefix"] = prefix
Fred Drake1f549022000-09-24 05:21:58 +0000241 Node.__init__(self)
Paul Prescod73678da2000-07-01 04:58:47 +0000242 # nodeValue and value are set elsewhere
Fred Drake55c38192000-06-29 19:39:57 +0000243
Fred Drake1f549022000-09-24 05:21:58 +0000244 def __setattr__(self, name, value):
245 if name in ("value", "nodeValue"):
246 self.__dict__["value"] = self.__dict__["nodeValue"] = value
Fred Drake55c38192000-06-29 19:39:57 +0000247 else:
Fred Drake1f549022000-09-24 05:21:58 +0000248 self.__dict__[name] = value
Fred Drake55c38192000-06-29 19:39:57 +0000249
Fred Drake4ccf4a12000-11-21 22:02:22 +0000250 def cloneNode(self, deep):
251 clone = Node.cloneNode(self, deep)
252 if clone.__dict__.has_key("ownerElement"):
253 del clone.ownerElement
254 return clone
255
Fred Drake55c38192000-06-29 19:39:57 +0000256class AttributeList:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000257 """The attribute list is a transient interface to the underlying
258 dictionaries. Mutations here will change the underlying element's
Fred Drake1f549022000-09-24 05:21:58 +0000259 dictionary"""
Fred Drake4ccf4a12000-11-21 22:02:22 +0000260
Fred Drake1f549022000-09-24 05:21:58 +0000261 def __init__(self, attrs, attrsNS):
262 self._attrs = attrs
263 self._attrsNS = attrsNS
Fred Drake4ccf4a12000-11-21 22:02:22 +0000264 self.length = len(self._attrs)
Fred Drake55c38192000-06-29 19:39:57 +0000265
Fred Drake1f549022000-09-24 05:21:58 +0000266 def item(self, index):
Fred Drake55c38192000-06-29 19:39:57 +0000267 try:
268 return self[self.keys()[index]]
269 except IndexError:
270 return None
Fred Drake55c38192000-06-29 19:39:57 +0000271
Fred Drake1f549022000-09-24 05:21:58 +0000272 def items(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000273 L = []
274 for node in self._attrs.values():
275 L.append((node.tagName, node.value))
276 return L
Fred Drake1f549022000-09-24 05:21:58 +0000277
278 def itemsNS(self):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000279 L = []
280 for node in self._attrs.values():
281 L.append(((node.URI, node.localName), node.value))
282 return L
Fred Drake16f63292000-10-23 18:09:50 +0000283
Fred Drake1f549022000-09-24 05:21:58 +0000284 def keys(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000285 return self._attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000286
Fred Drake1f549022000-09-24 05:21:58 +0000287 def keysNS(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000288 return self._attrsNS.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000289
Fred Drake1f549022000-09-24 05:21:58 +0000290 def values(self):
Paul Prescod73678da2000-07-01 04:58:47 +0000291 return self._attrs.values()
Fred Drake55c38192000-06-29 19:39:57 +0000292
Fred Drake1f549022000-09-24 05:21:58 +0000293 def __len__(self):
Fred Drake55c38192000-06-29 19:39:57 +0000294 return self.length
295
Fred Drake1f549022000-09-24 05:21:58 +0000296 def __cmp__(self, other):
297 if self._attrs is getattr(other, "_attrs", None):
Fred Drake55c38192000-06-29 19:39:57 +0000298 return 0
Fred Drake16f63292000-10-23 18:09:50 +0000299 else:
Fred Drake1f549022000-09-24 05:21:58 +0000300 return cmp(id(self), id(other))
Fred Drake55c38192000-06-29 19:39:57 +0000301
302 #FIXME: is it appropriate to return .value?
Fred Drake1f549022000-09-24 05:21:58 +0000303 def __getitem__(self, attname_or_tuple):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000304 if type(attname_or_tuple) is _TupleType:
Paul Prescod73678da2000-07-01 04:58:47 +0000305 return self._attrsNS[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000306 else:
Paul Prescod73678da2000-07-01 04:58:47 +0000307 return self._attrs[attname_or_tuple]
Fred Drake55c38192000-06-29 19:39:57 +0000308
Paul Prescod1e688272000-07-01 19:21:47 +0000309 # same as set
Fred Drake1f549022000-09-24 05:21:58 +0000310 def __setitem__(self, attname, value):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000311 if type(value) in _StringTypes:
Fred Drake1f549022000-09-24 05:21:58 +0000312 node = Attr(attname)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000313 node.value = value
Paul Prescod1e688272000-07-01 19:21:47 +0000314 else:
Fred Drake4ccf4a12000-11-21 22:02:22 +0000315 if not isinstance(value, Attr):
316 raise TypeError, "value must be a string or Attr object"
Fred Drake1f549022000-09-24 05:21:58 +0000317 node = value
318 old = self._attrs.get(attname, None)
Paul Prescod1e688272000-07-01 19:21:47 +0000319 if old:
320 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000321 self._attrs[node.name] = node
322 self._attrsNS[(node.namespaceURI, node.localName)] = node
Paul Prescod73678da2000-07-01 04:58:47 +0000323
Fred Drake1f549022000-09-24 05:21:58 +0000324 def __delitem__(self, attname_or_tuple):
325 node = self[attname_or_tuple]
Paul Prescod73678da2000-07-01 04:58:47 +0000326 node.unlink()
327 del self._attrs[node.name]
328 del self._attrsNS[(node.namespaceURI, node.localName)]
Fred Drake1f549022000-09-24 05:21:58 +0000329
Martin v. Löwisa2fda0d2000-10-07 12:10:28 +0000330class Element(Node):
Fred Drake1f549022000-09-24 05:21:58 +0000331 nodeType = Node.ELEMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000332 nextSibling = None
333 previousSibling = None
Fred Drake1f549022000-09-24 05:21:58 +0000334
335 def __init__(self, tagName, namespaceURI="", prefix="",
336 localName=None):
337 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000338 self.tagName = self.nodeName = tagName
Fred Drake1f549022000-09-24 05:21:58 +0000339 self.localName = localName or tagName
340 self.prefix = prefix
341 self.namespaceURI = namespaceURI
342 self.nodeValue = None
Fred Drake55c38192000-06-29 19:39:57 +0000343
Fred Drake4ccf4a12000-11-21 22:02:22 +0000344 self._attrs = {} # attributes are double-indexed:
345 self._attrsNS = {} # tagName -> Attribute
346 # URI,localName -> Attribute
347 # in the future: consider lazy generation
348 # of attribute objects this is too tricky
349 # for now because of headaches with
350 # namespaces.
351
352 def cloneNode(self, deep):
353 clone = Node.cloneNode(self, deep)
354 clone._attrs = {}
355 clone._attrsNS = {}
356 for attr in self._attrs.values():
357 node = attr.cloneNode(1)
358 clone._attrs[node.name] = node
359 clone._attrsNS[(node.namespaceURI, node.localName)] = node
360 node.ownerElement = clone
361 return clone
362
363 def unlink(self):
364 for attr in self._attrs.values():
365 attr.unlink()
366 self._attrs = None
367 self._attrsNS = None
368 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000369
Fred Drake1f549022000-09-24 05:21:58 +0000370 def getAttribute(self, attname):
Paul Prescod73678da2000-07-01 04:58:47 +0000371 return self._attrs[attname].value
Fred Drake55c38192000-06-29 19:39:57 +0000372
Fred Drake1f549022000-09-24 05:21:58 +0000373 def getAttributeNS(self, namespaceURI, localName):
Paul Prescod73678da2000-07-01 04:58:47 +0000374 return self._attrsNS[(namespaceURI, localName)].value
Fred Drake1f549022000-09-24 05:21:58 +0000375
376 def setAttribute(self, attname, value):
377 attr = Attr(attname)
Fred Drake55c38192000-06-29 19:39:57 +0000378 # for performance
Fred Drake1f549022000-09-24 05:21:58 +0000379 attr.__dict__["value"] = attr.__dict__["nodeValue"] = value
380 self.setAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000381
Fred Drake1f549022000-09-24 05:21:58 +0000382 def setAttributeNS(self, namespaceURI, qualifiedName, value):
383 prefix, localname = _nssplit(qualifiedName)
Fred Drake55c38192000-06-29 19:39:57 +0000384 # for performance
Fred Drake1f549022000-09-24 05:21:58 +0000385 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
386 attr.__dict__["value"] = attr.__dict__["nodeValue"] = value
387 self.setAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000388
Fred Drake1f549022000-09-24 05:21:58 +0000389 def getAttributeNode(self, attrname):
390 return self._attrs.get(attrname)
Paul Prescod73678da2000-07-01 04:58:47 +0000391
Fred Drake1f549022000-09-24 05:21:58 +0000392 def getAttributeNodeNS(self, namespaceURI, localName):
Paul Prescod73678da2000-07-01 04:58:47 +0000393 return self._attrsNS[(namespaceURI, localName)]
394
Fred Drake1f549022000-09-24 05:21:58 +0000395 def setAttributeNode(self, attr):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000396 if attr.ownerElement not in (None, self):
397 raise ValueError, "attribute node already owned"
Fred Drake1f549022000-09-24 05:21:58 +0000398 old = self._attrs.get(attr.name, None)
Paul Prescod73678da2000-07-01 04:58:47 +0000399 if old:
400 old.unlink()
Fred Drake1f549022000-09-24 05:21:58 +0000401 self._attrs[attr.name] = attr
402 self._attrsNS[(attr.namespaceURI, attr.localName)] = attr
Fred Drake4ccf4a12000-11-21 22:02:22 +0000403
404 # This creates a circular reference, but Element.unlink()
405 # breaks the cycle since the references to the attribute
406 # dictionaries are tossed.
407 attr.ownerElement = self
408
409 if old is not attr:
410 # It might have already been part of this node, in which case
411 # it doesn't represent a change, and should not be returned.
412 return old
Fred Drake55c38192000-06-29 19:39:57 +0000413
Fred Drake1f549022000-09-24 05:21:58 +0000414 def removeAttribute(self, name):
Paul Prescod73678da2000-07-01 04:58:47 +0000415 attr = self._attrs[name]
Fred Drake1f549022000-09-24 05:21:58 +0000416 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000417
Fred Drake1f549022000-09-24 05:21:58 +0000418 def removeAttributeNS(self, namespaceURI, localName):
Paul Prescod73678da2000-07-01 04:58:47 +0000419 attr = self._attrsNS[(namespaceURI, localName)]
Fred Drake1f549022000-09-24 05:21:58 +0000420 self.removeAttributeNode(attr)
Fred Drake55c38192000-06-29 19:39:57 +0000421
Fred Drake1f549022000-09-24 05:21:58 +0000422 def removeAttributeNode(self, node):
Paul Prescod73678da2000-07-01 04:58:47 +0000423 node.unlink()
424 del self._attrs[node.name]
425 del self._attrsNS[(node.namespaceURI, node.localName)]
Fred Drake16f63292000-10-23 18:09:50 +0000426
Fred Drake1f549022000-09-24 05:21:58 +0000427 def getElementsByTagName(self, name):
428 return _getElementsByTagNameHelper(self, name, [])
Fred Drake55c38192000-06-29 19:39:57 +0000429
Fred Drake1f549022000-09-24 05:21:58 +0000430 def getElementsByTagNameNS(self, namespaceURI, localName):
431 _getElementsByTagNameNSHelper(self, namespaceURI, localName, [])
Fred Drake55c38192000-06-29 19:39:57 +0000432
Fred Drake1f549022000-09-24 05:21:58 +0000433 def __repr__(self):
434 return "<DOM Element: %s at %s>" % (self.tagName, id(self))
Fred Drake55c38192000-06-29 19:39:57 +0000435
436 def writexml(self, writer):
Fred Drake1f549022000-09-24 05:21:58 +0000437 writer.write("<" + self.tagName)
Fred Drake16f63292000-10-23 18:09:50 +0000438
Fred Drake4ccf4a12000-11-21 22:02:22 +0000439 attrs = self._get_attributes()
440 a_names = attrs.keys()
Fred Drake55c38192000-06-29 19:39:57 +0000441 a_names.sort()
442
443 for a_name in a_names:
Fred Drake1f549022000-09-24 05:21:58 +0000444 writer.write(" %s=\"" % a_name)
Fred Drake4ccf4a12000-11-21 22:02:22 +0000445 _write_data(writer, attrs[a_name].value)
Fred Drake55c38192000-06-29 19:39:57 +0000446 writer.write("\"")
447 if self.childNodes:
448 writer.write(">")
449 for node in self.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000450 node.writexml(writer)
451 writer.write("</%s>" % self.tagName)
Fred Drake55c38192000-06-29 19:39:57 +0000452 else:
453 writer.write("/>")
454
Fred Drake1f549022000-09-24 05:21:58 +0000455 def _get_attributes(self):
456 return AttributeList(self._attrs, self._attrsNS)
Fred Drake55c38192000-06-29 19:39:57 +0000457
Fred Drake1f549022000-09-24 05:21:58 +0000458class Comment(Node):
459 nodeType = Node.COMMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000460 nodeName = "#comment"
461 attributes = None
Fred Drake55c38192000-06-29 19:39:57 +0000462
Fred Drake1f549022000-09-24 05:21:58 +0000463 def __init__(self, data):
464 Node.__init__(self)
465 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000466
Fred Drake1f549022000-09-24 05:21:58 +0000467 def writexml(self, writer):
468 writer.write("<!--%s-->" % self.data)
469
470class ProcessingInstruction(Node):
471 nodeType = Node.PROCESSING_INSTRUCTION_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000472 attributes = None
Fred Drake1f549022000-09-24 05:21:58 +0000473
474 def __init__(self, target, data):
475 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000476 self.target = self.nodeName = target
477 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000478
Fred Drake1f549022000-09-24 05:21:58 +0000479 def writexml(self, writer):
480 writer.write("<?%s %s?>" % (self.target, self.data))
Fred Drake55c38192000-06-29 19:39:57 +0000481
Fred Drake1f549022000-09-24 05:21:58 +0000482class Text(Node):
483 nodeType = Node.TEXT_NODE
484 nodeName = "#text"
Fred Drake4ccf4a12000-11-21 22:02:22 +0000485 attributes = None
Fred Drake1f549022000-09-24 05:21:58 +0000486
487 def __init__(self, data):
488 Node.__init__(self)
Fred Drake55c38192000-06-29 19:39:57 +0000489 self.data = self.nodeValue = data
Fred Drake55c38192000-06-29 19:39:57 +0000490
491 def __repr__(self):
Fred Drake1f549022000-09-24 05:21:58 +0000492 if len(self.data) > 10:
493 dotdotdot = "..."
Fred Drake55c38192000-06-29 19:39:57 +0000494 else:
Fred Drake1f549022000-09-24 05:21:58 +0000495 dotdotdot = ""
496 return "<DOM Text node \"%s%s\">" % (self.data[0:10], dotdotdot)
Fred Drake55c38192000-06-29 19:39:57 +0000497
Fred Drake1f549022000-09-24 05:21:58 +0000498 def writexml(self, writer):
499 _write_data(writer, self.data)
Fred Drake55c38192000-06-29 19:39:57 +0000500
Fred Drake1f549022000-09-24 05:21:58 +0000501def _nssplit(qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000502 fields = _string.split(qualifiedName, ':', 1)
Paul Prescod73678da2000-07-01 04:58:47 +0000503 if len(fields) == 2:
504 return fields
505 elif len(fields) == 1:
Fred Drake1f549022000-09-24 05:21:58 +0000506 return ('', fields[0])
Paul Prescod73678da2000-07-01 04:58:47 +0000507
Fred Drake1f549022000-09-24 05:21:58 +0000508class Document(Node):
509 nodeType = Node.DOCUMENT_NODE
Fred Drake4ccf4a12000-11-21 22:02:22 +0000510 nodeName = "#document"
511 nodeValue = None
512 attributes = None
Fred Drake1f549022000-09-24 05:21:58 +0000513 documentElement = None
Fred Drake55c38192000-06-29 19:39:57 +0000514
Fred Drake1f549022000-09-24 05:21:58 +0000515 def appendChild(self, node):
516 if node.nodeType == Node.ELEMENT_NODE:
Paul Prescodce88db02000-09-15 17:09:19 +0000517 if self.documentElement:
518 raise TypeError, "Two document elements disallowed"
519 else:
Fred Drake1f549022000-09-24 05:21:58 +0000520 self.documentElement = node
Fred Drake4ccf4a12000-11-21 22:02:22 +0000521 return Node.appendChild(self, node)
Paul Prescod73678da2000-07-01 04:58:47 +0000522
Fred Drake1f549022000-09-24 05:21:58 +0000523 createElement = Element
Fred Drake55c38192000-06-29 19:39:57 +0000524
Fred Drake1f549022000-09-24 05:21:58 +0000525 createTextNode = Text
Fred Drake55c38192000-06-29 19:39:57 +0000526
Fred Drake1f549022000-09-24 05:21:58 +0000527 createComment = Comment
Fred Drake55c38192000-06-29 19:39:57 +0000528
Fred Drake1f549022000-09-24 05:21:58 +0000529 createProcessingInstruction = ProcessingInstruction
Fred Drake55c38192000-06-29 19:39:57 +0000530
Fred Drake1f549022000-09-24 05:21:58 +0000531 createAttribute = Attr
Fred Drake55c38192000-06-29 19:39:57 +0000532
533 def createElementNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000534 prefix, localName = _nssplit(qualifiedName)
535 return self.createElement(qualifiedName, namespaceURI,
536 prefix, localName)
Fred Drake55c38192000-06-29 19:39:57 +0000537
538 def createAttributeNS(self, namespaceURI, qualifiedName):
Fred Drake4ccf4a12000-11-21 22:02:22 +0000539 prefix, localName = _nssplit(qualifiedName)
540 return self.createAttribute(qualifiedName, namespaceURI,
541 localName, prefix)
Fred Drake55c38192000-06-29 19:39:57 +0000542
Fred Drake1f549022000-09-24 05:21:58 +0000543 def getElementsByTagNameNS(self, namespaceURI, localName):
544 _getElementsByTagNameNSHelper(self, namespaceURI, localName)
Fred Drake55c38192000-06-29 19:39:57 +0000545
Fred Drake1f549022000-09-24 05:21:58 +0000546 def unlink(self):
547 self.documentElement = None
548 Node.unlink(self)
Fred Drake55c38192000-06-29 19:39:57 +0000549
Fred Drake1f549022000-09-24 05:21:58 +0000550 def getElementsByTagName(self, name):
551 rc = []
552 _getElementsByTagNameHelper(self, name, rc)
Fred Drake55c38192000-06-29 19:39:57 +0000553 return rc
554
Fred Drake1f549022000-09-24 05:21:58 +0000555 def writexml(self, writer):
Fred Drake55c38192000-06-29 19:39:57 +0000556 for node in self.childNodes:
Fred Drake1f549022000-09-24 05:21:58 +0000557 node.writexml(writer)
Fred Drake55c38192000-06-29 19:39:57 +0000558
Fred Drake4ccf4a12000-11-21 22:02:22 +0000559def _get_StringIO():
560 try:
561 from cStringIO import StringIO
562 except ImportError:
563 from StringIO import StringIO
564 return StringIO()
565
Fred Drake1f549022000-09-24 05:21:58 +0000566def _doparse(func, args, kwargs):
567 events = apply(func, args, kwargs)
568 toktype, rootNode = events.getEvent()
569 events.expandNode(rootNode)
Fred Drake55c38192000-06-29 19:39:57 +0000570 return rootNode
571
Fred Drake1f549022000-09-24 05:21:58 +0000572def parse(*args, **kwargs):
Paul Prescod623511b2000-07-21 22:05:49 +0000573 "Parse a file into a DOM by filename or file object"
Fred Drake4ccf4a12000-11-21 22:02:22 +0000574 from xml.dom import pulldom
Fred Drake1f549022000-09-24 05:21:58 +0000575 return _doparse(pulldom.parse, args, kwargs)
Fred Drake55c38192000-06-29 19:39:57 +0000576
Fred Drake1f549022000-09-24 05:21:58 +0000577def parseString(*args, **kwargs):
Paul Prescod623511b2000-07-21 22:05:49 +0000578 "Parse a file into a DOM from a string"
Fred Drake4ccf4a12000-11-21 22:02:22 +0000579 from xml.dom import pulldom
Fred Drake1f549022000-09-24 05:21:58 +0000580 return _doparse(pulldom.parseString, args, kwargs)