5 from xml.dom import minidom
6 from types import StringTypes, ListType
10 def __init__(self, xml = None, xsd = None, NSURL = None):
12 Class to manipulate RSpecs. Reads and parses rspec xml into python dicts
13 and reads python dicts and writes rspec xml
15 self.xsd = # Schema. Can be local or remote file.
16 self.NSURL = # If schema is remote, Name Space URL to query (full path minus filename)
17 self.rootNode = # root of the DOM
18 self.dict = # dict of the RSpec.
19 self.schemaDict = {} # dict of the Schema
32 self.dict = self.toDict()
34 self._parseXSD(self.NSURL + self.xsd)
37 def _getText(self, nodelist):
40 if node.nodeType == node.TEXT_NODE:
44 # The rspec is comprised of 2 parts, and 1 reference:
45 # attributes/elements describe individual resources
46 # complexTypes are used to describe a set of attributes/elements
47 # complexTypes can include a reference to other complexTypes.
50 def _getName(self, node):
51 '''Gets name of node. If tag has no name, then return tag's localName'''
53 if not node.nodeName.startswith("#"):
56 elif node.attributes.has_key("name"):
57 name = node.attributes.get("name").value
61 # Attribute. {name : nameofattribute, {items: values})
62 def _attributeDict(self, attributeDom):
63 '''Traverse single attribute node. Create a dict {attributename : {name: value,}]}'''
64 node = {} # parsed dict
65 for attr in attributeDom.attributes.keys():
66 node[attr] = attributeDom.attributes.get(attr).value
70 def toDict(self, nodeDom = None):
72 convert this rspec to a dict and return it.
76 nodeDom = self.rootNode
78 elementName = nodeDom.nodeName
79 if elementName and not elementName.startswith("#"):
80 # attributes have tags and values. get {tag: value}, else {type: value}
81 node[elementName] = self._attributeDict(nodeDom)
82 #node.update(self._attributeDict(nodeDom))
83 # resolve the child nodes.
84 if nodeDom.hasChildNodes():
85 for child in nodeDom.childNodes:
86 childName = self._getName(child)
89 if not node[elementName].has_key(childName):
90 node[elementName][childName] = []
92 childdict = self.toDict(child)
93 for value in childdict.values():
94 node[elementName][childName].append(value)
95 #node[childName].append(self.toDict(child))
101 convert this rspec to an xml string and return it.
103 return self.rootNode.toxml()
106 def toprettyxml(self):
108 print this rspec in xml in a pretty format.
110 return self.rootNode.toprettyxml()
113 def parseFile(self, filename):
115 read a local xml file and store it as a dom object.
117 dom = minidom.parse(filename)
118 self.rootNode = dom.childNodes[0]
121 def parseString(self, xml):
123 read an xml string and store it as a dom object.
125 xml = xml.replace('\n', '').replace('\t', '').strip()
126 dom = minidom.parseString(xml)
127 self.rootNode = dom.childNodes[0]
130 def _httpGetXSD(self, xsdURI):
131 # split the URI into relevant parts
132 host = xsdURI.split("/")[2]
133 if xsdURI.startswith("https"):
134 conn = httplib.HTTPSConnection(host,
135 httplib.HTTPSConnection.default_port)
136 elif xsdURI.startswith("http"):
137 conn = httplib.HTTPConnection(host,
138 httplib.HTTPConnection.default_port)
139 conn.request("GET", xsdURI)
140 # If we can't download the schema, raise an exception
141 r1 = conn.getresponse()
144 return r1.read().replace('\n', '').replace('\t', '').strip()
147 def _parseXSD(self, xsdURI):
149 Download XSD from URL, or if file, read local xsd file and set schemaDict
151 # Since the schema definiton is a global namespace shared by and agreed upon by
152 # others, this should probably be a URL. Check for URL, download xsd, parse, or
153 # if local file, use local file.
155 if xsdURI.startswith("http"):
157 schemaDom = minidom.parseString(self._httpGetXSD(xsdURI))
159 # logging.debug("%s: web file not found" % xsdURI)
160 # logging.debug("Using local file %s" % self.xsd")
162 print "Can't find %s on the web. Continuing." % xsdURI
164 if os.path.exists(xsdURI):
165 # logging.debug("using local copy.")
166 print "Using local %s" % xsdURI
167 schemaDom = minidom.parse(xsdURI)
169 raise Exception("Can't find xsd locally")
170 self.schemaDict = self.toDict(schemaDom.childNodes[0])
173 def dict2dom(self, rdict, include_doc = False):
175 convert a dict object into a dom object.
178 def elementNode(tagname, rd):
179 element = minidom.Element(tagname)
180 for key in rd.keys():
181 if isinstance(rd[key], StringTypes):
182 element.setAttribute(key, rd[key])
183 elif isinstance(rd[key], dict):
184 child = elementNode(key, rd[key])
185 element.appendChild(child)
186 elif isinstance(rd[key], list):
188 child = elementNode(key, item)
189 element.appendChild(child)
192 node = elementNode(rdict.keys()[0], rdict.values()[0])
194 rootNode = minidom.Document()
195 rootNode.appendChild(node)
201 def parseDict(self, rdict, include_doc = True):
203 Convert a dictionary into a dom object and store it.
205 self.rootNode = self.dict2dom(rdict, include_doc)
208 def getDictsByTagName(self, tagname, dom = None):
210 Search the dom for all elements with the specified tagname
211 and return them as a list of dicts
216 doms = dom.getElementsByTagName(tagname)
217 dictlist = [self.toDict(d) for d in doms]
218 for item in dictlist:
219 for value in item.values():
223 def getDictByTagNameValue(self, tagname, value, dom = None):
225 Search the dom for the first element with the specified tagname
226 and value and return it as a dict.
231 dicts = self.getDictsByTagName(tagname, dom)
234 if rdict.has_key('name') and rdict['name'] in [value]:
240 def filter(self, tagname, attribute, blacklist = [], whitelist = [], dom = None):
242 Removes all elements where:
243 1. tagname matches the element tag
244 2. attribute matches the element attribte
245 3. attribute value is in valuelist
252 if dom.localName in [tagname] and dom.attributes.has_key(attribute):
253 if whitelist and dom.attributes.get(attribute).value not in whitelist:
254 dom.parentNode.removeChild(dom)
255 if blacklist and dom.attributes.get(attribute).value in blacklist:
256 dom.parentNode.removeChild(dom)
258 if dom.hasChildNodes():
259 for child in dom.childNodes:
260 self.filter(tagname, attribute, blacklist, whitelist, child)