fix errors
[sfa.git] / geni / util / rspec.py
1 import sys
2 import pprint
3 import os
4 from xml.dom import minidom
5
6 class Rspec():
7
8     def __init__(self, xml = None, xsd = None):
9         self.xsd = xsd # schema
10         self.rootNode = None # root of the dom
11         self.dict = {} # dict of the rspec.
12         if xml: 
13             if type(xml) == file:
14                 self.parseFile(xml)
15             if type(xml) == str:
16                 self.parseString(xml)
17             self.dict = self.toDict() 
18   
19     def _getText(self, nodelist):
20         rc = ""
21         for node in nodelist:
22             if node.nodeType == node.TEXT_NODE:
23                 rc = rc + node.data
24         return rc
25   
26     # The rspec is comprised of 2 parts, and 1 reference:
27     # attributes/elements describe individual resources
28     # complexTypes are used to describe a set of attributes/elements
29     # complexTypes can include a reference to other complexTypes.
30   
31   
32     def _getName(self, node):
33         '''Gets name of node. If tag has no name, then return tag's localName'''
34         name = None
35         if not node.nodeName.startswith("#"):
36             if node.localName:
37                 name = node.localName
38             elif node.attributes.has_key("name"):
39                 name = node.attributes.get("name").value
40         return name     
41  
42  
43     # Attribute.  {name : nameofattribute, {items: values})
44     def _attributeDict(self, attributeDom):
45         '''Traverse single attribute node.  Create a dict {attributename : {name: value,}]}'''
46         node = {} # parsed dict
47         for attr in attributeDom.attributes.keys():
48             node[attr] = attributeDom.attributes.get(attr).value
49         return node
50   
51  
52     def toDict(self, nodeDom = None):
53         """
54         convert this rspec to a dict and return it.
55         """
56         node = {}
57         if not nodeDom:
58              nodeDom = self.rootNode
59   
60         elementName = nodeDom.nodeName
61         if elementName and not elementName.startswith("#"):
62             # attributes have tags and values.  get {tag: value}, else {type: value}
63             node[elementName] = self._attributeDict(nodeDom)
64             #node.update(self._attributeDict(nodeDom))
65             # resolve the child nodes.
66             if nodeDom.hasChildNodes():
67                 for child in nodeDom.childNodes:
68                     childName = self._getName(child)
69                     if not childName:
70                         continue
71                     if not node[elementName].has_key(childName):
72                         node[elementName][childName] = []       
73                         #node[childName] = []
74                     childdict = self.toDict(child)
75                     for value in childdict.values():
76                         node[elementName][childName].append(value)
77                     #node[childName].append(self.toDict(child))
78         return node
79
80   
81     def toxml(self):
82         """
83         convert this rspec to an xml string and return it.
84         """
85         return self.rootNode.toxml()
86
87   
88     def toprettyxml(self):
89         """
90         print this rspec in xml in a pretty format.
91         """
92         return self.rootNode.toprettyxml()
93
94   
95     def parseFile(self, filename):
96         """
97         read a local xml file and store it as a dom object.
98         """
99         dom = minidom.parse(filename)
100         self.rootNode = dom.childNodes[0]
101   
102   
103     def parseString(self, xml):
104         """
105         read an xml string and store it as a dom object.
106         """
107         xml = xml.replace('\n', '').replace('\t', '').strip()
108         dom = minidom.parseString(xml)
109         self.rootNode = dom.childNodes[0]
110
111  
112     def dict2dom(self, rdict, include_doc = False):
113         """
114         convert a dict object into a dom object.
115         """
116      
117         def elementNode(tagname, rd):
118             element = minidom.Element(tagname)   
119             for key in rd.keys():
120                 if isinstance(rd[key], StringTypes):
121                     element.setAttribute(key, rd[key])
122                 elif isinstance(rd[key], dict):
123                     child = elementNode(key, rd[key])
124                     element.appendChild(child)
125                 elif isinstance(rd[key], list):
126                     for item in rd[key]:
127                         child = elementNode(key, item)
128                         element.appendChild(child)
129             return element
130                      
131         node = elementNode(rdict.keys()[0], rdict.values()[0])
132         if include_doc:
133             rootNode = minidom.Document()
134             rootNode.appendChild(node)
135         else:
136             rootNode = node
137         return rootNode
138
139  
140     def parseDict(self, rdict, include_doc = True):
141         """
142         Convert a dictionary into a dom object and store it.
143         """
144         self.rootNode = self.dict2dom(rdict, include_doc)
145  
146  
147     def getDictsByTagName(self, tagname, dom = None):
148         """
149         Search the dom for all elements with the specified tagname
150         and return them as a list of dicts
151         """
152         if not dom:
153             dom = self.rootNode
154         dicts = []
155         doms = dom.getElementsByTagName(tagname)
156         dictlist = [self.toDict(d) for d in doms]
157         for item in dictlist:
158             for value in item.values():
159                 dicts.append(value)
160         return dicts
161
162     def getDictByTagNameValue(self, tagname, value, dom = None):
163         """
164         Search the dom for the first element with the specified tagname
165         and value and return it as a dict.
166         """
167         tempdict = {}
168         if not dom:
169             dom = self.rootNode
170         dicts = self.getDictsByTagName(tagname, dom)
171         
172         for rdict in dicts:
173             if rdict.has_key('name') and rdict['name'] in [value]:
174                 return rdict
175               
176         return tempdict
177 # vim:ts=4:expandtab