source: TI02-CSML/trunk/csml/csml2Moles/molesReadWrite.py @ 2180

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/trunk/csml/csml2Moles/molesReadWrite.py@2180
Revision 2180, 11.6 KB checked in by domlowe, 13 years ago (diff)

fix for dgDataSetType nameclash

Line 
1#Dominic Lowe, BADC  18 October 2006
2#Updated Sue Latham, BADC 6 December 2006 - add dgStructuredKeyword class
3
4import cElementTree as ET
5import sys
6
7
8#this is the NEW xml schema class
9
10class xmlSchema(object):
11    ''' this class creates a mapping of the xml schema sequences so that it can be referred to when
12    writing out a new moles document - this enables elements to be written in the order specified by the schema
13    If a particular sequence mapping can't be found then the elements will be written in whichever order python sees fit.
14    It tries various searches of the schema to pick out the sequences (which can be nested)
15    '''
16    def __init__(self, schema):
17        self.schema=schema
18        self.types={}
19        self.sequences={}
20        self.names=[]
21        self.setup()
22
23    def __isParent(self,elem):
24        #if this element is a parent of other elements (excluding annotation and documentation)
25        #then return True else return false
26        if elem[:]==[]:
27            return False
28        for child in elem[:]:
29            if child.tag == '{http://www.w3.org/2001/XMLSchema}element':
30                return True
31            elif child.tag == '{http://www.w3.org/2001/XMLSchema}complexType':
32                return True
33            elif child.tag == '{http://www.w3.org/2001/XMLSchema}simpleType':
34                return True
35            elif child.tag == '{http://www.w3.org/2001/XMLSchema}annotation':
36                pass
37            elif child.tag == '{http://www.w3.org/2001/XMLSchema}sequence':
38                return True
39            elif child.tag == '{http://www.w3.org/2001/XMLSchema}choice':
40                return True
41            elif child.tag == '{http://www.w3.org/2001/XMLSchema}complexContent':
42                return True
43            elif child.tag == '{http://www.w3.org/2001/XMLSchema}documentation':
44                pass
45            elif child.tag == '{http://www.w3.org/2001/XMLSchema}restriction':
46                return True
47            elif child.tag == '{http://www.w3.org/2001/XMLSchema}extension':
48                pass
49            elif child.tag == '{http://www.w3.org/2001/XMLSchema}attribute':
50                pass #?
51            elif child.tag == '{http://www.w3.org/2001/XMLSchema}enumeration':
52                pass #?
53       
54             #pattern
55             #attributeGroup
56             #minLength
57             #minInclusive
58             #maxInclusive
59
60        return False
61       
62       
63       
64       
65    def __checkChildren(self, parentclassname, elem):     
66        #if parentclassname == 'dgMetadataProvenance':
67            #pdb.set_trace()
68        for child in elem[:]:
69            childname = None
70            if child.attrib.has_key('name'):       
71                if child.attrib['name'][-4:]=='Type':
72                    if child.attrib['name'] in ['dgDataSetType']:  #add other rogue 'names' ending in Type to this list
73                        childname=child.attrib['name']
74                    else:
75                        childname=child.attrib['name'][:-4]
76                else:
77                    childname=child.attrib['name']       
78                if child.attrib.has_key('type'):
79                    if child.attrib['type'][:6]=='moles:':
80                        typename=child.attrib['type'][6:-4]
81                        self.types[childname]=typename             
82            elif child.attrib.has_key('ref'):
83                if child.attrib['ref'][:6]=='moles:':
84                    childname=child.attrib['ref'][6:]
85            if childname is not None:
86                if self.sequences[parentclassname] is None:
87                    self.sequences[parentclassname]=[childname]
88                else:
89                    tmp= self.sequences[parentclassname]                   
90                    tmp.append(childname)
91                    self.sequences[parentclassname]=tmp             
92                if self.__isParent(child):
93                    if not self.sequences.has_key(childname):
94                        self.sequences[childname]=[]
95                    self. __checkChildren(childname,child)   
96            else:
97                if self.__isParent(child):
98                    self. __checkChildren(parentclassname,child)   
99
100    def __resolveTypes(self):
101        for ty in self.types:
102            try:
103                self.sequences[ty]=self.sequences[self.types[ty]]
104            except:
105                pass
106           
107    def setup(self):   
108        tree = ET.parse(self.schema)
109        root = tree.getroot()
110        self.sequences['dummy']=[]
111        self.__checkChildren('dummy',root)
112        self.__resolveTypes()
113        self.sequences['dummy']=None
114   
115    def lookupOrder(self, dict,classname):
116        '''takes the attributes in a dictionary and orders them according to the schema sequence'''
117        try:       
118            order=self.sequences[classname]
119        except KeyError:
120            order = []
121            for key in dict:
122                #print key error
123                print 'KEY ERROR %s'%classname
124                if key is not 'schema':
125                    if key is not 'ns':
126                         order.append(key) # if it can't be found an unordered list is returned from the original dictionary items
127            #print 'returning %s'%order
128        return order
129
130class molesElement(object):
131    ''' molesElement class - base class of all elements '''
132    def __init__(self, namespace=None, **kwargs):
133        if namespace !=None:
134            self.ns=namespace
135        else:
136            self.ns = '{http://ndg.nerc.ac.uk/moles}'
137        self.__dict__.update(kwargs)
138   
139    def __combineattributes(self,attname, newChild):
140        att = getattr(self,attname)
141        if isinstance(att,molesElement):
142            setattr(self,attname,[att, newChild])
143        else:
144            att.append(newChild)
145            setattr(self, attname,att)
146           
147    def _stripNS(self, tagtostrip):
148        try:
149            elemname=tagtostrip.split('}')[1]
150            ns=tagtostrip.split('}')[0]+'}'
151        except IndexError:
152            elemname=tagtostrip
153            ns='{https://ndg.nerc.ac.uk/moles}'
154        return elemname, ns
155           
156        ns=tagtostrip.split('}')[1]
157     
158   
159    def addChildElem(self, childname, childobj):
160        #sometimes you want to add a child element but don't know if there is one already. In which case you want to create a list of child objects.
161        if hasattr(self, childname):
162            currentattribute=getattr(self,childname)
163            if type(getattr(self,childname)) is list:
164                currentattribute.append(childobj)
165            else:
166                newlist=[currentattribute]
167                newlist.append(childobj)
168                setattr(self,childname, newlist)
169        else:
170            setattr(self,childname, childobj)
171   
172    def toXML(self,molesFrag, schema=None):
173        if schema != None:
174            self.schema=schema
175        else:
176            self.schema=None
177        #print molesFrag.tag
178        orderedAttribs=schema.lookupOrder(self.__dict__,molesFrag.tag)
179        for item in orderedAttribs:
180           #print "item in orderedAttribs is %s" %item
181           if type(item) is xmlSchema:
182                        continue
183           if item == '{http://ndg.nerc.ac.uk/moles}':
184                continue
185           if hasattr(self, item):
186                if isinstance(self.__dict__[item], molesElement):
187                    frag=ET.Element(item)
188                    self.__dict__[item].toXML(frag,schema=self.schema)
189                    molesFrag.append(frag)
190                elif isinstance(self.__dict__[item], list):
191                    for it in self.__dict__[item]:
192                        if isinstance(it, molesElement):
193                            frag=ET.Element(item)
194                            it.toXML(frag, schema=self.schema)
195                            molesFrag.append(frag)
196                        else:
197                            frag=ET.Element(item)
198                            frag.text=it
199                else:
200                    frag=ET.Element(item)
201                    frag.text=self.__dict__[item]
202                    molesFrag.append(frag)
203        return molesFrag
204           
205    def fromXML(self,molesFrag):
206        children = molesFrag.getchildren()
207       
208        if children ==[]:
209            elementWithoutNS, ns=self._stripNS(molesElement.tag)
210            setattr(self,elementWithoutNS, molesElement.text)
211        if children!=[]:
212            for child in children:
213                if child.getchildren()!=[]:
214                    childWithoutNS, ns=self._stripNS(child.tag)
215                    newClass=type(childWithoutNS, (molesElement,),{})
216                    newChild=newClass(ns)
217                    newChild.fromXML(child)
218                    kw=child.tag
219                    if hasattr(self, childWithoutNS):
220                        self.__combineattributes(childWithoutNS, newChild)
221                    else:
222                        setattr(self,childWithoutNS, newChild)
223                else:
224                    childWithoutNS, ns=self._stripNS(child.tag)
225                    setattr(self,childWithoutNS, child.text)
226       
227                   
228class dgMetadata(molesElement):   
229    def __init__(self, **kwargs):
230        molesElement.__init__(self, **kwargs)
231       
232    def toXML(self):
233        self.schema = xmlSchema('ndgmetadata1.3.xsd')
234        molesFrag=ET.Element('dgMetadata')
235        molesFrag.attrib['xmlns']='http://ndg.nerc.ac.uk/moles'
236        molesElement.toXML(self,molesFrag,schema=self.schema)
237        return molesFrag
238
239
240class MolesDoc(object):
241    def __init__(self):
242        self._createClasses()
243   
244    def _create_a_class(self,name, base_class):
245        aNewClass=type(name, (base_class,),{})
246        return aNewClass
247
248    def _createClasses(self):
249        #if you want more classes just add their names to this list
250        #could probably examine the schema here....
251        classList= \
252        ['dataModelID', \
253        'dgDataGranule', \
254        'dgDataEntity', \
255        'dgMetadataRecord', \
256        'dgMetadataID',
257        'dgCoverage', \
258        'dgDataCoverage',\
259        'dgSpatioTemporalRange',\
260        'dgSpatioTemporalCoverage', \
261        'dgSpatialCoverage', \
262        'dgTemporalCoverage', \
263        'dgBoundingBox', \
264        'DateRange', \
265        'dgDataSummary', \
266        'dgParameterSummary', \
267        'dgParameterValue', \
268        'dgValueDataParameter', \
269        'dgStandardUnit', \
270        'dgOriginalUnit', \
271        'dgRangeDataParameter', \
272        'dgEnumerationParameter', \
273        'dgParameterGroup', \
274        'dgComponentParameter', \
275        'dgStdParameterMeasured', \
276        'dgStandardUnit', \
277        'dgValidTermID', \
278        'dgValidTermParentID', \
279        'dgValidSubterm', \
280        'metadataDescriptionID', \
281        'dgMetadataDescription', \
282        'dgStructuredKeyword', \
283        'abstract',\
284        'descriptionSection',\
285        'descriptionOnlineReference',\
286        'dgSimpleLink',\
287        'logos',\
288        'logoURI',\
289        'dgDataSetType',\
290        'dgSimulation',\
291        'dgAnalysis',\
292        'dgMeasurement',\
293        'dgFeatureType',\
294        'dgDataRoles',\
295        'dgDataCreator',\
296        'dgDataCurator',\
297        'dgRoleHolder',\
298        'dgOrganisationID',\
299        'dgPersonID',\
300        'dgRoleID',\
301        'contactDetails',\
302        'address',\
303        ]
304
305        for className in classList:
306            newClass=self._create_a_class(className, molesElement)
307            setattr(self,className,newClass)
308
309
310def main():
311    schema = xmlSchema('ndgmetadata1.3.xsd') 
312       
313    #print schema.sequences
314    for key in schema.sequences:
315        print '------------------------------------------------------------------'
316        print key
317        print schema.sequences[key]
318   
319
320 
321   
322if __name__=='__main__':
323    main()
Note: See TracBrowser for help on using the repository browser.