1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """module that provides modified DOM functionality for our needs
24
25 Note that users of ourdom should ensure that no code might still use classes
26 directly from minidom, like minidom.Element, minidom.Document or methods such
27 as minidom.parseString, since the functionality provided here will not be in
28 those objects.
29 """
30
31 from xml.dom import minidom
32 from xml.dom import expatbuilder
33
34
35
37 """A replacement for writexml that formats it like typical XML files.
38 Nodes are intendented but text nodes, where whitespace can be significant, are not indented."""
39
40
41
42 writer.write(indent+"<" + self.tagName)
43
44 attrs = self._get_attributes()
45 a_names = attrs.keys()
46 a_names.sort()
47
48 for a_name in a_names:
49 writer.write(" %s=\"" % a_name)
50 minidom._write_data(writer, attrs[a_name].value)
51 writer.write("\"")
52 if self.childNodes:
53
54
55
56
57
58
59 haveText = False
60 for childNode in self.childNodes:
61 if childNode.nodeType == self.TEXT_NODE and childNode.data.strip():
62 haveText = True
63 break
64 if haveText:
65 writer.write(">")
66 for node in self.childNodes:
67 node.writexml(writer,"","","")
68 writer.write("</%s>%s" % (self.tagName,newl))
69 else:
70
71 writer.write(">%s"%(newl))
72 for node in self.childNodes:
73 if node.nodeType != self.TEXT_NODE:
74 node.writexml(writer,indent+addindent,addindent,newl)
75 writer.write("%s</%s>%s" % (indent,self.tagName,newl))
76 else:
77 writer.write("/>%s"%(newl))
78
80 """A reimplementation of getElementsByTagName as an iterator.
81
82 Note that this is not compatible with getElementsByTagName that returns a
83 list, therefore, the class below exposes this through yieldElementsByTagName"""
84
85 for node in parent.childNodes:
86 if node.nodeType == minidom.Node.ELEMENT_NODE and \
87 (name == "*" or node.tagName == name):
88 yield node
89 if node.hasChildNodes():
90 for othernode in node.getElementsByTagName(name):
91 yield othernode
92
94 """limits the search to within tags occuring in onlysearch"""
95 for node in parent.childNodes:
96 if node.nodeType == minidom.Node.ELEMENT_NODE and \
97 (name == "*" or node.tagName == name):
98 yield node
99 if node.nodeType == minidom.Node.ELEMENT_NODE and node.tagName in onlysearch:
100 for node in node.searchElementsByTagName(name, onlysearch):
101 yield node
102
104 results = node.yieldElementsByTagName(name)
105
106
107
108
109
110 try:
111 result = results.next()
112 return result
113 except StopIteration:
114 return None
115
116 -def getnodetext(node):
117 """returns the node's text by iterating through the child nodes"""
118 if node is None: return ""
119 return "".join([t.data for t in node.childNodes if t.nodeType == t.TEXT_NODE])
120
121
122
126
132 - def writexml(self, writer, indent, addindent, newl):
134
150
151 theDOMImplementation = DOMImplementation()
152
153
154
157 """Free all data structures used during DOM construction."""
158 self.document = theDOMImplementation.createDocument(
159 expatbuilder.EMPTY_NAMESPACE, None, None)
160 self.curNode = self.document
161 self._elem_info = self.document._elem_info
162 self._cdata = False
163 self._initNamespaces()
164
166
167
168 if ' ' in name:
169 uri, localname, prefix, qname = expatbuilder._parse_ns_name(self, name)
170 else:
171 uri = expatbuilder.EMPTY_NAMESPACE
172 qname = name
173 localname = None
174 prefix = expatbuilder.EMPTY_PREFIX
175 node = Element(qname, uri, prefix, localname)
176 node.ownerDocument = self.document
177 expatbuilder._append_child(self.curNode, node)
178 self.curNode = node
179
180 if self._ns_ordered_prefixes:
181 for prefix, uri in self._ns_ordered_prefixes:
182 if prefix:
183 a = minidom.Attr(expatbuilder._intern(self, 'xmlns:' + prefix),
184 expatbuilder.XMLNS_NAMESPACE, prefix, "xmlns")
185 else:
186 a = minidom.Attr("xmlns", expatbuilder.XMLNS_NAMESPACE,
187 "xmlns", expatbuilder.EMPTY_PREFIX)
188 d = a.childNodes[0].__dict__
189 d['data'] = d['nodeValue'] = uri
190 d = a.__dict__
191 d['value'] = d['nodeValue'] = uri
192 d['ownerDocument'] = self.document
193 expatbuilder._set_attribute_node(node, a)
194 del self._ns_ordered_prefixes[:]
195
196 if attributes:
197 _attrs = node._attrs
198 _attrsNS = node._attrsNS
199 for i in range(0, len(attributes), 2):
200 aname = attributes[i]
201 value = attributes[i+1]
202 if ' ' in aname:
203 uri, localname, prefix, qname = expatbuilder._parse_ns_name(self, aname)
204 a = minidom.Attr(qname, uri, localname, prefix)
205 _attrs[qname] = a
206 _attrsNS[(uri, localname)] = a
207 else:
208 a = minidom.Attr(aname, expatbuilder.EMPTY_NAMESPACE,
209 aname, expatbuilder.EMPTY_PREFIX)
210 _attrs[aname] = a
211 _attrsNS[(expatbuilder.EMPTY_NAMESPACE, aname)] = a
212 d = a.childNodes[0].__dict__
213 d['data'] = d['nodeValue'] = value
214 d = a.__dict__
215 d['ownerDocument'] = self.document
216 d['value'] = d['nodeValue'] = value
217 d['ownerElement'] = node
218
219 if __debug__:
220
221
222
223
224
226 curNode = self.curNode
227 if ' ' in name:
228 uri, localname, prefix, qname = expatbuilder._parse_ns_name(self, name)
229 assert (curNode.namespaceURI == uri
230 and curNode.localName == localname
231 and curNode.prefix == prefix), \
232 "element stack messed up! (namespace)"
233 else:
234 assert curNode.nodeName == name, \
235 "element stack messed up - bad nodeName"
236 assert curNode.namespaceURI == expatbuilder.EMPTY_NAMESPACE, \
237 "element stack messed up - bad namespaceURI"
238 self.curNode = curNode.parentNode
239 self._finish_end_element(curNode)
240
241
242
243 -def parse(file, parser=None, bufsize=None):
244 """Parse a file into a DOM by filename or file object."""
245 builder = ExpatBuilderNS()
246 if isinstance(file, basestring):
247 fp = open(file, 'rb')
248 try:
249 result = builder.parseFile(fp)
250 finally:
251 fp.close()
252 else:
253 result = builder.parseFile(file)
254 return result
255
260