1 '''Module XMLpars
2 This module provides the class XMLParser especially designed for the use with the GUI.
3 You can create new XML files, write new data into an existing file and you can read information from a file.
4 There is already a search function implemented which gives back specific information.
5 This function can be used as a template for a more general search.
6
7 The communication interface is based on dictionaries.
8 @author: Tobias Heimpold
9 '''
10 import xml.dom.minidom as DOM
11 import os
12 from dsc_suite.tools.toolpaths import FOLDER_FOR_DATA as FFDATA
13
15 """class XMLParser(object)
16 This class is the parser for the XML files. It is based on dictionary interface to the GUI.
17 Every key in a dictionary is used as a tag name in the XML file. The value is either the tag content or (when a dictionary) the next hierarchical level of the XML file.
18 """
20 """__init__
21 - parses a XML file given by the path source or creates it
22 - mode is the tag name of the top level items
23 - root node must be named with mode+"s"
24 """
25 self.__source = source
26 self.__mode = mode
27 if not os.path.exists(source):
28 self.createNewXML(source, mode+"s")
29 self.__tree = DOM.parse(source)
30
31
33 """nextTopLevelTag(index)
34 - returns a dictionary with:
35 key ... tag name
36 value ... text in XML
37 - from the XML entry index
38 Hint: use with countTopLevelItems() to avoid index out of range exception !
39 """
40 root = self.__tree.firstChild
41
42 toplevelname = str(self.__findTopLevelItemName(self.__tree.firstChild))
43
44 olddata = self.__tree.getElementsByTagName(toplevelname)
45
46 datafile = olddata[index]
47
48 dict = self.__getTag(datafile, root)
49 return dict[toplevelname]
50
57
59 """writeNewData(dict)
60 - writes the data from dict into the XML File
61 - Attention: XML File must exist and have a root instance. The top level name is set by parsing the XML file --> see __init__
62 structure of dict:
63 {
64
65 <key1> : {<key2> : <value2>},
66 <key3> : <value3>
67 }
68 - results in XML structure:
69 <root>
70 <mode>
71 <key1>
72 <key2>value2</key2>
73 </key1>
74 </mode>
75 </root>
76 """
77
78 try:
79 toplevelname = str(self.__findTopLevelItemName(self.__tree.firstChild))
80 rootname = str(self.__tree.firstChild.tagName)
81 olddata = self.__tree.getElementsByTagName(toplevelname)
82 except:
83 toplevelname = None
84
85 if toplevelname == "None":
86 toplevelname = self.__mode
87 rootname = self.__mode+"s"
88 if toplevelname != self.__mode:
89 raise AttributeError
90
91
92
93 doc = DOM.Document()
94 root = DOM.Element(rootname)
95
96 for old_top in olddata:
97 self.__newFromOldNode(old_top, root)
98
99
100 for index in dict.keys():
101 newtop = DOM.Element(toplevelname)
102 self.__newNode(dict[index], newtop)
103 root.appendChild(newtop)
104
105
106 doc.appendChild(root)
107 fobj = open(self.__source, "w")
108 print >> fobj, doc.toprettyxml()
109 fobj.close()
110
112 """createNewXML(path, string)
113 - creates a new XMl file with the given path an adds the root instance named by string
114 """
115
116 doc = DOM.Document()
117
118 root = DOM.Element(string)
119 doc.appendChild(root)
120
121 fobj = open(path, "w")
122 print >> fobj, doc.toprettyxml()
123 fobj.close()
124
126 """getRootName()
127 - return the name of the root instance in the XML file"""
128 return str(self.__tree.firstChild.tagName)
129
130 - def getCharacteristic(self, data, algorithm, bench, cost_criteria, characteristics):
131 """getCharacteristic(data, algorithm, bench, cost_criteria, chararcteristic)
132 - should be used with mean_values XML only !! --> see GUI for information
133 parameter:
134 - data : string
135 - algorithm : string
136 - bench : string
137 - cost_criteria : list-of-strings
138 - characteristics : list-of strings
139 - return:
140 dict with structure:
141 {
142 criteria 1 : { char1 : value , char2 : value},
143 criteria 2 : { char1 : value, char2 : value}
144 }
145 or: {} if not found
146 """
147
148 root = self.__tree.firstChild
149
150 items = root.getElementsByTagName("datafile")
151
152 new_items = items[:]
153
154 tag_list = ["datastructure", "algorithm", "benchmark"]
155 value_list = [data, algorithm, bench]
156
157
158
159
160 for i in range(0,len(tag_list), 1):
161 items = new_items[:]
162 new_items = []
163 for item in items:
164 list = item.getElementsByTagName(tag_list[i])
165 for node in list:
166 child = node.firstChild
167 text = str(child.data.strip())
168 if text == value_list[i]:
169 new_items.append(item)
170
171
172
173 items = new_items[:]
174 chars = {}
175 for string in cost_criteria:
176 for item in items:
177 list = item.getElementsByTagName(string)
178 for criteria in list:
179 chars.update({string: {}})
180 for char in characteristics:
181 tag = criteria.getElementsByTagName(char)[0]
182 text = tag.firstChild.data.strip()
183 chars[string].update({char:text})
184 return chars
185
187 """findTopLevelItemNamse(self, node)
188 - finds the element and returns its tag name
189 - use for getting toplevelitem name in XML file
190 """
191 for child in node.childNodes:
192 if child.nodeType == DOM.Node.ELEMENT_NODE:
193 if child.tagName == "datafile" or child.tagName == "plot":
194 return child.tagName
195 else:
196 continue
197
199
200 for key in todo.keys():
201 if type(todo[key]) == dict:
202 newchild = DOM.Element(key)
203 self.__newNode(todo[key], newchild)
204
205 else:
206 newchild = DOM.Element(key)
207 newtext = DOM.Text()
208 newtext.data = todo[key]
209 newchild.appendChild(newtext)
210 parent.appendChild(newchild)
211
213 """newNode(node, parent)
214 - builds a new node from the given node including its child nodes and adds it as a child to parent node
215 recurrent function !
216 """
217 if node.nodeType == DOM.Node.ELEMENT_NODE:
218 newnode = DOM.Element(node.tagName)
219 if node.hasChildNodes:
220 for child in node.childNodes:
221 self.__newFromOldNode(child, newnode)
222 parent.appendChild(newnode)
223
224 if node.nodeType == DOM.Node.TEXT_NODE and node.nextSibling == None and node.previousSibling == None:
225 newtext = DOM.Text()
226 newtext.data = node.data.strip()
227 parent.appendChild(newtext)
228
230 """getTag(node, parent)
231 - both parameter are node instances of the XML file
232 - parent is obviously the parent node from node
233 - this function calls itself until node is an text node with interesting content
234 - returns dictionary:
235 {parent.tagName : node.text}
236 """
237
238 if node.nodeType == DOM.Node.ELEMENT_NODE:
239 dict = {}
240 if node.hasChildNodes:
241
242
243 for child in node.childNodes:
244 newdict = self.__getTag(child, node)
245 if node.tagName not in newdict.keys():
246 try:
247 dict[node.tagName].update(newdict)
248 except KeyError:
249 dict[node.tagName] = {}
250 dict[node.tagName].update(newdict)
251 else:
252 dict = newdict
253 return dict
254
255 if node.nodeType == DOM.Node.TEXT_NODE and node.nextSibling == None and node.previousSibling == None:
256
257 key = str(parent.tagName)
258 text = node.data.strip()
259 text = str(text)
260 return {key: text}
261 else:
262 return {}
263