1 | #parser_extra.py |
---|
2 | # DL 12 april 2006 |
---|
3 | # 'extra' functions to enable parsing. |
---|
4 | #contains: |
---|
5 | #. Namespace fix |
---|
6 | # Function to resolve references in CSML doc. |
---|
7 | |
---|
8 | import Parser |
---|
9 | import sys |
---|
10 | import elementtree.ElementTree as etree |
---|
11 | |
---|
12 | |
---|
13 | #some xml/string manipulation functions. may as well go in this file for now: |
---|
14 | |
---|
15 | |
---|
16 | def PrettyPrint(elem,indent='',html=0,space=' '): |
---|
17 | '''Lightweight pretty printing of elementTree elements''' |
---|
18 | def estrip(elem): |
---|
19 | ''' Just want to get rid of unwanted whitespace ''' |
---|
20 | if elem is None: |
---|
21 | return '' |
---|
22 | else: |
---|
23 | return elem.strip() |
---|
24 | strAttrib='' |
---|
25 | for att in elem.attrib: |
---|
26 | strAttrib+=' %s="%s"'%(att,elem.attrib[att]) |
---|
27 | result='%s<%s%s>%s'%(indent,elem.tag,strAttrib,estrip(elem.text)) |
---|
28 | children=len(elem) |
---|
29 | if children: |
---|
30 | for item in elem: |
---|
31 | result+='\n'+PrettyPrint(item,indent=indent+space) |
---|
32 | result+='\n%s%s</%s>'%(indent,estrip(item.tail),elem.tag) |
---|
33 | else: |
---|
34 | result+='</%s>'%(elem.tag) |
---|
35 | return result |
---|
36 | |
---|
37 | # fixing up namespaces: |
---|
38 | def removeInlineNS(csmlstring): |
---|
39 | # removeInlineNS: function removes "inline" namespaces and declares them as part of the Dataset element. |
---|
40 | #TODO: This whole thing is hardcoded and needs reviewing. |
---|
41 | |
---|
42 | #first need to update the ElementTree namespace map: |
---|
43 | etree._namespace_map.update({ |
---|
44 | 'http://www.opengis.net/om': 'om', 'http://www.opengis.net/gml': 'gml','http://ndg.nerc.ac.uk/csml' : 'csml', 'http://www.w3.org/1999/xlink':'xlink'}) |
---|
45 | |
---|
46 | #replace any fully qualified namespaces |
---|
47 | csmlstring=csmlstring.replace('{http://www.opengis.net/gml}', 'gml:') |
---|
48 | csmlstring=csmlstring.replace('{http://ndg.nerc.ac.uk/csml}','') |
---|
49 | csmlstring=csmlstring.replace('{http://www.w3.org/1999/xlink}','xlink:') |
---|
50 | csmlstring=csmlstring.replace('{http://www.opengis.net/om}','om:') |
---|
51 | csmlstring=csmlstring.replace('{http://ndg.nerc.ac.uk/moles}','moles:') |
---|
52 | #remove cmsl: prefixes |
---|
53 | csmlstring=csmlstring.replace('<csml:','<') |
---|
54 | csmlstring=csmlstring.replace('</csml:','</') |
---|
55 | |
---|
56 | #add namespace declarations at top of document |
---|
57 | csmlstring=csmlstring.replace('<Dataset', '<Dataset xmlns="http://ndg.nerc.ac.uk/csml" xmlns:gml="http://www.opengis.net/gml" xmlns:om="http://www.opengis.net/om" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:moles="http://ndg.nerc.ac.uk/moles" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://ndg.nerc.ac.uk/csml/XMLSchemas/CSMLAppSchema.xsd"') |
---|
58 | |
---|
59 | #this is only used when creating a new csml document |
---|
60 | csmlstring=csmlstring.replace('ns0', 'gml') |
---|
61 | csmlstring=csmlstring.replace('xmlns:ns1', 'xmlns:xlink') |
---|
62 | csmlstring=csmlstring.replace('ns1:href', 'xlink:href') |
---|
63 | csmlstring=csmlstring.replace('ns1:moles', 'xlink:moles') |
---|
64 | csmlstring=csmlstring.replace('ns1:', '') #the rest of the ns1s are CSML namespaces... due to the way it has been parsed. |
---|
65 | return csmlstring |
---|
66 | |
---|
67 | |
---|
68 | class ParserPostProcessor: |
---|
69 | def __init__(self,dataset): |
---|
70 | if isinstance(dataset,Parser.Dataset): |
---|
71 | self.dataset=dataset |
---|
72 | else: |
---|
73 | print 'Error: Could not post-process CSML document' |
---|
74 | sys.exit() |
---|
75 | |
---|
76 | def resolveReferences(self): |
---|
77 | #if there are any phenomenon defintions then |
---|
78 | #for every <parameter> element, need to resolve any hrefs. |
---|
79 | if hasattr(self.dataset, 'phenomenonDefinitions'): |
---|
80 | for feature in self.dataset.featureCollection.members: |
---|
81 | if hasattr(feature, 'parameter'): |
---|
82 | if hasattr(feature.parameter,'href'): |
---|
83 | #search phenomenon definitions for a match. |
---|
84 | for definition in self.dataset.phenomenonDefinitions.definitionMembers: |
---|
85 | if definition.id == feature.parameter.href[1:]: #remove '#' |
---|
86 | #remove href and replace with object |
---|
87 | feature.parameter.href =None |
---|
88 | feature.parameter=definition |
---|
89 | break |
---|
90 | |
---|
91 | #if there are embedded reference system definitions then |
---|
92 | #for every DomainReference and DomainComplement need to resolve any srsNames |
---|
93 | if hasattr(self.dataset, 'referenceSystemDefinitions'): |
---|
94 | for feature in self.dataset.featureCollection.members: |
---|
95 | if hasattr(feature, 'domain'): #Trajectory features don't have domains.. |
---|
96 | if hasattr(feature.domain.domainReference, 'srsName'): |
---|
97 | #search reference definitions for a match. |
---|
98 | for definition in self.dataset.referenceSystemDefinitions.definitionMembers: |
---|
99 | if definition.id == feature.domain.domainReference.srsName[1:]: |
---|
100 | #remove srsName attribute and replace with Object. |
---|
101 | pass #Leave this for now. |
---|
102 | if hasattr(feature.domain, 'domainComplement'): |
---|
103 | if hasattr(feature.domain.domainComplement, 'srsName'): |
---|
104 | #search reference definitions for a match. |
---|
105 | for definition in self.dataset.referenceSystemDefinitions.definitionMembers: |
---|
106 | if definition.id == feature.domain.domainComplement.srsName[1:]: |
---|
107 | #remove srsName attribute and replace with Object. |
---|
108 | pass #Leave this for now. |
---|
109 | |
---|
110 | #NetCDFExtracts etc may be referenced e.g. as <axisvalues> element. Need to fix these too. |
---|
111 | if hasattr(self.dataset, 'arrayDescriptors'): |
---|
112 | for feature in self.dataset.featureCollection.members: |
---|
113 | if hasattr (feature, 'domain'): |
---|
114 | if hasattr(feature.domain, 'domainComplement'): |
---|
115 | if isinstance(feature.domain.domainComplement, Parser.Grid): |
---|
116 | for ordinate in feature.domain.domainComplement.ordinates: |
---|
117 | #search arrayDescriptors for a match. |
---|
118 | for arrayDescriptor in self.dataset.arrayDescriptors: |
---|
119 | if arrayDescriptor.id == ordinate.axisValues[1:]: #remove '#' |
---|
120 | ordinate.axisValues = arrayDescriptor |
---|
121 | break |
---|
122 | |
---|
123 | #uom may reference UnitDefinitions. Replace these too |
---|
124 | if hasattr(self.dataset,'arrayDescriptors'): |
---|
125 | for feature in self.dataset.featureCollection.members: |
---|
126 | if hasattr (feature, 'rangeSet'): |
---|
127 | if hasattr (feature.rangeSet, 'aggregatedArray'): |
---|
128 | if hasattr(feature.rangeSet.aggregatedArray, 'uom'): |
---|
129 | if hasattr(self.dataset, 'unitDefinitions'): |
---|
130 | for definition in self.dataset.unitDefinitions.definitionMembers: |
---|
131 | if definition.id== feature.rangeSet.aggregatedArray.uom[1:]: |
---|
132 | feature.rangeSet.aggregatedArray.uom=definition |
---|
133 | break |
---|
134 | #TODO need to also take into account the fact that UnitDefinitions could be externally defined. |
---|
135 | |
---|
136 | return self.dataset |
---|