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

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

added main() method to molesReadWrite.py that lists sschema object model

RevLine 
[1650]1#Dominic Lowe, BADC  18 October 2006
[1855]2#Updated Sue Latham, BADC 6 December 2006 - add dgStructuredKeyword class
[1597]3
4import cElementTree as ET
[1692]5import sys
[1650]6
[2133]7
8#this is the NEW xml schema class
[2152]9
[1692]10class xmlSchema(object):
[1694]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    '''
[1692]16    def __init__(self, schema):
[2133]17        self.schema=schema
18        self.types={}
[1692]19        self.sequences={}
[2133]20        self.names=[]
21        self.setup()
[2152]22
[2133]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       
[2152]65    def __checkChildren(self, parentclassname, elem):     
66        #if parentclassname == 'dgMetadataProvenance':
67            #pdb.set_trace()
68        for child in elem[:]:
69            childname = None
[2133]70            if child.attrib.has_key('name'):       
71                if child.attrib['name'][-4:]=='Type':
72                    childname=child.attrib['name'][:-4]
73                else:
74                    childname=child.attrib['name']       
75                if child.attrib.has_key('type'):
76                    if child.attrib['type'][:6]=='moles:':
77                        typename=child.attrib['type'][6:-4]
78                        self.types[childname]=typename             
79            elif child.attrib.has_key('ref'):
80                if child.attrib['ref'][:6]=='moles:':
81                    childname=child.attrib['ref'][6:]
82            if childname is not None:
83                if self.sequences[parentclassname] is None:
84                    self.sequences[parentclassname]=[childname]
85                else:
86                    tmp= self.sequences[parentclassname]                   
87                    tmp.append(childname)
88                    self.sequences[parentclassname]=tmp             
89                if self.__isParent(child):
[2152]90                    if not self.sequences.has_key(childname):
91                        self.sequences[childname]=[]
[2133]92                    self. __checkChildren(childname,child)   
93            else:
94                if self.__isParent(child):
95                    self. __checkChildren(parentclassname,child)   
96
97    def __resolveTypes(self):
98        for ty in self.types:
99            try:
100                self.sequences[ty]=self.sequences[self.types[ty]]
101            except:
102                pass
103           
104    def setup(self):   
105        tree = ET.parse(self.schema)
106        root = tree.getroot()
107        self.sequences['dummy']=[]
108        self.__checkChildren('dummy',root)
109        self.__resolveTypes()
110        self.sequences['dummy']=None
111   
112    def lookupOrder(self, dict,classname):
113        '''takes the attributes in a dictionary and orders them according to the schema sequence'''
114        try:       
115            order=self.sequences[classname]
116        except KeyError:
117            order = []
118            for key in dict:
119                #print key error
120                print 'KEY ERROR %s'%classname
121                if key is not 'schema':
122                    if key is not 'ns':
123                         order.append(key) # if it can't be found an unordered list is returned from the original dictionary items
124            #print 'returning %s'%order
125        return order
126
[1606]127class molesElement(object):
[1694]128    ''' molesElement class - base class of all elements '''
[1676]129    def __init__(self, namespace=None, **kwargs):
130        if namespace !=None:
131            self.ns=namespace
132        else:
[1904]133            self.ns = '{http://ndg.nerc.ac.uk/moles}'
[1672]134        self.__dict__.update(kwargs)
[1694]135   
136    def __combineattributes(self,attname, newChild):
[1643]137        att = getattr(self,attname)
138        if isinstance(att,molesElement):
139            setattr(self,attname,[att, newChild])
[1650]140        else:
[1643]141            att.append(newChild)
142            setattr(self, attname,att)
[1904]143           
144    def _stripNS(self, tagtostrip):
145        try:
146            elemname=tagtostrip.split('}')[1]
147            ns=tagtostrip.split('}')[0]+'}'
148        except IndexError:
149            elemname=tagtostrip
150            ns='{https://ndg.nerc.ac.uk/moles}'
151        return elemname, ns
152           
153        ns=tagtostrip.split('}')[1]
154     
[1891]155   
[1904]156    def addChildElem(self, childname, childobj):
[1891]157        #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.
158        if hasattr(self, childname):
159            currentattribute=getattr(self,childname)
160            if type(getattr(self,childname)) is list:
161                currentattribute.append(childobj)
162            else:
163                newlist=[currentattribute]
164                newlist.append(childobj)
165                setattr(self,childname, newlist)
166        else:
167            setattr(self,childname, childobj)
168   
[1692]169    def toXML(self,molesFrag, schema=None):
170        if schema != None:
171            self.schema=schema
172        else:
173            self.schema=None
[2082]174        #print molesFrag.tag
[1694]175        orderedAttribs=schema.lookupOrder(self.__dict__,molesFrag.tag)
176        for item in orderedAttribs:
[2082]177           #print "item in orderedAttribs is %s" %item
[2065]178           if type(item) is xmlSchema:
179                        continue
180           if item == '{http://ndg.nerc.ac.uk/moles}':
181                continue
[1904]182           if hasattr(self, item):
[1694]183                if isinstance(self.__dict__[item], molesElement):
184                    frag=ET.Element(item)
185                    self.__dict__[item].toXML(frag,schema=self.schema)
186                    molesFrag.append(frag)
187                elif isinstance(self.__dict__[item], list):
188                    for it in self.__dict__[item]:
189                        if isinstance(it, molesElement):
190                            frag=ET.Element(item)
191                            it.toXML(frag, schema=self.schema)
192                            molesFrag.append(frag)
193                        else:
194                            frag=ET.Element(item)
195                            frag.text=it
196                else:
197                    frag=ET.Element(item)
198                    frag.text=self.__dict__[item]
199                    molesFrag.append(frag)
[1597]200        return molesFrag
[1672]201           
[1629]202    def fromXML(self,molesFrag):
203        children = molesFrag.getchildren()
[1904]204       
[1629]205        if children ==[]:
[1904]206            elementWithoutNS, ns=self._stripNS(molesElement.tag)
207            setattr(self,elementWithoutNS, molesElement.text)
[1629]208        if children!=[]:
209            for child in children:
210                if child.getchildren()!=[]:
[1904]211                    childWithoutNS, ns=self._stripNS(child.tag)
212                    newClass=type(childWithoutNS, (molesElement,),{})
213                    newChild=newClass(ns)
[1629]214                    newChild.fromXML(child)
215                    kw=child.tag
[1904]216                    if hasattr(self, childWithoutNS):
217                        self.__combineattributes(childWithoutNS, newChild)
[1643]218                    else:
[1904]219                        setattr(self,childWithoutNS, newChild)
[1643]220                else:
[1904]221                    childWithoutNS, ns=self._stripNS(child.tag)
222                    setattr(self,childWithoutNS, child.text)
[1650]223       
[1643]224                   
[1597]225class dgMetadata(molesElement):   
[1676]226    def __init__(self, **kwargs):
227        molesElement.__init__(self, **kwargs)
[1672]228       
[1597]229    def toXML(self):
[1838]230        self.schema = xmlSchema('ndgmetadata1.3.xsd')
[1597]231        molesFrag=ET.Element('dgMetadata')
[1904]232        molesFrag.attrib['xmlns']='http://ndg.nerc.ac.uk/moles'
[1692]233        molesElement.toXML(self,molesFrag,schema=self.schema)
[1597]234        return molesFrag
235
[1606]236
237class MolesDoc(object):
238    def __init__(self):
[1652]239        self._createClasses()
[1606]240   
241    def _create_a_class(self,name, base_class):
242        aNewClass=type(name, (base_class,),{})
243        return aNewClass
244
245    def _createClasses(self):
[1608]246        #if you want more classes just add their names to this list
[1694]247        #could probably examine the schema here....
[1609]248        classList= \
249        ['dataModelID', \
[1608]250        'dgDataGranule', \
251        'dgDataEntity', \
252        'dgMetadataRecord', \
[1855]253        'dgMetadataID',
[1609]254        'dgCoverage', \
[2065]255        'dgDataCoverage',\
[2168]256        'dgSpatioTemporalRange',\
[1609]257        'dgSpatioTemporalCoverage', \
258        'dgSpatialCoverage', \
259        'dgTemporalCoverage', \
260        'dgBoundingBox', \
[1611]261        'DateRange', \
[2065]262        'dgDataSummary', \
263        'dgParameterSummary', \
264        'dgParameterValue', \
265        'dgValueDataParameter', \
266        'dgStandardUnit', \
267        'dgOriginalUnit', \
268        'dgRangeDataParameter', \
269        'dgEnumerationParameter', \
270        'dgParameterGroup', \
271        'dgComponentParameter', \
272        'dgStdParameterMeasured', \
273        'dgStandardUnit', \
274        'dgValidTermID', \
275        'dgValidTermParentID', \
276        'dgValidSubterm', \
277        'metadataDescriptionID', \
[1629]278        'dgMetadataDescription', \
[1891]279        'dgStructuredKeyword', \
[2111]280        'abstract',\
[2129]281        'descriptionSection',\
282        'descriptionOnlineReference',\
283        'dgSimpleLink',\
284        'logos',\
285        'logoURI',\
286        'dgDataSetType',\
287        'dgSimulation',\
288        'dgAnalysis',\
289        'dgMeasurement',\
290        'dgFeatureType',\
[2166]291        'dgDataRoles',\
292        'dgDataCreator',\
293        'dgDataCurator',\
294        'dgRoleHolder',\
295        'dgOrganisationID',\
296        'dgPersonID',\
297        'dgRoleID',\
298        'contactDetails',\
299        'address',\
[1891]300        ]
[1606]301
[1608]302        for className in classList:
303            newClass=self._create_a_class(className, molesElement)
304            setattr(self,className,newClass)
[2169]305
306
307def main():
308    schema = xmlSchema('ndgmetadata1.3.xsd') 
309       
310    #print schema.sequences
311    for key in schema.sequences:
312        print '------------------------------------------------------------------'
313        print key
314        print schema.sequences[key]
315   
316
317 
318   
319if __name__=='__main__':
320    main()
Note: See TracBrowser for help on using the repository browser.