wiki:UsingTheParserToCreateCSML

Version 6 (modified by domlowe, 13 years ago) (diff)

Edited page on using the parser to create csml

How to create CSML using the CSML Parser classes

As you will know if you read the other parser how to, the CSML parser creates a python representation of a CSML document, using python classes to represent XML data types.

Each parser class has a fromXML() and a toXML() method. The fromXML method takes an XML document (or fragment) and populates the attributes of the python object, the toXML method takes the attributes and structure of the python object and creates an XML ElementTree fragment.

So to create CSML from scratch using python, all you need to do is:

  • Create some parser objects - a Dataset, a FeatureCollection, some Features etc.
  • Set their attributes to the right values for your data*.
  • Call the toXML method of the root level Dataset() object.
  • Sit back and enjoy your CSML document.

*In this example I have hard-coded data.

The following code snippets go through this process for a sample feature. To find out more you will have to explore the data structures of the parser a bit more using PyDoc or dir(). But the general pattern remains the same for all feature types.

The Code:

Here is the full code listing which we will look at in more detail:

import csml.parser
import csml.parser_extra


  #########################################
##  construction of CSML objects ##
  #########################################

# 
# ###############Reference System Definitions #######################
#empty list to hold definitionMembers
dm=[]
tc=csml.parser.TimeCoordinateSystem()
dm.append(tc)
rsd=csml.parser.ReferenceSystemDefinitions(definitionMembers=dm)



# #################### FeatureCollection #######################
# 
# #empty list to hold featureMembers
fms =[]
# 

# #### add a PointSeriesFeature: #####
ptsf=csml.parser.PointSeriesFeature()
ptsf.id='testbed270401'
ptsf.description=csml.parser.Description('Station BLUEBIRD')
ptsd=csml.parser.PointSeriesDomain()
t=csml.parser.Trajectory()
t.srsName='urn:EPSG:geographicCRS:4326'
t.locations=csml.parser.DirectPositionList(vals='0.1 1.5 25')
t.times=csml.parser.TimePositionList('#pred20060427001','-18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60')
ptsd.domainReference=t
ptsf.domain=ptsd
rs=csml.parser.RangeSet()
rs.quantityList=csml.parser.MeasureOrNullList('MLUnits.xml#m', '0.27 0.25 0.25 0.23 0.22 0.22 0.21 0.17 0.17 0.14 0.14 0.12 0.10 0.08 0.08 0.08 0.11 0.13 0.11 0.11 0.13 0.10 0.06 0.06 0.06 0.01 -0.03 -0.06 -0.09 -0.11 -0.11 -0.13 -0.16 -0.18 -0.17 -0.16 -0.18 -0.16 -0.12 -0.09 -0.08 -0.07 -0.06 -0.05 -0.04 -0.03 -0.03 -0.04 -0.02 -0.01 -0.02 -0.02 -0.02 -0.03 -0.03 -0.02 -0.01 -0.01 -0.02 -0.02 -0.03 -0.04 -0.04 -0.05 -0.04 -0.05 -0.08 -0.09 -0.11 -0.12 -0.12 -0.12 -0.12 -0.12 -0.13 -0.14 -0.15')
ptsf.rangeSet=rs
fms.append(ptsf)



# #instantiate FeatureCollection object:
fc=csml.parser.FeatureCollection(members=fms)
etp = csml.parser.EnvelopeWithTimePeriod()
etp.lowerCorner=csml.parser.DirectPosition('42 12',uomLabels='deg deg',axisLabels='lat lon')
etp.upperCorner=csml.parser.DirectPosition('42 26',uomLabels='deg deg',axisLabels='lat lon')
etp.timePosition='2006-04-26T06:00:00+01'
etp.timePosition2='2006-04-29T012:00:00+01'
fc.boundedBy=etp



#MetaDataProperty Object of <Dataset>
#list to hold multiple metaDataProperty elements
mds = []

md = csml.parser.MetaDataProperty()
md.text=['Data (c) 2006 CCLRC // www.cclrc.ac.uk']
mds.append(md)

md = csml.parser.MetaDataProperty()
md.text=['Test for CCLRC']
mds.append(md)
#etc...


########### The Dataset  ##############
#Create an Empty Dataset
ds = csml.parser.Dataset()
#Set objects as attributes of dataset
#NOTE: you can equally write this in the form: ds.id = 'Test001'  as used above.
setattr(ds,'id','Test001')
setattr(ds, 'metaDataProperty', mds)
setattr(ds,'description',csml.parser.Description('This is a test Water level.Period 26/04/06 06h -> 29/04/06 12h'))
setattr(ds, 'referenceSystemDefinitions', rsd)
setattr(ds, 'featureCollection',fc)
########################################

#call the toXML method of the Dataset object:
csmldoc = ds.toXML()
#parse and pretty print the result
strCSML=csml.parser_extra.PrettyPrint(csmldoc)
strCSML=csml.parser_extra.removeInlineNS(strCSML)
print strCSML

#(you could save this to file instead)

Now to look at this in more detail:

First we import the parser and parser_extra (which contains some essential extra functions):

import csml.parser
import csml.parser_extra

Now we can start the construction of CSML objects. However it probably helps to look at the end of the code first. Here we create a Dataset object (ds) and set other objects as attributes of the Dataset object.

########### The Dataset  ##############
#Create an Empty Dataset
ds = csml.parser.Dataset()
#Set objects as attributes of dataset
#NOTE: you can equally write this in the form: ds.id = 'Test001'  as used above.
setattr(ds,'id','Test001')
setattr(ds, 'metaDataProperty', mds)
setattr(ds,'description',csml.parser.Description('This is a test Water level.Period 26/04/06 06h -> 29/04/06 12h'))
setattr(ds, 'referenceSystemDefinitions', rsd)
setattr(ds, 'featureCollection',fc)
########################################

So the featureCollection, referenceSystemDefinitions etc are attributes of the Dataset. (Remember when we call the toXML() method on the Dataset, this also calls the toXML() methods of the featureCollection, referenceSystemDefinitions etc.)

Anyway, so the if the aim is to get a fully populated Dataset object, we need to create some feature objects. Below we are creating a PointSeriesFeature:

# #first we need an empty list to hold the featureMembers
fms =[]
 

##### now create a PointSeriesFeature: #####
##### see how you build up the domain and rangeSet ####
ptsf=csml.parser.PointSeriesFeature()
ptsf.id='testbed270401'
ptsf.description=csml.parser.Description('Station BLUEBIRD')
ptsd=csml.parser.PointSeriesDomain()
t=csml.parser.Trajectory()
t.srsName='urn:EPSG:geographicCRS:4326'
t.locations=csml.parser.DirectPositionList(vals='0.1 1.5 25')
t.times=csml.parser.TimePositionList('#pred20060427001','-18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60')
ptsd.domainReference=t
ptsf.domain=ptsd
rs=csml.parser.RangeSet()
rs.quantityList=csml.parser.MeasureOrNullList('MLUnits.xml#m', '0.27 0.25 0.25 0.23 0.22 0.22 0.21 0.17 0.17 0.14 0.14 0.12 0.10 0.08 0.08 0.08 0.11 0.13 0.11 0.11 0.13 0.10 0.06 0.06 0.06 0.01 -0.03 -0.06 -0.09 -0.11 -0.11 -0.13 -0.16 -0.18 -0.17 -0.16 -0.18 -0.16 -0.12 -0.09 -0.08 -0.07 -0.06 -0.05 -0.04 -0.03 -0.03 -0.04 -0.02 -0.01 -0.02 -0.02 -0.02 -0.03 -0.03 -0.02 -0.01 -0.01 -0.02 -0.02 -0.03 -0.04 -0.04 -0.05 -0.04 -0.05 -0.08 -0.09 -0.11 -0.12 -0.12 -0.12 -0.12 -0.12 -0.13 -0.14 -0.15')
ptsf.rangeSet=rs
fms.append(ptsf)

Okay, so you can create as many features as you like and add them to the fms[] (feature members) list. The process for creating file extracts e.g. NetCDFExtract() is very similar. Just instantiate a NetCDFExtract class, and set its attributes (id, variableName, fileName) to the values you want. You can then reference the (gml)id of this class from your features.

Anyway that was an aside. Now we have a feature or features we need to create a FeatureCollection object to contain them. This FeatureCollection object should also contain some bounding box information:

# #instantiate FeatureCollection object:
fc=csml.parser.FeatureCollection(members=fms)
etp = csml.parser.EnvelopeWithTimePeriod()
etp.lowerCorner=csml.parser.DirectPosition('42 12',uomLabels='deg deg',axisLabels='lat lon')
etp.upperCorner=csml.parser.DirectPosition('42 26',uomLabels='deg deg',axisLabels='lat lon')
etp.timePosition='2006-04-26T06:00:00+01'
etp.timePosition2='2006-04-29T012:00:00+01'
fc.boundedBy=etp

And here is an (empty) example of a ReferenceSystemDefinition object. Note that UnitDefinitions and PhenomenonDefinitions are all handled pretty much the same way.

# ###############Reference System Definitions #######################
#empty list to hold definitionMembers
dm=[]
tc=csml.parser.TimeCoordinateSystem()
dm.append(tc)
rsd=csml.parser.ReferenceSystemDefinitions(definitionMembers=dm)

Now we can define some MetaDataProperty?(ies) of the top-level (or root) Dataset object:

!python

#MetaDataProperty Object of <Dataset>
#list to hold multiple metaDataProperty elements
mds = []

md = csml.parser.MetaDataProperty()
md.text=['Data (c) 2006 CCLRC // www.cclrc.ac.uk']
mds.append(md)

md = csml.parser.MetaDataProperty()
md.text=['Test for CCLRC']
mds.append(md)
#etc...

And now as shown above, we tie everything together by assigning your featureCollection and your definitions and you fileextracts (not shown) to be attributes of the Dataset object:

########### The Dataset  ##############
#Create an Empty Dataset
ds = csml.parser.Dataset()
#Set objects as attributes of dataset
#NOTE: you can equally write this in the form: ds.id = 'Test001'  as used above.
setattr(ds,'id','Test001')
setattr(ds, 'metaDataProperty', mds)
setattr(ds,'description',csml.parser.Description('This is a test Water level. Period 26/04/06 06h -> 29/04/06 12h'))
setattr(ds, 'referenceSystemDefinitions', rsd)
setattr(ds, 'featureCollection',fc)
########################################

To generate your CSML file you now need to call the toXML() method of the dataset, and then also run a couple of functions that pretty print the result and fix up ElementTree namespaces.

#call the toXML method of the Dataset object:
csmldoc = ds.toXML()
#parse and pretty print the result
strCSML=csml.parser_extra.PrettyPrint(csmldoc)
strCSML=csml.parser_extra.removeInlineNS(strCSML)
print strCSML
#(you could save this to file instead)

That's it. So to recap, all we have done is:

  • Created some parser objects - a Dataset, a FeatureCollection, some Features etc.
  • Set the values of their attributes.
  • Set these objects to be attributes of the root level Dataset object.
  • Called the toXML method of the Dataset object.
  • Called a couple of utilty functions to tidy up the XML.
  • Sat back and enjoyed our CSML document.