source: TI02-CSML/branches/CSML2/csParser.py @ 1833

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/branches/CSML2/csParser.py@1833
Revision 1833, 14.1 KB checked in by domlowe, 13 years ago (diff)

fixed error with featureMembers

Line 
1import cElementTree as ET
2import elementtree.ElementTree as etree
3import parser_extra
4import sys
5'''CSML v2 Parser ''' 
6
7#this map needs updating for V2
8etree._namespace_map.update({'http://www.opengis.net/om': 'om', 'http://www.opengis.net/swe': 'swe',  'http://www.opengis.net/gml': 'gml','http://ndg.nerc.ac.uk/csml' : 'csml', 'http://www.w3.org/1999/xlink':'xlink'})
9
10       
11
12nsCSML = 'http://ndg.nerc.ac.uk/csml'
13nsGML = 'http://www.opengis.net/gml'
14nsOM = 'http://www.opengis.net/om'
15nsXLINK = 'http://www.w3.org/1999/xlink'
16nsXML = 'http://ndg.nerc.ac.uk/csml'
17nsMOLES='http://ndg.nerc.ac.uk/moles'
18nsSWE='http://www.opengis.net/swe'
19   
20def myQName(uri,tag):
21    return "{"+uri+"}"+tag
22
23def CSML(tag):
24    return myQName(nsCSML,tag)
25
26def GML(tag):
27    return myQName(nsGML,tag)
28
29def SWE(tag):
30    return myQName(nsSWE,tag)
31
32def XLINK(tag):
33    return myQName(nsXLINK,tag)
34
35def addchildren(obj, dict):
36    ''' merges (adds) dictionary to existing self.CHILDREN dictionary '''
37    dict1 = dict
38    if hasattr(obj, 'CHILDREN'):
39      dict2=obj.CHILDREN
40    else:
41      dict2={}
42    dict3={}
43    for item in dict1:
44        dict3[item] =dict1[item]
45    for item in dict2:
46        dict3[item] =dict2[item]
47    obj.CHILDREN=dict3
48   
49
50def addatts(obj, atts):
51  ''' merges self.ATTRIBUTES'''
52  if hasattr(obj, 'ATTRIBUTES'):
53    for att in atts:
54        obj.ATTRIBUTES.append(att)
55  else:
56    obj.ATTRIBUTES=atts
57
58class csElement(object):
59    ''' main csElement class - all other elements inherit from this baseclass 
60    all the from/to XML conversion is done by this class'''
61   
62    def __init__(self, **kwargs):
63        if not hasattr(self, 'ATTRIBUTES'):
64            self.ATTRIBUTES=[]
65           
66       
67    def __removeURI(self, qname):
68        try:
69            attname = qname.split('}')[1]
70        except IndexError:
71            attname = qname
72        return attname
73       
74    def _getSubstitutionType(self,tag):
75        print 'splitting tag'
76        return tag.split('}')[1]
77       
78   
79    def _getReverseSubsType(self, typename):
80        return typename
81   
82    def toXML(self, csmlfrag):
83        #process self and convert to XML
84        if hasattr(self, 'CONTENT'):
85            if self.CONTENT is not None: csmlfrag.text=self.CONTENT
86        if hasattr(self, 'ATTRIBUTES'):
87            for item in self.__dict__:
88                if item in self.ATTRIBUTES:
89                    csmlfrag.set(item, self.__dict__[item])
90            for item in self.__dict__:
91                if GML(item) in self.ATTRIBUTES:
92                    csmlfrag.set(GML(item), self.__dict__[item])       
93    # self.CHILDREN (recursive - calls the toXML method of children
94        for att in self.__dict__:
95            if att not in ['ATTRIBUTES', 'CHILDREN', 'CONTENT']:
96                for child in self.CHILDREN:
97                    if child == att:
98                        parserobjects=[]
99                        if type(self.__dict__[att]) is list:
100                            for a in self.__dict__[att]:
101                                parserobjects.append(a)
102                        else:
103                            parserobjects.append(self.__dict__[att])
104                        parentfrag=None
105                        if len(self.CHILDREN[child])==3:
106                                ename2=self.CHILDREN[child][2]
107                                parentfrag=ET.Element(ename2)
108                        for po in parserobjects:
109                            if type(self.CHILDREN[child][0]) is not list:
110                                ename=self.CHILDREN[child][0]
111                            else:
112                                ename = self._getReverseSubsType(type(po).__name__)
113                            if len(self.CHILDREN[child])==3:
114                                frag=ET.Element(ename)
115                                po.toXML(frag)
116                                parentfrag.append(frag)
117                            else:
118                                frag=ET.Element(ename)
119                                po.toXML(frag)
120                                csmlfrag.append(frag)
121                        if parentfrag is not None:
122                            csmlfrag.append(parentfrag)
123        return csmlfrag
124       
125    def fromXML(self,csmlfrag):
126        # deal with attributes, e.g. gml id's
127        if csmlfrag.text is not None:
128                self.CONTENT = csmlfrag.text
129        for item in csmlfrag.items():
130            if item[0] in self.ATTRIBUTES:
131                setattr(self, item[0], item[1])
132        # self.CHILDREN (recursive - calls the fromXML method of children
133        for frag in csmlfrag[:]:
134            #for each child element
135            #iterate through expected CHILDREN
136            for child in self.CHILDREN:
137                #get element name
138                if len(self.CHILDREN[child])==3:
139                    ename = self.CHILDREN[child][2]
140                    ename2 = self.CHILDREN[child][0]
141                   
142                else:
143                    ename = self.CHILDREN[child][0] 
144                    ename2=None
145                #if there are options, then find the name that matches the frag
146                if ename2 is not None:
147                    if frag[:] != []:
148                        for subfrag in frag[:]:
149                            etype=None
150                            if type(ename2) is list:
151                                if subfrag.tag in ename2:
152                                    etype=self._getSubstitutionType(subfrag.tag)
153                            if subfrag.tag==ename2:
154                                etype=self.CHILDREN[child][1]
155                            if etype:
156                                childobj=eval(etype)()
157                                if len(self.CHILDREN[child])==3:
158                                    if frag[:] != []:
159                                        childobj.fromXML(subfrag)
160                                else:
161                                    childobj.fromXML(frag)
162                                #set this object to be an attribute of the 'parent' (self) object
163                                if hasattr(self, child):
164                                    if type(self.__dict__[child]) is not list:
165                                        tmp=self.__dict__[child]
166                                        setattr(self, child, [tmp]) #convert to list
167                                    self.__dict__[child].append(childobj)
168                                else:
169                                    setattr(self, child, childobj)
170                else:
171                    etype=None
172                    if type(ename) is list:
173                        if frag.tag in ename:
174                            etype=self._getSubstitutionType(frag.tag)
175                    elif frag.tag==ename:
176                        etype=self.CHILDREN[child][1]
177                    if etype:
178                        childobj=eval(etype)()
179                        if len(self.CHILDREN[child])==3:
180                            if frag[:] != []:
181                                childobj.fromXML(frag[0])
182                        else:
183                            childobj.fromXML(frag)
184                        #set this object to be an attribute of the 'parent' (self) object
185                        if hasattr(self, child):
186                            if type(self.__dict__[child]) is not list:
187                                tmp=self.__dict__[child]
188                                setattr(self, child, [tmp]) #convert to list
189                            self.__dict__[child].append(childobj)
190                        else:
191                            setattr(self, child, childobj)
192
193               
194class csString(csElement):
195    pass
196
197class AbstractGML(csElement):
198    def __init__(self, **kwargs):
199        a=[GML('id'), GML('description'), GML('name'), GML('MetaDataProperty')]
200        addatts(self,a)
201
202class AssociationAttributeGroup(csElement):
203    def __init__(self, **kwargs):
204        a =[XLINK('href'),XLINK('role'), XLINK('arcrole'),XLINK('title'), XLINK('show'), XLINK('actuate')] 
205        addatts(self,a)
206
207class AbstractFeature(AbstractGML,csElement):
208    def __init__(self, **kwargs):
209        AbstractGML.__init__(self,**kwargs)
210        children={'boundedBy':[GML('boundedBy'), 'Envelope']}
211        addchildren(self,children)
212
213class AbstractFeatureCollection(AbstractFeature,csElement):
214    def __init__(self, **kwargs):
215        AbstractFeature.__init__(self,**kwargs)
216
217class domainSet(AbstractGML,AssociationAttributeGroup,csElement):
218    def __init__(self, **kwargs):
219        AbstractGML.__init__(self,**kwargs)
220        addchildren(self,{})
221
222class ReferenceableGridDomain(domainSet):
223    def __init__(self, **kwargs):
224        domainSet.__init__(self,**kwargs)
225        addchildren(self,{})
226
227class AbstractCoverage(AbstractFeature, csElement):
228    def __init__(self, **kwargs):
229        AbstractFeature.__init__(self,**kwargs)
230
231class AbstractDiscreteCoverage(AbstractCoverage, csElement):
232    def __init__(self, **kwargs):
233        AbstractCoverage.__init__(self,**kwargs)
234        addchildren(self,{})
235
236class ReferenceableGrid(AbstractGML, AssociationAttributeGroup, csElement):
237    def __init__(self, **kwargs):
238        AbstractGML.__init__(self,**kwargs)
239        AssociationAttributeGroup.__init__(self,**kwargs)
240        addchildren(self,{})
241        a=['dimension']
242        addatts(self,a)   
243        if hasattr(self, 'ATTRIBUTES'):
244            for att in a:
245                self.ATTRIBUTES.append(att)
246        else:
247            self.ATTRIBUTES=a
248
249class ReferenceableGridCoverage(AbstractDiscreteCoverage, csElement):
250    def __init__(self, **kwargs):
251        AbstractDiscreteCoverage.__init__(self,**kwargs)
252        children={'referenceableGridDomain':[CSML('ReferenceableGrid'),'ReferenceableGrid' ,CSML('referenceableGridDomain') ]}
253        addchildren(self,children)
254
255class Definition(AbstractGML):
256    def __init__(self, **kwargs):
257        AbstractGML.__init__(self,**kwargs)
258        addchildren(self,{})
259
260class Phenomenon(Definition,AssociationAttributeGroup):
261    def __init__(self, **kwargs):
262        Definition.__init__(self,**kwargs)
263        AssociationAttributeGroup.__init__(self,**kwargs)
264        children = {'':[CSML(''), '']}   
265        addchildren(self,children)
266
267class GridFeature(AbstractFeature, csElement):
268    def __init__(self, **kwargs):
269        AbstractFeature.__init__(self,**kwargs)
270        #children={'time':[CSML('time'), 'csString'], 'value':[CSML('value'), 'ReferenceableGridCoverage', CSML('ReferenceableGridCoverage')], 'parameter':[CSML('parameter'), 'Phenomenon']}
271        children={'time':[CSML('time'), 'csString'], 'value':[CSML('ReferenceableGridCoverage'), 'ReferenceableGridCoverage', CSML('value')], 'parameter':[CSML('parameter'), 'Phenomenon']}
272        addchildren(self,children)
273
274class ArrayDescriptor(AbstractGML, csElement):
275    def __init__(self,**kwargs):
276        AbstractGML.__init__(self,**kwargs)
277        children={'arraySize':[CSML('arraySize'), 'csString'], 'uom':[CSML('uom'),'csString'], 'numericType':[CSML('numericType'),'csString'], 'regExpTransform':[CSML('regExpTransform'),'csString'], 'numericTransform':[CSML('numericTransform'),'csString']}
278        addchildren(self,children)
279       
280class FileExtract(ArrayDescriptor, csElement):
281    def __init__(self,**kwargs):
282        ArrayDescriptor.__init__(self,**kwargs)
283        children= {'fileName':[CSML('fileName'), 'csString']}
284        addchildren(self,children)
285
286class NetCDFExtract(FileExtract, csElement):
287    def __init__(self,**kwargs):
288        FileExtract.__init__(self, **kwargs)
289        children={'variableName':[CSML('variableName'), 'csString']}
290        addchildren(self,children)
291       
292class NASAAmesExtract(FileExtract, csElement):
293    def __init__(self,**kwargs):
294        FileExtract.__init__(self, **kwargs)
295        children={'variableName':[CSML('variableName'), 'csString'], 'index':[CSML('index'),'csString']}
296        addchildren(self,children)
297
298class FeatureCollection(AbstractFeatureCollection,csElement):
299    def __init__(self,**kwargs):
300        AbstractFeatureCollection.__init__(self,**kwargs)
301        children={'members':[[CSML('GridFeature'),CSML('PointFeature')], 'AbstractFeature', GML('featureMembers')]}
302        addchildren(self,children)
303    def _getSubstitutionType(self,tag):
304        if tag==CSML('GridFeature'):
305            return 'GridFeature'
306        elif tag==CSML('PointFeature'):
307            return 'PointFeature'
308        else: return 'AbstractFeature'
309    def _getReverseSubsType(self, typename):
310        if typename== 'GridFeature':
311            return CSML('GridFeature')
312        elif typename == 'PointFeature':
313            return CSML('PointFeature')
314        else: return CSML('AbstractFeature')
315
316       
317class Dataset(AbstractGML, csElement):   
318    ''' Dataset class, needed as root of tree'''
319    def __init__(self, **kwargs):
320        AbstractGML.__init__(self,**kwargs)
321        #children = {'ncExtract':[CSML('NetCDFExtract'), 'NetCDFExtract'], 'featureCollection':[CSML('featureCollection') ,'FeatureCollection']}
322        children = {'featureCollection':[GML('FeatureCollection') ,'FeatureCollection'],'fileExtracts':[[CSML('NetCDFExtract'),CSML('NASAAmesExtract')], 'ArrayDescriptor']}
323        addchildren(self,children)
324    def toXML(self):
325        csmlfrag=ET.Element(CSML('Dataset'))
326        csElement.toXML(self, csmlfrag)
327        return csmlfrag
328    def _getSubstitutionType(self,tag):
329        if tag==CSML('NetCDFExtract'):
330            return 'NetCDFExtract'
331        elif tag==CSML('NASAAmesExtract'):
332            return 'NASAAmesExtract'
333        else: return 'ArrayDescriptor'
334    def _getReverseSubsType(self, typename):
335        if typename== 'NetCDFExtract':
336            return CSML('NetCDFExtract')
337        elif typename == 'NASAAmesExtract':
338            return CSML('NASAAmesExtract')
339        else: return CSML('ArrayDescriptor')
340       
341        return typename
342
343def main():
344    '''round trip for testing purposes:'''
345    print '\n'
346    tree=ET.ElementTree(file='test.xml')
347    ds=Dataset()
348    ds.fromXML(tree.getroot())
349    csmltree=ds.toXML()
350    #print csmltree
351   
352    csmlout=parser_extra.PrettyPrint(csmltree)
353    csmlout=parser_extra.removeInlineNS(csmlout)
354    print '\n %s'% csmlout
355    #for member in ds.featureCollection.members:
356      #print dir(member.value)
357       
358
359if __name__=='__main__':
360    main()
Note: See TracBrowser for help on using the repository browser.