X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Futil%2Frspec.py;h=ffc816c3fdb8d0b5c42c5ec53ff283652b6b85a8;hb=bfcea75fd4f7d91b186f4f0e479db0e6f0a231ae;hp=2b1fe856fceffc2b020384a905cff43a9f7f73aa;hpb=7167178c2b6b108ec5d47f05e7c3b397779b5fa8;p=sfa.git diff --git a/sfa/util/rspec.py b/sfa/util/rspec.py index 2b1fe856..ffc816c3 100644 --- a/sfa/util/rspec.py +++ b/sfa/util/rspec.py @@ -1,15 +1,15 @@ -### $Id$ -### $URL$ - -import pdb import sys import pprint import os +from StringIO import StringIO +from types import StringTypes, ListType import httplib from xml.dom import minidom -from types import StringTypes, ListType +from lxml import etree -class Rspec: +from sfa.util.sfalogging import sfa_logger + +class RSpec: def __init__(self, xml = None, xsd = None, NSURL = None): ''' @@ -28,10 +28,10 @@ class Rspec: self.dict = {} self.schemaDict = {} self.NSURL = NSURL - if xml: + if xml: if type(xml) == file: self.parseFile(xml) - if type(xml) == str: + if type(xml) in StringTypes: self.parseString(xml) self.dict = self.toDict() if xsd: @@ -92,6 +92,8 @@ class Rspec: if (nodeDom.hasChildNodes()): childdict={} + for attribute in nodeDom.attributes.keys(): + childdict = self.appendToDictOrCreate(childdict, attribute, nodeDom.getAttribute(attribute)) for child in nodeDom.childNodes[:-1]: if (child.nodeValue): siblingdict = self.appendToDictOrCreate(siblingdict, curNodeName, child.nodeValue) @@ -101,17 +103,16 @@ class Rspec: child = nodeDom.childNodes[-1] if (child.nodeValue): siblingdict = self.appendToDictOrCreate(siblingdict, curNodeName, child.nodeValue) + if (childdict): + siblingdict = self.appendToDictOrCreate(siblingdict, curNodeName, childdict) else: siblingdict = self.toGenDict(child, siblingdict, childdict, curNodeName) - - # Keep the attributes separate from text nodes - attrdict={} - for attribute in nodeDom.attributes.keys(): - attrdict = self.appendToDictOrCreate(attrdict, attribute, nodeDom.getAttribute(attribute)) - if (attrdict): - self.appendToDictOrCreate(siblingdict, curNodeName, attrdict) else: - self.appendToDictOrCreate(siblingdict, curNodeName, []) + childdict={} + for attribute in nodeDom.attributes.keys(): + childdict = self.appendToDictOrCreate(childdict, attribute, nodeDom.getAttribute(attribute)) + + self.appendToDictOrCreate(siblingdict, curNodeName, childdict) if (parentdict is not None): parentdict = self.appendToDictOrCreate(parentdict, parent, siblingdict) @@ -137,23 +138,25 @@ class Rspec: if nodeDom.hasChildNodes(): for child in nodeDom.childNodes: childName = self._getName(child) - # skip null children - if not childName: - continue - # initialize the possible array of children - if not node[elementName].has_key(childName): - node[elementName][childName] = [] - # if child node has text child nodes - # append the children to the array as strings - if child.hasChildNodes() and isinstance(child.childNodes[0], minidom.Text): - for nextchild in child.childNodes: + + # skip null children + if not childName: continue + + # initialize the possible array of children + if not node[elementName].has_key(childName): node[elementName][childName] = [] + + if isinstance(child, minidom.Text): + # add if data is not empty + if child.data.strip(): node[elementName][childName].append(nextchild.data) - # convert element child node to dict - else: + elif child.hasChildNodes() and isinstance(child.childNodes[0], minidom.Text): + for nextchild in child.childNodes: + node[elementName][childName].append(nextchild.data) + else: childdict = self.toDict(child) for value in childdict.values(): node[elementName][childName].append(value) - #node[childName].append(self.toDict(child)) + return node @@ -171,11 +174,19 @@ class Rspec: return self.rootNode.toprettyxml() + def __removeWhitespaceNodes(self, parent): + for child in list(parent.childNodes): + if child.nodeType == minidom.Node.TEXT_NODE and child.data.strip() == '': + parent.removeChild(child) + else: + self.__removeWhitespaceNodes(child) + def parseFile(self, filename): """ read a local xml file and store it as a dom object. """ dom = minidom.parse(filename) + self.__removeWhitespaceNodes(dom) self.rootNode = dom.childNodes[0] @@ -183,8 +194,8 @@ class Rspec: """ read an xml string and store it as a dom object. """ - xml = xml.replace('\n', '').replace('\t', '').strip() dom = minidom.parseString(xml) + self.__removeWhitespaceNodes(dom) self.rootNode = dom.childNodes[0] @@ -207,11 +218,13 @@ class Rspec: def _parseXSD(self, xsdURI): """ - Download XSD from URL, or if file, read local xsd file and set schemaDict + Download XSD from URL, or if file, read local xsd file and set + schemaDict. + + Since the schema definiton is a global namespace shared by and + agreed upon by others, this should probably be a URL. Check + for URL, download xsd, parse, or if local file, use that. """ - # Since the schema definiton is a global namespace shared by and agreed upon by - # others, this should probably be a URL. Check for URL, download xsd, parse, or - # if local file, use local file. schemaDom = None if xsdURI.startswith("http"): try: @@ -219,15 +232,14 @@ class Rspec: except Exception, e: # logging.debug("%s: web file not found" % xsdURI) # logging.debug("Using local file %s" % self.xsd") - print e - print "Can't find %s on the web. Continuing." % xsdURI + sfa_logger().log_exc("rspec.parseXSD: can't find %s on the web. Continuing." % xsdURI) if not schemaDom: if os.path.exists(xsdURI): # logging.debug("using local copy.") - print "Using local %s" % xsdURI + sfa_logger().debug("rspec.parseXSD: Using local %s" % xsdURI) schemaDom = minidom.parse(xsdURI) else: - raise Exception("Can't find xsd locally") + raise Exception("rspec.parseXSD: can't find xsd locally") self.schemaDict = self.toDict(schemaDom.childNodes[0]) @@ -274,7 +286,7 @@ class Rspec: """ Convert a dictionary into a dom object and store it. """ - self.rootNode = self.dict2dom(rdict, include_doc) + self.rootNode = self.dict2dom(rdict, include_doc).childNodes[0] def getDictsByTagName(self, tagname, dom = None): @@ -332,6 +344,28 @@ class Rspec: self.filter(tagname, attribute, blacklist, whitelist, child) + def merge(self, rspecs, tagname, dom=None): + """ + Merge this rspec with the requested rspec based on the specified + starting tag name. The start tag (and all of its children) will be merged + """ + tempdict = {} + if not dom: + dom = self.rootNode + + whitelist = [] + blacklist = [] + + if dom.localName in [tagname] and dom.attributes.has_key(attribute): + if whitelist and dom.attributes.get(attribute).value not in whitelist: + dom.parentNode.removeChild(dom) + if blacklist and dom.attributes.get(attribute).value in blacklist: + dom.parentNode.removeChild(dom) + + if dom.hasChildNodes(): + for child in dom.childNodes: + self.filter(tagname, attribute, blacklist, whitelist, child) + def validateDicts(self): types = { 'EInt' : int, @@ -363,7 +397,7 @@ class Rspec: -class RecordSpec(Rspec): +class RecordSpec(RSpec): root_tag = 'record' def parseDict(self, rdict, include_doc = False): @@ -376,7 +410,7 @@ class RecordSpec(Rspec): record_dict = rdict if not len(rdict.keys()) == 1: record_dict = {self.root_tag : rdict} - return Rspec.dict2dom(self, record_dict, include_doc) + return RSpec.dict2dom(self, record_dict, include_doc) # vim:ts=4:expandtab