parseDict now converts a dict do a dom object
[sfa.git] / util / rspec.py
1 import sys
2 import pprint
3 import os
4 from xml.dom import minidom
5 from types import StringTypes
6
7 class Rspec():
8
9     def __init__(self, xml = None, xsd = None):
10         self.xsd = xsd
11         self.rootNode = None
12         if xml:
13             self.parse_string(xml)
14             
15
16     def _getText(self, nodelist):
17         rc = ""
18         for node in nodelist:
19             if node.nodeType == node.TEXT_NODE:
20                 rc = rc + node.data
21         return rc
22
23     # The rspec is comprised of 2 parts, and 1 reference:
24     # attributes/elements describe individual resources
25     # complexTypes are used to describe a set of attributes/elements
26     # complexTypes can include a reference to other complexTypes.
27
28
29     def _getName(self, node):
30         '''Gets name of node. If tag has no name, then return tag's localName'''
31         name = None
32         if not node.nodeName.startswith("#"):
33             if node.localName:
34                 name = node.localName
35             elif node.attributes.has_key("name"):
36                 name = node.attributes.get("name").value
37
38         return name     
39
40     # Attribute.  {name : nameofattribute, {items: values})
41     def _attributeDict(self, attributeDom):
42         '''Traverse single attribute node.  Create a dict {attributename : {name: value,}]}'''
43         node = {} # parsed dict
44         for attr in attributeDom.attributes.keys():
45             node[attr] = attributeDom.attributes.get(attr).value
46         return node
47
48
49     def toDict(self, nodeDom = None):
50         """
51         convert this rspec to a dict and return it.
52         """
53         node = {}
54         if not nodeDom:
55             nodeDom = self.rootNode
56
57         elementName = nodeDom.nodeName
58         if elementName and not elementName.startswith("#"):
59             # attributes have tags and values.  get {tag: value}, else {type: value} 
60             node[elementName] = self._attributeDict(nodeDom)
61             #node.update(self._attributeDict(nodeDom))
62             # resolve the child nodes.
63             if nodeDom.hasChildNodes():
64                 for child in nodeDom.childNodes:
65                     childName = self._getName(child)
66                     if not childName:
67                         continue
68                     if not node[elementName].has_key(childName):
69                         node[elementName][childName] = []       
70                         #node[childName] = []
71                     childdict = self.toDict(child)
72                     for value in childdict.values():
73                         node[elementName][childName].append(value)
74                     #node[childName].append(self.toDict(child))
75         return node
76
77     def toxml(self):
78         """
79         convert this rspec to an xml string and return it.
80         """
81         return self.rootNode.toxml()
82
83     def toprettyxml(self):
84         """
85         print this rspec in xml in a pretty format.
86         """
87         return self.rootNode.toprettyxml()
88
89     def parseFile(self, filename):
90         """
91         read a local xml file and store it as a dom object.
92         """
93         dom = minidom.parse(filename)
94         self.rootNode = dom.childNodes[0]
95
96
97     def parseString(self, xml):
98         """
99         read an xml string and store it as a dom object.
100         """
101         xml = xml.replace('\n', '').replace('\t', '').strip()
102         dom = minidom.parseString(xml)
103         self.rootNode = dom.childNodes[0]
104
105     def parseDict(self, rdict):
106         """
107         convert a dict object into a dom object.
108         """
109         doc = minidom.Document()
110         
111         def elementNode(tagname, rd):
112             element = minidom.Element(tagname)   
113             for key in rd.keys():
114                 if isinstance(rd[key], StringTypes):
115                     element.setAttribute(key, rd[key])
116  
117                 elif isinstance(rd[key], dict): 
118                     child = elementNode(key, rd[key])
119                     element.appendChild(child)
120                 
121                 elif isinstance(rd[key], list):
122                     for item in rd[key]:
123                         child = elementNode(key, item)
124                         element.appendChild(child)
125
126             return element
127                         
128         node = elementNode(rdict.keys()[0], rdict.values()[0]) 
129         doc.appendChild(node)
130         self.rootNode = doc
131