Parses xsd into dict. Probably can be optimized.
authorFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Tue, 20 Jan 2009 21:56:38 +0000 (21:56 +0000)
committerFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Tue, 20 Jan 2009 21:56:38 +0000 (21:56 +0000)
rspec/rspecvalidate.py

index 17f208f..e09a21b 100644 (file)
 import sys
 import pprint
 from xml.dom import minidom
+from logging import Logger
 
+logger = Logger
+
+# The rspec is comprised of 2 parts, and 1 reference:
+# attributes/elements describe individual resources
+# complexTypes are used to describe a set of attributes/elements
+# complexTypes can include a reference to other complexTypes.
 
 def getText(nodelist):
     rc = ""
@@ -24,42 +31,69 @@ def getText(nodelist):
             rc = rc + node.data
     return rc
 
-# complexType: a supernode comprised of element nodes below it.
-def traverseComplexType(cmpTypeNode):
-    _elements = {}
-    if cmpTypeNode.hasChildNodes():
-        for n in cmpTypeNode.getElementsByTagName("xsd:attribute"):
-            _elements[n.getAttribute("name")] = {'type': n.getAttribute("type")}
+def getName(node):
+    '''Gets name of node.  Raises NameError exception if no name'''
+    if node.attributes.has_key("name"):
+        name = node.attributes.get("name").value
+    else: raise Exception("Can't find 'name'")
+    return name 
 
+# complexType: a supernode comprised of attribute and/or element nodes below it.
+def complexTypeDict(cmpTypeDom):
+    '''Traverse complex node.  Create a dict {name : [{attributename : {name: value,}, sequence]}'''
+    children = [] # array of dicts.  1 for each element/attribute.
+    if cmpTypeDom.hasChildNodes():
+        for child in cmpTypeDom.childNodes:
+            # attributes have tags and values.  get {tag: value}
+            if child.localName in ("attribute", "element"): children.append(attributeDict(child))
+            # sequence is a list of elements.  append dict to list
+            elif child.localName == "sequence": children.append(sequenceList(child))
+            elif child.localName == "simpleType":  pass #unsure what this type is used for.
+            else: Exception("Unknown type: %s" % child.localName)
+    node = { getName(cmpTypeDom) : children}
+    return node
 
-# Element.  {name, value, default}
-def Element(elementDom):
-    node = {} #parsed dict
-    for attr in elementDom.attributes.keys():
-        node[attr] = elementDom.attributes.get(attr).value
-    # set the name to the name of the element.  otherwise, node name.
-    if elementDom.attributes.has_key("name"): 
-        element = {(elementDom.localName, elementDom.attributes.get("name").value) : node}
-    else:
-        element = {elementDom.localName: node}
-    # print repr(element)
-    # print
-    return element
+# Attribute.  {name : nameofattribute, {items: values})
+def attributeDict(attributeDom):
+    '''Traverse single attribute node.  Create a dict {attributename : {name: value,}]}'''
+    node = {} # parsed dict
+    for attr in attributeDom.attributes.keys():
+        node[attr] = attributeDom.attributes.get(attr).value
+    attribute = {getName(attributeDom) : node}
+    return attribute
 
-# Sequence is a list of dicts.  Each dict is an element type with Type fields
-def Sequence(sequenceNode):
-    pass
+def sequenceList(sequenceDom):
+    '''Return list of elements/attributes in sequence list'''
+    sequence = []
+    if sequenceDom.localName == "sequence": 
+        # for sanity
+        if sequenceDom.hasChildNodes:
+            for seqitm in sequenceDom.childNodes:
+                if seqitm.localName in ("element", "attribute"): 
+                    sequence.append(attributeDict(seqitm))
+                else: print "Idunno what %s is" % seqitm.localName
+        else: raise NameError
+    return sequence 
 
-def buildDict(document, docdict = {}):
+def schemaDict(document):
+    schema = {}
+    '''Parse the given schema and produce a dict of types'''
     if document.hasChildNodes():
-        for i in document.childNodes: 
-            if i.attributes: docdict.update({ i.localName: buildDict(i, docdict)})
-    if document.attributes: docdict.update(Element(document))
-    return docdict
+        for i in document.childNodes:
+            if i.localName in ('element', 'attribute'): 
+                schema.update(attributeDict(i))
+            elif i.localName == "complexType": 
+                schema.update(complexTypeDict(i))                
+            else: print "Idunno what %s is" % i.localName
+    return schema
 
 def main(fname):
     pp = pprint.PrettyPrinter(indent=4)
-    pp.pprint(buildDict(minidom.parse(fname)))
+    dom = minidom.parse(fname)
+    print "Testing Complex Type:"
+    pp.pprint(complexTypeDict(dom.childNodes[0].childNodes[15]))
+    print "Testing Whole doc:"
+    pp.pprint(schemaDict(dom.childNodes[0]))
 
 if __name__ == '__main__':  
     main(fname="planetlab.xsd")