|
1 # |
|
2 # # minixsv, Release 0.3 |
|
3 # file: minidomif.py |
|
4 # |
|
5 # XML interface class to minidom |
|
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 import urllib |
|
46 from xmlifbase import * |
|
47 from xml.parsers.expat import ExpatError |
|
48 from xml.dom.expatbuilder import ExpatBuilderNS |
|
49 from xml.dom.minidom import * |
|
50 |
|
51 |
|
52 class MiniDomInterface (XmlInterfaceBase): |
|
53 ##################################################### |
|
54 # for description of the interface methods see xmlifbase.py |
|
55 ##################################################### |
|
56 |
|
57 def __init__ (self, verbose): |
|
58 XmlInterfaceBase.__init__ (self, verbose) |
|
59 if self.verbose: |
|
60 print "Using minidom interface module..." |
|
61 |
|
62 |
|
63 def parse (self, file, baseUrl): |
|
64 url = self._convertToUrl(file) |
|
65 absUrl = self._convertToAbsUrl (url, baseUrl) |
|
66 fp = urllib.urlopen (absUrl) |
|
67 try: |
|
68 builder = ExtExpatBuilderNS(file, url, absUrl) |
|
69 tree = builder.parseFile(fp) |
|
70 finally: |
|
71 fp.close() |
|
72 |
|
73 return TreeWrapper(self, tree) |
|
74 |
|
75 |
|
76 def parseString (self, text): |
|
77 builder = ExtExpatBuilderNS("", "", "") |
|
78 tree = builder.parseString (text) |
|
79 return TreeWrapper (self, tree) |
|
80 |
|
81 |
|
82 ######################################################### |
|
83 # Wrapper class for minidom.Document class |
|
84 |
|
85 class TreeWrapper (TreeWrapperBase): |
|
86 |
|
87 def getRootNode (self): |
|
88 return ElementWrapper (self.xmlIf, self, self.tree.documentElement) |
|
89 |
|
90 def insertSubtree (self, nextSiblingWrapper, file, baseUrl): |
|
91 subTreeWrapper = self.xmlIf.extParse (file, baseUrl) |
|
92 assert self.getRootNode().getLocalName() == subTreeWrapper.getRootNode().getLocalName(),\ |
|
93 "%s: line %d: root node of include file %s does not match!" %(self.getRootNode().getUrl(), self.getRootNode().getStartLineNumber(), file) |
|
94 |
|
95 elementWrapperList = subTreeWrapper.getRootNode().getChildren() |
|
96 for elementWrapper in elementWrapperList: |
|
97 if nextSiblingWrapper != None: |
|
98 self.tree.documentElement.insertBefore(elementWrapper.element, nextSiblingWrapper.element) |
|
99 else: |
|
100 self.tree.documentElement.appendChild(elementWrapper.element) |
|
101 |
|
102 |
|
103 ######################################################### |
|
104 # Wrapper class for minidom.Document class |
|
105 |
|
106 class ElementWrapper (ElementWrapperBase): |
|
107 |
|
108 def getTagName (self): |
|
109 return self.element.tagName |
|
110 |
|
111 |
|
112 def getLocalName (self): |
|
113 # base method replaced (optimized method) |
|
114 return self.element.localName |
|
115 |
|
116 |
|
117 def getNamespaceURI (self): |
|
118 # base method replaced (optimized method) |
|
119 return self.element.namespaceURI |
|
120 |
|
121 |
|
122 def getChildren (self, filterTag=None): |
|
123 return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), self._getElemNodes(filterTag)) |
|
124 |
|
125 |
|
126 def getElementsByTagName (self, filterTag=None): |
|
127 if filterTag == None: |
|
128 filterTag = '*' |
|
129 return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), self.element.getElementsByTagName(filterTag)) |
|
130 |
|
131 |
|
132 def removeChild (self, childElementWrapper): |
|
133 self.element.removeChild(childElementWrapper.element) |
|
134 |
|
135 |
|
136 def getAttributeDict (self): |
|
137 """Return dictionary of attributes""" |
|
138 attribDict = {} |
|
139 for attrName, attrValue in self.element.attributes.items(): |
|
140 attribDict[attrName] = attrValue |
|
141 return attribDict |
|
142 |
|
143 |
|
144 def getAttribute (self, attributeName): |
|
145 if self.element.attributes.has_key (attributeName): |
|
146 return self.element.getAttribute (attributeName) |
|
147 else: |
|
148 return None |
|
149 |
|
150 |
|
151 def hasAttribute (self, attributeName): |
|
152 return self.element.attributes.has_key (attributeName) |
|
153 |
|
154 |
|
155 def setAttribute (self, attributeName, attributeValue): |
|
156 if not self.hasAttribute(attributeName): |
|
157 self.element.setAttributeNode (self.treeWrapper.tree.createAttribute (attributeName)) |
|
158 self.element.setAttribute(attributeName, attributeValue) |
|
159 |
|
160 |
|
161 ############################################################### |
|
162 # Caution! Currently returns only the first text node!! |
|
163 def getElementValue (self): |
|
164 textNodes = self._getTextNodes () |
|
165 if textNodes: |
|
166 return textNodes[0].data |
|
167 else: |
|
168 return "" |
|
169 |
|
170 |
|
171 ############################################################### |
|
172 # Caution! Currently only sets the first text node!! |
|
173 def setElementValue (self, value): |
|
174 textNodes = self._getTextNodes() |
|
175 if textNodes: |
|
176 textNodes[0].data = value |
|
177 |
|
178 |
|
179 ############################################################### |
|
180 # PRIVATE methods |
|
181 ############################################################### |
|
182 |
|
183 def _getTextNodes (self): |
|
184 """Return list of TEXT nodes.""" |
|
185 return filter (lambda e: (e.nodeType == Node.TEXT_NODE), # - only TEXT-NODES |
|
186 self.element.childNodes) # from element's child nodes |
|
187 |
|
188 |
|
189 def _getElemNodes (self, filterTag): |
|
190 """Return list of ELEMENT nodes and check for tag name (if given).""" |
|
191 return filter (lambda e: (e.nodeType == Node.ELEMENT_NODE) and # - only ELEMENTs |
|
192 (not filterTag or filterTag == '*' or e.tagName == filterTag), # - if tagName given --> check tagName |
|
193 self.element.childNodes) # from element's nodes |
|
194 |
|
195 |
|
196 |
|
197 ################################################### |
|
198 # Expat builder class derived from ExpatBuilderNS |
|
199 # extended to store related line numbers in the node object |
|
200 |
|
201 class ExtExpatBuilderNS (ExpatBuilderNS): |
|
202 def __init__ (self, filePath, url, absUrl): |
|
203 self.filePath = filePath |
|
204 self.url = url |
|
205 self.absUrl = absUrl |
|
206 ExpatBuilderNS.__init__(self) |
|
207 |
|
208 def start_element_handler(self, name, attributes): |
|
209 ExpatBuilderNS.start_element_handler(self, name, attributes) |
|
210 self.curNode.url = self.url |
|
211 self.curNode.absUrl = self.absUrl |
|
212 self.curNode.filePath = self.filePath |
|
213 self.curNode.startLineNumber = self.getParser().ErrorLineNumber |
|
214 |
|
215 def end_element_handler(self, name): |
|
216 self.curNode.endLineNumber = self.getParser().ErrorLineNumber |
|
217 ExpatBuilderNS.end_element_handler(self, name) |
|
218 |