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

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

RangeSet, CoverageFunction, AggregatedArray, Envelope, !SRSInformationGroup, !SRSReferenceGroup 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')]
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                            else:
125                                frag=ET.Element(ename)
126                                po.toXML(frag)
127                                csmlfrag.append(frag)
128                        if parentfrag is not None:
129                            csmlfrag.append(parentfrag)
130        return csmlfrag
131       
132    def fromXML(self,csmlfrag):
133        # deal with attributes, e.g. gml id's
134        if csmlfrag.text is not None:
135                self.CONTENT = csmlfrag.text
136        for item in csmlfrag.items():
137            if item[0] in self.ATTRIBUTES:
138                setattr(self, item[0], item[1])
139        # self.CHILDREN (recursive - calls the fromXML method of children
140        for frag in csmlfrag[:]:
141            #for each child element
142            #iterate through expected CHILDREN
143            for child in self.CHILDREN:
144                #get element name
145                if len(self.CHILDREN[child])==3:
146                    ename = self.CHILDREN[child][2]
147                    ename2 = self.CHILDREN[child][0]
148                   
149                else:
150                    ename = self.CHILDREN[child][0] 
151                    ename2=None
152                #if there are options, then find the name that matches the frag
153                if ename2 is not None:
154                    if frag[:] != []:
155                        for subfrag in frag[:]:
156                            etype=None
157                            if type(ename2) is list:
158                                if subfrag.tag in ename2:
159                                    etype=self._getSubstitutionType(subfrag.tag)
160                            if subfrag.tag==ename2:
161                                etype=self.CHILDREN[child][1]
162                            if etype:
163                                childobj=eval(etype)()
164                                if len(self.CHILDREN[child])==3:
165                                    if frag[:] != []:
166                                        childobj.fromXML(subfrag)
167                                else:
168                                    childobj.fromXML(frag)
169                                #set this object to be an attribute of the 'parent' (self) object
170                                if hasattr(self, child):
171                                    if type(self.__dict__[child]) is not list:
172                                        tmp=self.__dict__[child]
173                                        setattr(self, child, [tmp]) #convert to list
174                                    self.__dict__[child].append(childobj)
175                                else:
176                                    setattr(self, child, childobj)
177                else:
178                    etype=None
179                    if type(ename) is list:
180                        if frag.tag in ename:
181                            etype=self._getSubstitutionType(frag.tag)
182                    elif frag.tag==ename:
183                        etype=self.CHILDREN[child][1]
184                    if etype:
185                        childobj=eval(etype)()
186                        if len(self.CHILDREN[child])==3:
187                            if frag[:] != []:
188                                childobj.fromXML(frag[0])
189                        else:
190                            childobj.fromXML(frag)
191                        #set this object to be an attribute of the 'parent' (self) object
192                        if hasattr(self, child):
193                            if type(self.__dict__[child]) is not list:
194                                tmp=self.__dict__[child]
195                                setattr(self, child, [tmp]) #convert to list
196                            self.__dict__[child].append(childobj)
197                        else:
198                            setattr(self, child, childobj)
199
200               
201class csString(csElement):
202    pass
203
204class AbstractGML(csElement):
205    def __init__(self, **kwargs):
206        a=[GML('id'), GML('description'), GML('name'), GML('MetaDataProperty')]
207        addatts(self,a)
208
209class AssociationAttributeGroup(csElement):
210    def __init__(self, **kwargs):
211        a =[XLINK('href'),XLINK('role'), XLINK('arcrole'),XLINK('title'), XLINK('show'), XLINK('actuate')] 
212        addatts(self,a)
213
214class SRSReferenceGroup(csElement):
215    def __init__(self, **kwargs):
216        a =['srsName','srsDimension'] 
217        addatts(self,a)
218       
219class SRSInformationGroup(csElement):
220    def __init__(self, **kwargs):
221        a =['uomLabels','axisLabels'] 
222        addatts(self,a)
223
224class ArrayDescriptor(AbstractGML, csElement):
225    def __init__(self,**kwargs):
226        AbstractGML.__init__(self,**kwargs)
227        children={'arraySize':[CSML('arraySize'), 'csString'], 'uom':[CSML('uom'),'csString'], 'numericType':[CSML('numericType'),'csString'], 'regExpTransform':[CSML('regExpTransform'),'csString'], 'numericTransform':[CSML('numericTransform'),'csString']}
228        addchildren(self,children)
229
230class DirectPosition(AbstractGML, SRSReferenceGroup,SRSInformationGroup,csElement):
231    def __init__(self, **kwargs):
232        AbstractGML.__init__(self,**kwargs)
233
234
235class Envelope(AbstractGML,SRSReferenceGroup, csElement):
236    def __init__(self, **kwargs):
237        SRSReferenceGroup.__init__(self,**kwargs)
238        AbstractGML.__init__(self,**kwargs)
239        children={'lowerCorner':[GML('lowerCorner'), 'DirectPosition'],'upperCorner':[GML('upperCorner'), 'DirectPosition']}
240        addchildren(self,children)
241
242
243class AbstractFeature(AbstractGML,csElement):
244    def __init__(self, **kwargs):
245        AbstractGML.__init__(self,**kwargs)
246        children={'boundedBy':[GML('boundedBy'), 'Envelope']}
247        addchildren(self,children)
248
249class AbstractFeatureCollection(AbstractFeature,csElement):
250    def __init__(self, **kwargs):
251        AbstractFeature.__init__(self,**kwargs)
252
253class DomainSet(AbstractGML,AssociationAttributeGroup,csElement):
254    def __init__(self, **kwargs):
255        AbstractGML.__init__(self,**kwargs)
256        addchildren(self,{})
257
258class AggregatedArray(ArrayDescriptor,csElement):
259    def __init__(self, **kwargs):
260        ArrayDescriptor.__init__(self,**kwargs)
261        children={'aggType':[CSML('aggType'),'csString'], 'aggIndex':[CSML('aggIndex'),'csString'],'components':[FILEFORMATS, 'ArrayDescriptor',CSML('component')]}
262        addchildren(self,children)
263#'component':[CSML:('component'), 'ArrayDescriptor', CSML('component')],
264class MeasureOrNullList(AbstractGML,csElement):
265    def __init__(self, **kwargs):
266        AbstractGML.__init__(self,**kwargs)
267        children={}
268        addchildren(self,children)
269       
270class CompositeValue(AbstractGML,csElement):
271    def __init__(self, **kwargs):
272        AbstractGML.__init__(self,**kwargs)
273        children={'measures':[GML('measure'),'csString',GML('valueComponents')]}
274        addchildren(self,children)
275       
276class DataBlock(AbstractGML,csElement):
277    def __init__(self, **kwargs):
278        AbstractGML.__init__(self,**kwargs)
279        children={'doubleOrNullTupleList':[GML('doubleOrNullTupleList'),'csString'],'rangeParameters':[GML('CompositeValue'), 'CompositeValue', GML('rangeParameters')]}
280        addchildren(self,children)
281
282class RangeSet(AbstractGML,AssociationAttributeGroup,csElement):
283    def __init__(self, **kwargs):
284        AbstractGML.__init__(self,**kwargs)
285        children={'quantityList':[GML('QuantityList'), 'MeasureOrNullList'],        'dataBlock':[GML('DataBlock'),'DataBlock'],'arrayDescriptor':[FILEFORMATS, 'ArrayDescriptor'],  'aggregatedArray':[CSML('AggregatedArray'), 'AggregatedArray']}
286        addchildren(self,children)
287
288class PointDomain(DomainSet):
289    def __init__(self, **kwargs):
290        DomainSet.__init__(self,**kwargs)
291        children={'pointMember':[GML('pointMember'), 'csString']}
292        addchildren(self,children)
293
294class AbstractCoverage(AbstractFeature, csElement):
295    def __init__(self, **kwargs):
296        AbstractFeature.__init__(self,**kwargs)
297
298class AbstractDiscreteCoverage(AbstractCoverage, csElement):
299    def __init__(self, **kwargs):
300        AbstractCoverage.__init__(self,**kwargs)
301        addchildren(self,{})
302
303class GridCoordinatesTable(AbstractGML,csElement):
304    def __init__(self,**kwargs):
305        AbstractGML.__init__(self,**kwargs)
306        children={'pointMember':[GML('pointMember'), 'csString']}
307        addchildren(self,children)
308       
309class ReferenceableGrid(AbstractGML, AssociationAttributeGroup, csElement):
310    def __init__(self, **kwargs):
311        AbstractGML.__init__(self,**kwargs)
312        AssociationAttributeGroup.__init__(self,**kwargs)
313        children={'coordTransformTable':[GML('GridCoordinatesTable'), 'GridCoordinatesTable', GML('coordTransformTable')]}
314        addchildren(self,children)
315        a=['dimension']
316        addatts(self,a)
317
318class ReferenceableGridCoverage(AbstractDiscreteCoverage, csElement):
319    def __init__(self, **kwargs):
320        AbstractDiscreteCoverage.__init__(self,**kwargs)
321        children={'referenceableGridDomain':[CSML('ReferenceableGrid'),'ReferenceableGrid' ,CSML('referenceableGridDomain') ]}
322        addchildren(self,children)
323       
324class PointCoverage(AbstractDiscreteCoverage, csElement):
325    def __init__(self, **kwargs):
326        AbstractDiscreteCoverage.__init__(self,**kwargs)
327        children={'pointDomain':[CSML('PointDomain'),'PointDomain' ,CSML('pointDomain') ], 'rangeSet':[GML('rangeSet'), 'RangeSet'],'coverageFunction':[GML('coverageFunction'),'csString']}
328        addchildren(self,children)
329
330class Definition(AbstractGML):
331    def __init__(self, **kwargs):
332        AbstractGML.__init__(self,**kwargs)
333        addchildren(self,{})
334
335class Phenomenon(Definition,AssociationAttributeGroup):
336    def __init__(self, **kwargs):
337        Definition.__init__(self,**kwargs)
338        AssociationAttributeGroup.__init__(self,**kwargs)
339        children = {'':[CSML(''), '']}   
340        addchildren(self,children)
341
342class PointFeature(AbstractFeature, csElement):
343    def __init__(self, **kwargs):
344        AbstractFeature.__init__(self,**kwargs)
345        children={'location':[CSML('location'), 'csString'],'time':[CSML('time'), 'csString'], 'value':[CSML('PointCoverage'), 'PointCoverage', CSML('value')], 'parameter':[CSML('parameter'), 'Phenomenon']}
346        addchildren(self,children)
347
348
349class GridFeature(AbstractFeature, csElement):
350    def __init__(self, **kwargs):
351        AbstractFeature.__init__(self,**kwargs)
352        children={'time':[CSML('time'), 'csString'], 'value':[CSML('ReferenceableGridCoverage'), 'ReferenceableGridCoverage', CSML('value')], 'parameter':[CSML('parameter'), 'Phenomenon']}
353        addchildren(self,children)
354
355
356       
357class FileExtract(ArrayDescriptor, csElement):
358    def __init__(self,**kwargs):
359        ArrayDescriptor.__init__(self,**kwargs)
360        children= {'fileName':[CSML('fileName'), 'csString']}
361        addchildren(self,children)
362
363class NetCDFExtract(FileExtract, csElement):
364    def __init__(self,**kwargs):
365        FileExtract.__init__(self, **kwargs)
366        children={'variableName':[CSML('variableName'), 'csString']}
367        addchildren(self,children)
368       
369class NASAAmesExtract(FileExtract, csElement):
370    def __init__(self,**kwargs):
371        FileExtract.__init__(self, **kwargs)
372        children={'variableName':[CSML('variableName'), 'csString'], 'index':[CSML('index'),'csString']}
373        addchildren(self,children)
374
375class FeatureCollection(AbstractFeatureCollection,csElement):
376    def __init__(self,**kwargs):
377        AbstractFeatureCollection.__init__(self,**kwargs)
378        children={'members':[[CSML('GridFeature'),CSML('PointFeature')], 'AbstractFeature', GML('featureMembers')]}
379        addchildren(self,children)
380    def _getSubstitutionType(self,tag):
381        if tag==CSML('GridFeature'):
382            return 'GridFeature'
383        elif tag==CSML('PointFeature'):
384            return 'PointFeature'
385        else: return 'AbstractFeature'
386    def _getReverseSubsType(self, typename):
387        if typename== 'GridFeature':
388            return CSML('GridFeature')
389        elif typename == 'PointFeature':
390            return CSML('PointFeature')
391        else: return CSML('AbstractFeature')
392
393       
394class Dataset(AbstractGML, csElement):   
395    ''' Dataset class, needed as root of tree'''
396    def __init__(self, **kwargs):
397        AbstractGML.__init__(self,**kwargs)
398        #children = {'ncExtract':[CSML('NetCDFExtract'), 'NetCDFExtract'], 'featureCollection':[CSML('featureCollection') ,'FeatureCollection']}
399        children = {'featureCollection':[GML('FeatureCollection') ,'FeatureCollection'],'fileExtracts':[FILEFORMATS, 'ArrayDescriptor']}
400        addchildren(self,children)
401    def toXML(self):
402        csmlfrag=ET.Element(CSML('Dataset'))
403        csElement.toXML(self, csmlfrag)
404        return csmlfrag
405    def _getSubstitutionType(self,tag):
406        if tag==CSML('NetCDFExtract'):
407            return 'NetCDFExtract'
408        elif tag==CSML('NASAAmesExtract'):
409            return 'NASAAmesExtract'
410        else: return 'ArrayDescriptor'
411    def _getReverseSubsType(self, typename):
412        if typename== 'NetCDFExtract':
413            return CSML('NetCDFExtract')
414        elif typename == 'NASAAmesExtract':
415            return CSML('NASAAmesExtract')
416        else: return CSML('ArrayDescriptor')
417       
418        return typename
419
420def main():
421    '''round trip for testing purposes:'''
422    print '\n'
423    tree=ET.ElementTree(file='test.xml')
424    ds=Dataset()
425    ds.fromXML(tree.getroot())
426    csmltree=ds.toXML()
427    #print csmltree
428   
429    csmlout=parser_extra.PrettyPrint(csmltree)
430    csmlout=parser_extra.removeInlineNS(csmlout)
431    print '\n %s'% csmlout
432    #for member in ds.featureCollection.members:
433      #print dir(member.value)
434       
435
436if __name__=='__main__':
437    main()
Note: See TracBrowser for help on using the repository browser.