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

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

ReferenceableGrid and associated classes added

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   
20 
21               
22def myQName(uri,tag):
23    return "{"+uri+"}"+tag
24
25def CSML(tag):
26    return myQName(nsCSML,tag)
27
28def GML(tag):
29    return myQName(nsGML,tag)
30
31def SWE(tag):
32    return myQName(nsSWE,tag)
33
34def XLINK(tag):
35    return myQName(nsXLINK,tag)
36
37def addchildren(obj, dict):
38    ''' merges (adds) dictionary to existing self.CHILDREN dictionary '''
39    dict1 = dict
40    if hasattr(obj, 'CHILDREN'):
41      dict2=obj.CHILDREN
42    else:
43      dict2={}
44    dict3={}
45    for item in dict1:
46        dict3[item] =dict1[item]
47    for item in dict2:
48        dict3[item] =dict2[item]
49    obj.CHILDREN=dict3
50   
51
52def addatts(obj, atts):
53  ''' merges self.ATTRIBUTES'''
54  if hasattr(obj, 'ATTRIBUTES'):
55    for att in atts:
56        obj.ATTRIBUTES.append(att)
57  else:
58    obj.ATTRIBUTES=atts
59
60
61#Some variable definitions: these things are often repeated so store in variables.
62FILEFORMATS=[CSML('NetCDFExtract'),CSML('NASAAmesExtract'), CSML('GRIBExtract'),CSML('CDMLExtract'), CSML('RawFileExtract')]
63 
64
65class csElement(object):
66    ''' main csElement class - all other elements inherit from this baseclass 
67    all the from/to XML conversion is done by this class'''
68   
69    def __init__(self, **kwargs):
70        if not hasattr(self, 'ATTRIBUTES'):
71            self.ATTRIBUTES=[]
72           
73       
74    def __removeURI(self, qname):
75        try:
76            attname = qname.split('}')[1]
77        except IndexError:
78            attname = qname
79        return attname
80       
81    def _getSubstitutionType(self,tag):
82        print 'splitting tag'
83        return tag.split('}')[1]
84       
85   
86    def _getReverseSubsType(self, typename):
87        return typename
88   
89    def toXML(self, csmlfrag):
90        #process self and convert to XML
91        if hasattr(self, 'CONTENT'):
92            if self.CONTENT is not None: csmlfrag.text=self.CONTENT
93        if hasattr(self, 'ATTRIBUTES'):
94            for item in self.__dict__:
95                if item in self.ATTRIBUTES:
96                    csmlfrag.set(item, self.__dict__[item])
97            for item in self.__dict__:
98                if GML(item) in self.ATTRIBUTES:
99                    csmlfrag.set(GML(item), self.__dict__[item])       
100    # self.CHILDREN (recursive - calls the toXML method of children
101        for att in self.__dict__:
102            if att not in ['ATTRIBUTES', 'CHILDREN', 'CONTENT']:
103                for child in self.CHILDREN:
104                    if child == att:
105                        parserobjects=[]
106                        if type(self.__dict__[att]) is list:
107                            for a in self.__dict__[att]:
108                                parserobjects.append(a)
109                        else:
110                            parserobjects.append(self.__dict__[att])
111                        parentfrag=None
112                        if len(self.CHILDREN[child])>=3:
113                                ename2=self.CHILDREN[child][2]
114                                parentfrag=ET.Element(ename2)
115                        for po in parserobjects:
116                            if type(self.CHILDREN[child][0]) is not list:
117                                ename=self.CHILDREN[child][0]
118                            else:
119                                ename = self._getReverseSubsType(type(po).__name__)
120                            if len(self.CHILDREN[child])==3:
121                                frag=ET.Element(ename)
122                                po.toXML(frag)
123                                parentfrag.append(frag)
124                                appendLater=True
125                            elif len(self.CHILDREN[child])>=4:
126                                if self.CHILDREN[child][3]==1:
127                                    frag=ET.Element(ename)
128                                    po.toXML(frag)
129                                    parentfrag.append(frag)
130                                    csmlfrag.append(parentfrag)
131                                    parentfrag=ET.Element(parentfrag.tag)
132                                    appendLater=False
133                            else:
134                                frag=ET.Element(ename)
135                                po.toXML(frag)
136                                csmlfrag.append(frag)
137                                appendLater=True
138                        if appendLater==True and parentfrag != None:
139                            csmlfrag.append(parentfrag)
140        return csmlfrag
141       
142    def fromXML(self,csmlfrag):
143        # deal with attributes, e.g. gml id's
144        if csmlfrag.text is not None:
145                self.CONTENT = csmlfrag.text
146        for item in csmlfrag.items():
147            if item[0] in self.ATTRIBUTES:
148                setattr(self, item[0], item[1])
149        # self.CHILDREN (recursive - calls the fromXML method of children
150        for frag in csmlfrag[:]:
151            #for each child element
152            #iterate through expected CHILDREN
153            for child in self.CHILDREN:
154                #get element name
155                if len(self.CHILDREN[child])>=3:
156                    ename = self.CHILDREN[child][2]
157                    ename2 = self.CHILDREN[child][0]
158                   
159                else:
160                    ename = self.CHILDREN[child][0] 
161                    ename2=None
162                #if there are options, then find the name that matches the frag
163                if ename2 is not None:
164                    if frag[:] != []:
165                        for subfrag in frag[:]:
166                            etype=None
167                            if type(ename2) is list:
168                                if subfrag.tag in ename2:
169                                    etype=self._getSubstitutionType(subfrag.tag)
170                            if subfrag.tag==ename2:
171                                etype=self.CHILDREN[child][1]
172                            if etype:
173                                childobj=eval(etype)()
174                                if len(self.CHILDREN[child])>=3:
175                                    if frag[:] != []:
176                                        childobj.fromXML(subfrag)
177                                else:
178                                    childobj.fromXML(frag)
179                                #set this object to be an attribute of the 'parent' (self) object
180                                if hasattr(self, child):
181                                    if type(self.__dict__[child]) is not list:
182                                        tmp=self.__dict__[child]
183                                        setattr(self, child, [tmp]) #convert to list
184                                    self.__dict__[child].append(childobj)
185                                else:
186                                    setattr(self, child, childobj)
187                else:
188                    etype=None
189                    if type(ename) is list:
190                        if frag.tag in ename:
191                            etype=self._getSubstitutionType(frag.tag)
192                    elif frag.tag==ename:
193                        etype=self.CHILDREN[child][1]
194                    if etype:
195                        childobj=eval(etype)()
196                        if len(self.CHILDREN[child])>=3:
197                            if frag[:] != []:
198                                childobj.fromXML(frag[0])
199                        else:
200                            childobj.fromXML(frag)
201                        #set this object to be an attribute of the 'parent' (self) object
202                        if hasattr(self, child):
203                            if type(self.__dict__[child]) is not list:
204                                tmp=self.__dict__[child]
205                                setattr(self, child, [tmp]) #convert to list
206                            self.__dict__[child].append(childobj)
207                        else:
208                            setattr(self, child, childobj)
209
210               
211class csString(csElement):
212    pass
213
214class AbstractGML(csElement):
215    def __init__(self, **kwargs):
216        a=[GML('id'), GML('description'), GML('name'), GML('MetaDataProperty')]
217        addatts(self,a)
218
219class AssociationAttributeGroup(csElement):
220    def __init__(self, **kwargs):
221        a =[XLINK('href'),XLINK('role'), XLINK('arcrole'),XLINK('title'), XLINK('show'), XLINK('actuate')] 
222        addatts(self,a)
223
224class SRSReferenceGroup(csElement):
225    def __init__(self, **kwargs):
226        a =['srsName','srsDimension'] 
227        addatts(self,a)
228       
229class SRSInformationGroup(csElement):
230    def __init__(self, **kwargs):
231        a =['uomLabels','axisLabels'] 
232        addatts(self,a)
233
234class ArrayDescriptor(AbstractGML, csElement):
235    def __init__(self,**kwargs):
236        AbstractGML.__init__(self,**kwargs)
237        children={'arraySize':[CSML('arraySize'), 'csString'], 'uom':[CSML('uom'),'csString'], 'numericType':[CSML('numericType'),'csString'], 'regExpTransform':[CSML('regExpTransform'),'csString'], 'numericTransform':[CSML('numericTransform'),'csString']}
238        addchildren(self,children)
239
240class DirectPosition(AbstractGML, SRSReferenceGroup,SRSInformationGroup,csElement):
241    def __init__(self, **kwargs):
242        AbstractGML.__init__(self,**kwargs)
243
244
245class Envelope(AbstractGML,SRSReferenceGroup, csElement):
246    def __init__(self, **kwargs):
247        SRSReferenceGroup.__init__(self,**kwargs)
248        AbstractGML.__init__(self,**kwargs)
249        children={'lowerCorner':[GML('lowerCorner'), 'DirectPosition'],'upperCorner':[GML('upperCorner'), 'DirectPosition']}
250        addchildren(self,children)
251
252
253class AbstractFeature(AbstractGML,csElement):
254    def __init__(self, **kwargs):
255        AbstractGML.__init__(self,**kwargs)
256        children={'boundedBy':[GML('boundedBy'), 'Envelope']}
257        addchildren(self,children)
258
259class AbstractFeatureCollection(AbstractFeature,csElement):
260    def __init__(self, **kwargs):
261        AbstractFeature.__init__(self,**kwargs)
262
263class DomainSet(AbstractGML,AssociationAttributeGroup,csElement):
264    def __init__(self, **kwargs):
265        AbstractGML.__init__(self,**kwargs)
266        addchildren(self,{})
267
268class AggregatedArray(ArrayDescriptor,csElement):
269    def __init__(self, **kwargs):
270        ArrayDescriptor.__init__(self,**kwargs)
271        children={'aggType':[CSML('aggType'),'csString'], 'aggIndex':[CSML('aggIndex'),'csString'],'components':[FILEFORMATS, 'ArrayDescriptor',CSML('component')]}
272        addchildren(self,children)
273#'component':[CSML:('component'), 'ArrayDescriptor', CSML('component')],
274class MeasureOrNullList(AbstractGML,csElement):
275    def __init__(self, **kwargs):
276        AbstractGML.__init__(self,**kwargs)
277        children={}
278        addchildren(self,children)
279       
280class CompositeValue(AbstractGML,csElement):
281    def __init__(self, **kwargs):
282        AbstractGML.__init__(self,**kwargs)
283        children={'measures':[GML('measure'),'csString',GML('valueComponents')]}
284        addchildren(self,children)
285       
286class DataBlock(AbstractGML,csElement):
287    def __init__(self, **kwargs):
288        AbstractGML.__init__(self,**kwargs)
289        children={'doubleOrNullTupleList':[GML('doubleOrNullTupleList'),'csString'],'rangeParameters':[GML('CompositeValue'), 'CompositeValue', GML('rangeParameters')]}
290        addchildren(self,children)
291
292class RangeSet(AbstractGML,AssociationAttributeGroup,csElement):
293    def __init__(self, **kwargs):
294        AbstractGML.__init__(self,**kwargs)
295        children={'quantityList':[GML('QuantityList'), 'MeasureOrNullList'],        'dataBlock':[GML('DataBlock'),'DataBlock'],'arrayDescriptor':[FILEFORMATS, 'ArrayDescriptor'],  'aggregatedArray':[CSML('AggregatedArray'), 'AggregatedArray']}
296        addchildren(self,children)
297
298class PointDomain(DomainSet):
299    def __init__(self, **kwargs):
300        DomainSet.__init__(self,**kwargs)
301        children={'pointMember':[GML('pointMember'), 'csString']}
302        addchildren(self,children)
303
304class AbstractCoverage(AbstractFeature, csElement):
305    def __init__(self, **kwargs):
306        AbstractFeature.__init__(self,**kwargs)
307
308class AbstractDiscreteCoverage(AbstractCoverage, csElement):
309    def __init__(self, **kwargs):
310        AbstractCoverage.__init__(self,**kwargs)
311        addchildren(self,{})
312       
313       
314class SpatialOrTemporalPositionList(AbstractGML,csElement):
315    def __init__(self, **kwargs):
316        AbstractGML.__init__(self,**kwargs)
317        children={'coordinateList':[GML('coordinateList'),'csString'], 'timePositionList':[CSML('timePositionList'),'csString']}
318        addchildren(self,children)
319
320class GridOrdinateDescription(AbstractGML,csElement):
321    def __init__(self, **kwargs):
322        AbstractGML.__init__(self,**kwargs)
323        children={'coordAxisLabel':[GML('coordAxisLabel'), 'csString'], 'coordAxisValues':[GML('SpatialOrTemporalPositionList'),'SpatialOrTemporalPositionList',GML('coordAxisValues')], 'gridAxesSpanned':[GML('gridAxesSpanned'), 'csString'], 'sequenceRule':[GML('sequenceRule'),'SequenceRuleType']}
324        addchildren(self,children)
325
326class SequenceRuleType(csElement):
327    def __init__(self, **kwargs):
328        a=['axisOrder']
329        addatts(self,a)
330        children={}
331        addchildren(self,children)
332
333class GridPointDescription(AbstractGML,csElement):
334    def __init__(self, **kwargs):
335        AbstractGML.__init__(self,**kwargs)
336        children={'posList':[GML('posList'),'csString'],'sequenceRule':[GML('sequenceRule'),'SequenceRuleType']}
337        addchildren(self,children)
338
339
340class GridCoordinatesTable(AbstractGML,csElement):
341    def __init__(self,**kwargs):
342        '''the additional value '1' in the children dictionary is used to signify that the elements must be nested as:
343        <gml:ordinate>
344            <gml:GridOrdinateDescription>
345        </gml:ordinate>
346        <gml:ordinate>
347            <gml:GridOrdinateDescription>
348        </gml:ordinate>
349       
350        not as:
351        <gml:ordinate>
352            <gml:GridOrdinateDescription>
353            <gml:GridOrdinateDescription>
354        </gml:ordinate> '''
355        AbstractGML.__init__(self,**kwargs)
356        children={'gridOrdinates':[GML('GridOrdinateDescription'), 'GridOrdinateDescription',GML('gridOrdinate'),1], 'gridPoints':[GML('GridPointDescription'),'GridPointDescription',GML('gridPoints')]}
357        addchildren(self,children)
358       
359class ReferenceableGrid(AbstractGML, AssociationAttributeGroup, csElement):
360    def __init__(self, **kwargs):
361        AbstractGML.__init__(self,**kwargs)
362        AssociationAttributeGroup.__init__(self,**kwargs)
363        children={'coordTransformTable':[GML('GridCoordinatesTable'), 'GridCoordinatesTable', GML('coordTransformTable')]}
364        addchildren(self,children)
365        a=['dimension']
366        addatts(self,a)
367
368class ReferenceableGridCoverage(AbstractDiscreteCoverage, csElement):
369    def __init__(self, **kwargs):
370        AbstractDiscreteCoverage.__init__(self,**kwargs)
371        children={'referenceableGridDomain':[CSML('ReferenceableGrid'),'ReferenceableGrid' ,CSML('referenceableGridDomain') ]}
372        addchildren(self,children)
373       
374class PointCoverage(AbstractDiscreteCoverage, csElement):
375    def __init__(self, **kwargs):
376        AbstractDiscreteCoverage.__init__(self,**kwargs)
377        children={'pointDomain':[CSML('PointDomain'),'PointDomain' ,CSML('pointDomain') ], 'rangeSet':[GML('rangeSet'), 'RangeSet'],'coverageFunction':[GML('coverageFunction'),'csString']}
378        addchildren(self,children)
379
380class Definition(AbstractGML):
381    def __init__(self, **kwargs):
382        AbstractGML.__init__(self,**kwargs)
383        addchildren(self,{})
384
385class Phenomenon(Definition,AssociationAttributeGroup):
386    def __init__(self, **kwargs):
387        Definition.__init__(self,**kwargs)
388        AssociationAttributeGroup.__init__(self,**kwargs)
389        children = {'':[CSML(''), '']}   
390        addchildren(self,children)
391
392class PointFeature(AbstractFeature, csElement):
393    def __init__(self, **kwargs):
394        AbstractFeature.__init__(self,**kwargs)
395        children={'location':[CSML('location'), 'csString'],'time':[CSML('time'), 'csString'], 'value':[CSML('PointCoverage'), 'PointCoverage', CSML('value')], 'parameter':[CSML('parameter'), 'Phenomenon']}
396        addchildren(self,children)
397
398
399class GridFeature(AbstractFeature, csElement):
400    def __init__(self, **kwargs):
401        AbstractFeature.__init__(self,**kwargs)
402        children={'time':[CSML('time'), 'csString'], 'value':[CSML('ReferenceableGridCoverage'), 'ReferenceableGridCoverage', CSML('value')], 'parameter':[CSML('parameter'), 'Phenomenon']}
403        addchildren(self,children)
404
405
406       
407class FileExtract(ArrayDescriptor, csElement):
408    def __init__(self,**kwargs):
409        ArrayDescriptor.__init__(self,**kwargs)
410        children= {'fileName':[CSML('fileName'), 'csString']}
411        addchildren(self,children)
412
413class NetCDFExtract(FileExtract, csElement):
414    def __init__(self,**kwargs):
415        FileExtract.__init__(self, **kwargs)
416        children={'variableName':[CSML('variableName'), 'csString']}
417        addchildren(self,children)
418       
419class NASAAmesExtract(FileExtract, csElement):
420    def __init__(self,**kwargs):
421        FileExtract.__init__(self, **kwargs)
422        children={'variableName':[CSML('variableName'), 'csString'], 'index':[CSML('index'),'csString']}
423        addchildren(self,children)
424
425class FeatureCollection(AbstractFeatureCollection,csElement):
426    def __init__(self,**kwargs):
427        AbstractFeatureCollection.__init__(self,**kwargs)
428        children={'members':[[CSML('GridFeature'),CSML('PointFeature')], 'AbstractFeature', GML('featureMembers')]}
429        addchildren(self,children)
430    def _getSubstitutionType(self,tag):
431        if tag==CSML('GridFeature'):
432            return 'GridFeature'
433        elif tag==CSML('PointFeature'):
434            return 'PointFeature'
435        else: return 'AbstractFeature'
436    def _getReverseSubsType(self, typename):
437        if typename== 'GridFeature':
438            return CSML('GridFeature')
439        elif typename == 'PointFeature':
440            return CSML('PointFeature')
441        else: return CSML('AbstractFeature')
442
443       
444class Dataset(AbstractGML, csElement):   
445    ''' Dataset class, needed as root of tree'''
446    def __init__(self, **kwargs):
447        AbstractGML.__init__(self,**kwargs)
448        #children = {'ncExtract':[CSML('NetCDFExtract'), 'NetCDFExtract'], 'featureCollection':[CSML('featureCollection') ,'FeatureCollection']}
449        children = {'featureCollection':[GML('FeatureCollection') ,'FeatureCollection'],'fileExtracts':[FILEFORMATS, 'ArrayDescriptor']}
450        addchildren(self,children)
451    def toXML(self):
452        csmlfrag=ET.Element(CSML('Dataset'))
453        csElement.toXML(self, csmlfrag)
454        return csmlfrag
455    def _getSubstitutionType(self,tag):
456        if tag==CSML('NetCDFExtract'):
457            return 'NetCDFExtract'
458        elif tag==CSML('NASAAmesExtract'):
459            return 'NASAAmesExtract'
460        else: return 'ArrayDescriptor'
461    def _getReverseSubsType(self, typename):
462        if typename== 'NetCDFExtract':
463            return CSML('NetCDFExtract')
464        elif typename == 'NASAAmesExtract':
465            return CSML('NASAAmesExtract')
466        else: return CSML('ArrayDescriptor')
467       
468        return typename
469
470def main():
471    '''round trip for testing purposes:'''
472    print '\n'
473    tree=ET.ElementTree(file='test.xml')
474    ds=Dataset()
475    ds.fromXML(tree.getroot())
476    csmltree=ds.toXML()
477    #print csmltree
478   
479    csmlout=parser_extra.PrettyPrint(csmltree)
480    csmlout=parser_extra.removeInlineNS(csmlout)
481    print '\n %s'% csmlout
482    #for member in ds.featureCollection.members:
483      #print dir(member.value)
484       
485
486if __name__=='__main__':
487    main()
Note: See TracBrowser for help on using the repository browser.