|
1 # |
|
2 # minixsv, Release 0.3 |
|
3 # file: elemtreeif.py |
|
4 # |
|
5 # XML interface class to elementtree toolkit by Fredrik Lundh |
|
6 # |
|
7 # history: |
|
8 # 2004-09-09 rl created |
|
9 # 2004-09-22 rl XML interface classes completely re-designed |
|
10 # 2004-09-23 rl added filename and line number support |
|
11 # 2004-09-29 rl URL processing added |
|
12 # 2004-10-01 rl URL processing improved |
|
13 # 2004-10-12 rl XML text processing added |
|
14 # |
|
15 # Copyright (c) 2004 by Roland Leuthe. All rights reserved. |
|
16 # |
|
17 # -------------------------------------------------------------------- |
|
18 # The minixsv XML schema validator is |
|
19 # |
|
20 # Copyright (c) 2004 by Roland Leuthe |
|
21 # |
|
22 # By obtaining, using, and/or copying this software and/or its |
|
23 # associated documentation, you agree that you have read, understood, |
|
24 # and will comply with the following terms and conditions: |
|
25 # |
|
26 # Permission to use, copy, modify, and distribute this software and |
|
27 # its associated documentation for any purpose and without fee is |
|
28 # hereby granted, provided that the above copyright notice appears in |
|
29 # all copies, and that both that copyright notice and this permission |
|
30 # notice appear in supporting documentation, and that the name of |
|
31 # the author not be used in advertising or publicity |
|
32 # pertaining to distribution of the software without specific, written |
|
33 # prior permission. |
|
34 # |
|
35 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD |
|
36 # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- |
|
37 # ABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR |
|
38 # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY |
|
39 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
|
40 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS |
|
41 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
|
42 # OF THIS SOFTWARE. |
|
43 # -------------------------------------------------------------------- |
|
44 |
|
45 |
|
46 import urllib |
|
47 import urlparse |
|
48 from xmlifbase import * |
|
49 from xml.parsers.expat import ExpatError |
|
50 from elementtree.ElementTree import * |
|
51 |
|
52 ######################################################### |
|
53 # Derived interface class for elementtree toolkit |
|
54 |
|
55 class ElementTreeInterface (XmlInterfaceBase): |
|
56 ##################################################### |
|
57 # for description of the interface methods see xmlifbase.py |
|
58 ##################################################### |
|
59 |
|
60 def __init__ (self, verbose): |
|
61 XmlInterfaceBase.__init__ (self, verbose) |
|
62 if self.verbose: |
|
63 print "Using elementtree interface module..." |
|
64 |
|
65 |
|
66 def parse (self, file, baseUrl): |
|
67 url = self._convertToUrl(file) |
|
68 absUrl = self._convertToAbsUrl (url, baseUrl) |
|
69 fp = urllib.urlopen (absUrl) |
|
70 try: |
|
71 tree = ElementTree() |
|
72 parser = ExtXMLTreeBuilder(file, url, absUrl) |
|
73 tree.parse(fp, parser) |
|
74 finally: |
|
75 fp.close() |
|
76 |
|
77 return TreeWrapper(self, tree) |
|
78 |
|
79 |
|
80 def parseString (self, text): |
|
81 parser = ExtXMLTreeBuilder("", "", "") |
|
82 parser.feed(text) |
|
83 return TreeWrapper (self, ElementTree(parser.close())) |
|
84 |
|
85 |
|
86 ######################################################### |
|
87 # Wrapper class for ElementTree class |
|
88 |
|
89 class TreeWrapper (TreeWrapperBase): |
|
90 |
|
91 def getRootNode (self): |
|
92 return ElementWrapper(self.xmlIf, self, self.tree.getroot()) |
|
93 |
|
94 |
|
95 def insertSubtree (self, nextSiblingWrapper, file, baseUrl): |
|
96 subTreeWrapper = self.xmlIf.extParse (file, baseUrl) |
|
97 assert self.getRootNode().getTagName() == subTreeWrapper.getRootNode().getTagName(),\ |
|
98 "%s: line %d: root node of include file %s does not match!" %(self.getRootNode().getUrl(), self.getRootNode().getStartLineNumber(), file) |
|
99 |
|
100 if nextSiblingWrapper != None: |
|
101 insertIndex = self.tree.getroot().getchildren().index (nextSiblingWrapper.element) |
|
102 else: |
|
103 insertIndex = 0 |
|
104 elementWrapperList = subTreeWrapper.getRootNode().getChildren() |
|
105 elementWrapperList.reverse() |
|
106 for elementWrapper in elementWrapperList: |
|
107 self.tree.getroot().insert (insertIndex, elementWrapper.element) |
|
108 |
|
109 |
|
110 ######################################################### |
|
111 # Wrapper class for Element class |
|
112 |
|
113 class ElementWrapper (ElementWrapperBase): |
|
114 |
|
115 def getTagName (self): |
|
116 return self.element.tag |
|
117 |
|
118 |
|
119 def getChildren (self, filterTag=None): |
|
120 if filterTag in (None, '*'): |
|
121 children = self.element.getchildren() |
|
122 else: |
|
123 children = self.element.findall(filterTag) |
|
124 |
|
125 return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), children) |
|
126 |
|
127 |
|
128 def getFirstChild (self, filterTag=None): |
|
129 # replace base method (performance optimized) |
|
130 if filterTag in (None, '*'): |
|
131 children = self.element.getchildren() |
|
132 if children != []: |
|
133 element = children[0] |
|
134 else: |
|
135 element = None |
|
136 else: |
|
137 element = self.element.find(filterTag) |
|
138 |
|
139 if element != None: |
|
140 return ElementWrapper(self.xmlIf, self.treeWrapper, element) |
|
141 else: |
|
142 return None |
|
143 |
|
144 |
|
145 def getElementsByTagName (self, filterTag=None): |
|
146 if filterTag == '*': |
|
147 filterTag = None |
|
148 elements = self.element.getiterator (filterTag) |
|
149 |
|
150 return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), elements) |
|
151 |
|
152 |
|
153 def removeChild (self, childElementWrapper): |
|
154 self.element.remove (childElementWrapper.element) |
|
155 |
|
156 |
|
157 def getAttributeDict (self): |
|
158 return self.element.attrib |
|
159 |
|
160 |
|
161 def getAttribute (self, attributeName): |
|
162 if self.element.attrib.has_key(attributeName): |
|
163 return self.element.attrib[attributeName] |
|
164 else: |
|
165 return None |
|
166 |
|
167 |
|
168 def hasAttribute (self, attributeName): |
|
169 return self.element.attrib.has_key(attributeName) |
|
170 |
|
171 |
|
172 def setAttribute (self, attributeName, attributeValue): |
|
173 self.element.attrib[attributeName] = attributeValue |
|
174 |
|
175 |
|
176 ############################################################### |
|
177 # Caution! Currently returns only the element value until the first |
|
178 # child element!! |
|
179 def getElementValue (self): |
|
180 if self.element.text != None: |
|
181 return self.element.text |
|
182 else: |
|
183 return "" |
|
184 |
|
185 |
|
186 ############################################################### |
|
187 # Caution! Currently only sets the element value until the first |
|
188 # child element!! |
|
189 def setElementValue (self, value): |
|
190 self.element.text = value |
|
191 |
|
192 |
|
193 ################################################### |
|
194 # Element tree builder class derived from XMLTreeBuilder |
|
195 # extended to store related line numbers in the Element object |
|
196 |
|
197 class ExtXMLTreeBuilder (XMLTreeBuilder): |
|
198 def __init__(self, filePath, url, absUrl): |
|
199 self.filePath = filePath |
|
200 self.url = url |
|
201 self.absUrl = absUrl |
|
202 XMLTreeBuilder.__init__(self) |
|
203 |
|
204 def _start(self, tag, attrib_in): |
|
205 element = XMLTreeBuilder._start(self, tag, attrib_in) |
|
206 element.filePath = self.filePath |
|
207 element.url = self.url |
|
208 element.absUrl = self.absUrl |
|
209 element.startLineNumber = self._parser.ErrorLineNumber |
|
210 return element |
|
211 |
|
212 def _end(self, tag): |
|
213 element = XMLTreeBuilder._end(self, tag) |
|
214 element.endLineNumber = self._parser.ErrorLineNumber |
|
215 return element |
|
216 |
|
217 |