def executePost(self): """ Method for executing a POST requests that insert new observations into a SOS procedure .. note:: The POST data shall be in JSON format as following: >>> { "ForceInsert" : "true", "Observation" : { "procedure": "urn:ogc:object:procedure:x-istsos:1.01.0:P_TRE", "AssignedSensorId" : "247df84cf4a0c2ebc632d08318d00cb3", "samplingTime": { "beginPosition": "2012-01-01T13:00:00+01:00", "endPosition": "2012-01-01T17:00:00+01:00" }, "observedProperty": { "CompositePhenomenon": { "id": "comp_126", "dimension": "2" }, "component": [ "urn:ogc:def:parameter:x-istsos:1.01.0:time:iso8601", "urn:ogc:def:parameter:x-istsos:1.0:meteo:air:rainfall" ] }, "featureOfInterest": { "geom": ( "<gml:Point srsName='EPSG:21781'>" "<gml:coordinates>717900,98520,342</gml:coordinates>" "</gml:Point>"), "name": "urn:ogc:object:feature:x-istsos:1.01.0:" "station:Trevano" }, "result": { "DataArray": { "elementCount": "2", "values": [ [ "22012-01-01T14:00:00+01:00", "10.000000" ], [ "2012-01-01T15:00:00+01:00", "20.000000" ] ], "field": [ { "definition": "urn:ogc:def:parameter:x-istsos:" "1.01.0:time:iso8601", "name": "Time" }, { "definition": "urn:ogc:def:parameter:x-istsos:" "1.0:meteo:air:rainfall", "name": "air-rainfall", "uom": "mm" } ] } } } } """ ns = { 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', 'sml': 'http://www.opengis.net/sensorML', 'swe': 'http://www.opengis.net/swe', 'xlink': 'http://www.w3.org/1999/xlink', 'gml': 'http://www.opengis.net/gml', 'sos': 'http://www.opengis.net/sos/1.0', 'sa': 'http://www.opengis.net/sampling/1.0', 'ogc': 'http://www.opengis.net/ogc', 'om': 'http://www.opengis.net/om/1.0' } # map namespaces try: register_namespace = et.register_namespace for key in ns: register_namespace(key, ns[key]) except AttributeError: try: et._namespace_map.update(ns) for key in ns: et._namespace_map[ns[key]] = key except AttributeError: try: from xml.etree.ElementTree import _namespace_map except ImportError: try: from elementtree.ElementTree import _namespace_map except ImportError: traceback.print_exc(file=sys.stderr) for key in ns: _namespace_map[ns[key]] = key #create xml request root = et.Element("{%s}InsertObservation" % ns['sos']) root.attrib["{%s}schemaLocation" % ns['xsi']] = ( "http://schemas.opengis.net/sos/1.0.0/sosAll.xsd") root.attrib["version"] = "1.0.0" root.attrib["service"] = "SOS" AssignedSensorId = et.SubElement(root, "{%s}AssignedSensorId" % ns['sos']) AssignedSensorId.text = self.json["AssignedSensorId"] if "ForceInsert" in self.json: ForceInsert = et.SubElement(root, "{%s}ForceInsert" % ns['sos']) ForceInsert.text = self.json["ForceInsert"] Observation = et.SubElement(root, "{%s}Observation" % ns['om']) procedure = et.SubElement(Observation, "{%s}procedure" % ns['om']) procedure.attrib["{%s}href" % ns['xlink']] = (self.json["Observation"]["procedure"]) samplingTime = et.SubElement(Observation, "{%s}samplingTime" % ns['om']) TimePeriod = et.SubElement(samplingTime, "{%s}TimePeriod" % ns['gml']) beginPosition = et.SubElement(TimePeriod, "{%s}beginPosition" % ns['gml']) beginPosition.text = ( self.json["Observation"]["samplingTime"]["beginPosition"]) endPosition = et.SubElement(TimePeriod, "{%s}endPosition" % ns['gml']) endPosition.text = ( self.json["Observation"]["samplingTime"]["endPosition"]) observedProperty = et.SubElement(Observation, "{%s}observedProperty" % ns['om']) CompositePhenomenon = et.SubElement( observedProperty, "{%s}CompositePhenomenon" % ns['swe']) CompositePhenomenon.attrib["dimension"] = ( self.json["Observation"]["observedProperty"] )["CompositePhenomenon"]["dimension"] for comp in self.json["Observation"]["observedProperty"]["component"]: component = et.SubElement(CompositePhenomenon, "{%s}component" % ns['swe']) component.attrib["{%s}href" % ns['xlink']] = comp featureOfInterest = et.SubElement(Observation, "{%s}featureOfInterest" % ns['om']) featureOfInterest.attrib["{%s}href" % ns['xlink']] = ( self.json["Observation"]["featureOfInterest"]["name"]) result = et.SubElement(Observation, "{%s}result" % ns['om']) DataArray = et.SubElement(result, "{%s}DataArray" % ns['swe']) elementCount = et.SubElement(DataArray, "{%s}elementCount" % ns['swe']) value = et.SubElement(elementCount, "{%s}value" % ns['swe']) value.text = ( self.json["Observation"]["result"]["DataArray"]["elementCount"]) elementType = et.SubElement(DataArray, "{%s}elementType" % ns['swe']) elementType.attrib["name"] = "SimpleDataArray" DataRecord = et.SubElement(elementType, "{%s}DataRecord" % ns['swe']) DataRecord.attrib["definition"] = ( "urn:ogc:def:dataType:x-istsos:1.0:timeSeries") for index, item in enumerate( self.json["Observation"]["result"]["DataArray"]["field"]): field = et.SubElement(DataRecord, "{%s}field" % ns['swe']) field.attrib["name"] = item["name"] if index == 0: Time = et.SubElement(field, "{%s}Time" % ns['swe']) Time.attrib["definition"] = item["definition"] if not item["definition"].find("time") > 0: raise Exception("first element of DataRecord is not of " "type time") else: Quantity = et.SubElement(field, "{%s}Quantity" % ns['swe']) Quantity.attrib["definition"] = item["definition"] if "uom" in item: uom = et.SubElement(Quantity, "{%s}uom" % ns['swe']) uom.attrib["code"] = item["uom"] encoding = et.SubElement(DataArray, "{%s}encoding" % ns['swe']) TextBlock = et.SubElement(encoding, "{%s}TextBlock" % ns['swe']) TextBlock.attrib["tokenSeparator"] = "," TextBlock.attrib["blockSeparator"] = "@" TextBlock.attrib["decimalSeparator"] = "." values = et.SubElement(DataArray, "{%s}values" % ns['swe']) values.text = "@".join([ ",".join(row) for row in ( self.json["Observation"]["result"]["DataArray"]["values"]) ]) # PrettyPrint XML iostring = et.tostring(root, encoding="UTF-8") headers = {"Content-type": "text/xml"} if 'HTTP_AUTHORIZATION' in self.waEnviron: headers['Authorization'] = self.waEnviron['HTTP_AUTHORIZATION'] response = requests.post(self.serviceconf.serviceurl["url"], data=iostring, headers=headers) data = response.text try: response.raise_for_status() if data.find("AssignedObservationId") > 0: self.setMessage("%s" % data) else: self.setException( "Insert observations failed - Communication: %s %s - " "Response: %s" % (response.status_code, e, response.text)) except Exception as e: self.setException( "Insert observations failed - Communication: %s %s - Response:" " %s" % (response.status_code, e, response.text))
def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__(self, sosRequest, method, requestObject, sosConfig) #************************** if method == "GET": raise sosException.SOSException( "NoApplicableCode", None, "registerSensor request support only POST method!") if method == "POST": from StringIO import StringIO tree, ns = parse_and_get_ns(StringIO(requestObject)) #---SensorDescription #---------------------- SensorDescription = tree.find("{%s}SensorDescription" % ns['sos']) if SensorDescription == None: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", "sos:SensorDescription parameter is mandatory with multiplicity 1" ) #---Procedure Name name = tree.find( "{%s}SensorDescription/{%s}member/{%s}System/{%s}name" % (ns['sos'], ns['sml'], ns['sml'], ns['gml'])) self.procedure = name.text #---ProcedureDescription description = tree.find( "{%s}SensorDescription/{%s}member/{%s}System/{%s}description" % (ns['sos'], ns['sml'], ns['sml'], ns['gml'])) if not description == None: self.proc_desc = description.text else: self.proc_desc = 'NULL' # Add capabilities time to db # Convert all to seconds #---Capabilities capabilities = tree.findall( "{%s}SensorDescription/{%s}member/{%s}System/{%s}capabilities/{%s}DataRecord/{%s}field" % (ns['sos'], ns['sml'], ns['sml'], ns['sml'], ns['swe'], ns['swe'])) #print >> sys.stderr, "capabilities: ",capabilities self.time_sam_val = "0" self.time_acq_val = "0" for cap in capabilities: if cap.attrib.has_key('name') and cap.attrib[ 'name'] == 'Sampling time resolution': # parse Sampling time resolution tmpSam = int( cap.find("{%s}Quantity/{%s}value" % (ns['swe'], ns['swe'])).text) uom = cap.find("{%s}Quantity/{%s}uom" % (ns['swe'], ns['swe'])) if uom.attrib.has_key('code'): uomSam = uom.attrib['code'] self.time_sam_val = convertToSec[uomSam]( tmpSam) #convertToSec(uomSam,tmpSam) else: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", "sml:capabilities, missing uom for Sampling time resolution" ) elif cap.attrib.has_key('name') and cap.attrib[ 'name'] == 'Acquisition time resolution': # parse Acquisition time resolution tmpAcq = int( cap.find("{%s}Quantity/{%s}value" % (ns['swe'], ns['swe'])).text) uom = cap.find("{%s}Quantity/{%s}uom" % (ns['swe'], ns['swe'])) if uom.attrib.has_key('code'): uomAcq = uom.attrib['code'] self.time_acq_val = convertToSec[uomAcq]( tmpAcq) #convertToSec(uomAcq,tmpAcq) else: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", "sml:capabilities, missing uom for Sampling time resolution" ) #print >> sys.stderr, self.time_sam_val #---System type # From istSOS 2.0 the system type became mandatory (insitu-fixed-point, insitu-mobile-point, ...) self.systemType = None classifiers = tree.findall( "{%s}SensorDescription/{%s}member/{%s}System/{%s}classification/{%s}ClassifierList/{%s}classifier" % (ns['sos'], ns['sml'], ns['sml'], ns['sml'], ns['sml'], ns['sml'])) for classifier in classifiers: if classifier.attrib.has_key( 'name') and classifier.attrib['name'] == 'System Type': val = classifier.find("{%s}Term/{%s}value" % (ns['sml'], ns['sml'])) if val != None: self.systemType = val.text member = tree.find("{%s}SensorDescription/{%s}member" % (ns['sos'], ns['sml'])) root = et.Element("{%s}SensorML" % ns['sml']) root.attrib["{%s}schemaLocation" % ns[ 'xsi']] = "http://www.opengis.net/sensorML/1.0.1 http://schemas.opengis.net/sensorML/1.0.1/sensorML.xsd" root.attrib["version"] = "1.0.1" root.append(member) self.xmlSensorDescription = root """ from xml.dom.minidom import parseString txt = et.tostring(root, encoding="UTF-8") self.xmlSensorDescription = parseString(txt).toprettyxml() """ #---ObservationTemplate #---------------------- ObservationTemplate = tree.find("{%s}ObservationTemplate" % ns['sos']) if ObservationTemplate == None: raise sosException.SOSException( "MissingParameterValue", "ObservationTemplate", "ObservationTemplate parameter is mandatory with multiplicity 1" ) Observation = ObservationTemplate.find("{%s}Observation" % ns['om']) if Observation == None: raise sosException.SOSException( "NoApplicableCode", None, "om:Observation tag is mandatory with multiplicity 1") #-------procedure procedure = Observation.find("{%s}procedure" % ns['om']) self.procedure = procedure.attrib["{%s}href" % ns['xlink']].split(":")[-1] if procedure == None: raise sosException.SOSException( "NoApplicableCode", None, "om:procedure tag is mandatory with multiplicity 1") #-------ObservedProperties self.oprDef = [] self.oprDesc = [] self.oprName = [] self.beginPosition = 'NULL' try: name = Observation.find( "{%s}observedProperty/{%s}CompositePhenomenon/{%s}name" % (ns['om'], ns['swe'], ns['gml'])) except: raise sosException.SOSException( "NoApplicableCode", None, "swe:CompositePhenomenon mandatory name element is missing" ) components = Observation.findall( "{%s}observedProperty/{%s}CompositePhenomenon/{%s}component" % (ns['om'], ns['swe'], ns['swe'])) if not components == []: for comp in components: try: self.oprDef.append(comp.attrib["{%s}href" % ns['xlink']]) except: raise sosException.SOSException( "NoApplicableCode", None, "om:observedProperty/component attribute missing: 'xlink:href' required" ) """ NON STANDARD try: desc = comp.find("{%s}description" % ns['gml']) self.oprDesc.append(desc.text) except: self.oprDesc.append("NULL") try: desc = comp.find("{%s}name" % ns['gml']) self.oprName.append(desc.text) except: self.oprName.append("NULL") """ """ PER COSA È? CASO NON COMPOSITEPHENOMENON? else: observedProperty = Observation.find("{%s}observedProperty" % ns['om']) try: self.oprName.append(observedProperty.attrib["{%s}href" % ns['xlink']]) except: name = Observation.find("{%s}observedProperty/{%s}name" %(ns['om'],ns['gml']) ) try: self.oprName.append(name.txt) except: raise sosException.SOSException(1, "om:observedProperty Name is missing: 'xlink:href' or 'gml:name' required") desc = Observation.find("{%s}observedProperty/{%s}description" %(ns['om'],ns['gml']) ) try: self.oprDesc.append(desc.txt) except: self.oprDesc.append("NULL") """ #-------samplingTime #============================================================================== # samplingTime = Observation.find("{%s}samplingTime" % ns['om'] ) # if samplingTime == None: # raise sosException.SOSException("NoApplicableCode",None,"om:samplingTime tag is mandatory with multiplicity 1") # else: # duration = samplingTime.find("{%s}TimePeriod/{%s}TimeLength/{%s}duration" # %(ns['gml'],ns['gml'],ns['gml'], ) ) # # if not duration==None: # # strdur = str( parse_duration( duration.text.strip() ) ).split(",") # if len(strdur)>1: # self.time_res_val = strdur[0].split(" ")[0] # self.time_res_unit = strdur[0].split(" ")[1] # elif len(strdur)==1: # time = strdur[0].split(":") # self.time_res_val = parse_duration( duration.text.strip() ).seconds # self.time_res_unit = "sec" # else: # self.time_res_unit = "unknown" # self.time_res_val = "NULL" #============================================================================== #------featureOfInterest featureOfInterest = Observation.find("{%s}featureOfInterest" % ns['om']) if featureOfInterest == None: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest tag is mandatory with multiplicity 1" ) try: self.foiName = featureOfInterest.attrib["{%s}href" % ns['xlink']] except: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest: attribute 'xlink:href' is required") """ NON COMPLIANT name = Observation.find("{%s}featureOfInterest/{%s}name" %(ns['om'],ns['gml']) ) try: self.foiName = name.text except: raise sosException.SOSException(1,"om:featureOfInterest name is missing: 'xlink:href' or 'gml:name' is required") """ description = Observation.find( "{%s}featureOfInterest/{%s}FeatureCollection/{%s}description" % (ns['om'], ns['gml'], ns['gml'])) if not description == None: self.foiDesc = description.text else: self.foiDesc = "NULL" #--foiWKZ # gml_type = ["gml:Polygon", "gml:LineString", "gml:Point", "gml:Box", "gml:GeometryCollection", # "gml:MultiPoint", "gml:MultiLineString", "gml:MultiPolygon"] self.foiType = None for geomtype in sosConfig.foiGeometryType: geomtype = geomtype.split(":")[1] GMLfeature = Observation.find( "{%s}featureOfInterest/{%s}FeatureCollection/{%s}location/{%s}%s" % (ns['om'], ns['gml'], ns['gml'], ns['gml'], geomtype)) if not GMLfeature == None: self.foiType = geomtype self.foiSRS = GMLfeature.attrib["srsName"].split(":")[-1] self.foiGML = et.tostring( GMLfeature, encoding="UTF-8").replace( "<?xml version='1.0' encoding='UTF-8'?>", "") if self.foiType == None: raise sosException.SOSException( "NoApplicableCode", None, "not found valid GML feature, supported: %s " % (";".join(sosConfig.foiGeometryType))) #--result result = Observation.find("{%s}result" % ns['om']) self.parameters = [] self.uoms = [] self.names = [] self.descs = [] self.constr = [] self.partime = [] if not result == None: sdr = Observation.find("{%s}result/{%s}SimpleDataRecord" % (ns['om'], ns['swe'])) da = Observation.find("{%s}result/{%s}DataArray" % (ns['om'], ns['swe'])) if sdr != None and da == None: fields = sdr.findall("{%s}field" % ns['swe']) elif da != None and sdr == None: fields = da.findall( "{%s}elementType/{%s}DataRecord/{%s}field" % (ns['swe'], ns['swe'], ns['swe'])) else: err_txt = "in <swe:result>: <swe:DataRecord> or <swe:DataArray> are mandatory in multiplicity 1" raise sosException.SOSException("NoApplicableCode", None, err_txt) timetag = False for field in fields: defin = None uom = None self.names.append(field.attrib['name']) tf = field.find("{%s}Time" % ns['swe']) qf = field.find("{%s}Quantity" % ns['swe']) if not tf == None and qf == None: self.partime.append(1) timetag = True self.parameters.append(tf.attrib["definition"]) uom = tf.find("{%s}uom" % ns['swe']) self.uoms.append(uom.attrib["code"]) desc = tf.find("{%s}description" % ns['swe']) if not desc == None: self.descs.append(desc.text) else: self.descs.append("NULL") #self.constr.append(None) #self.constr.append("NULL") elif not qf == None and tf == None: self.partime.append(0) self.parameters.append(qf.attrib["definition"]) uom = qf.find("{%s}uom" % ns['swe']) self.uoms.append(uom.attrib["code"]) desc = qf.find("{%s}description" % ns['swe']) if not desc == None: self.descs.append(desc.text) else: self.descs.append("NULL") # look for constraints [min,max,interval,valueList] #=================================================== #import sys cc = {} constraints = qf.findall("{%s}constraint" % (ns['swe'])) if len(constraints) == 0: self.constr.append(None) else: for constraint in constraints: if constraint: if "{%s}role" % ns[ "xlink"] in constraint.attrib: if constraint.attrib["{%s}role" % ns[ "xlink"]] == "urn:ogc:def:classifiers:x-istsos:1.0:qualityIndex:check:reasonable": crole = constraint.attrib[ "{%s}role" % ns["xlink"]] allow = constraint.find( "{%s}AllowedValues" % (ns['swe'])) if allow is None: err_txt = "in <swe:constraint>: <swe:AllowedValues> is mandatory in multiplicity 1" raise sosException.SOSException( "NoApplicableCode", None, err_txt) else: cvals = None if len(allow) == 1: ct = allow[0].tag if not ct in [ "{%s}min" % ns["swe"], "{%s}max" % ns["swe"], "{%s}interval" % ns["swe"], "{%s}valueList" % ns["swe"] ]: err_txt = "in <swe:constraint>: support only min, max, interval, valueList tag" raise sosException.SOSException( "NoApplicableCode", None, err_txt) xvals = allow[ 0].text.strip().split( " ") if ct == "{%s}min" % ns[ "swe"]: ct = "min" if not len(xvals) == 1: err_txt = "'%s' constraint support/need one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = float( xvals[0]) except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}max" % ns[ "swe"]: ct = "max" if not len(xvals) == 1: err_txt = "'%s' constraint support/need one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = float( xvals[0]) except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}interval" % ns[ "swe"]: ct = "interval" if not len(xvals) == 2: err_txt = "'%s' constraint support/need two values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = [ float( xvals[0]), float(xvals[1]) ] except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}valueList" % ns[ "swe"]: ct = "valueList" if not len(xvals) > 0: err_txt = "'%s' constraint support/need at least one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = [ float(a) for a in xvals ] except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) cc["role"] = crole cc["%s" % ct] = cvals if not cc == {}: self.constr.append(json.dumps(cc)) else: self.constr.append(None) else: err_txt = "swe:Time or swe:Quantity is mandatory in multiplicity 1:N" raise sosException.SOSException( "NoApplicableCode", None, err_txt) else: err_txt = "om:result is mandatory in multiplicity 1:N" raise sosException.SOSException("NoApplicableCode", None, err_txt) #case simple om:result """ WAS elif len(sdr)==0 and len(da)==0: if len(observedProperties)==1: self.parameters.append(observedProperties[0]) self.uoms.append(getElemAtt(res[0],"uom")) else: raise sosException.SOSException(1,"om:observedProperty is mandatory with multiplicity 1") else: err_txt = "om:observation ERROR" raise sosException.SOSException(1,err_txt) """ """
def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__(self, sosRequest, method, requestObject, sosConfig) if method == "GET": raise sosException.SOSException( "NoApplicableCode", None, "registerSensor request support only POST method!") if method == "POST": from StringIO import StringIO tree, ns = parse_and_get_ns(StringIO(requestObject)) SensorDescription = tree.find("{%s}SensorDescription" % ns['sos']) if SensorDescription is None: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", ("sos:SensorDescription parameter is " "mandatory with multiplicity 1")) name = tree.find( "{%s}SensorDescription/{%s}member/{%s}System/{%s}name" % (ns['sos'], ns['sml'], ns['sml'], ns['gml'])) self.procedure = name.text description = tree.find( "{%s}SensorDescription/{%s}member/{%s}System/{%s}description" % (ns['sos'], ns['sml'], ns['sml'], ns['gml'])) if not description is None: self.proc_desc = description.text else: self.proc_desc = 'NULL' #---Capabilities capabilities = tree.findall( "{%s}SensorDescription/{%s}member/{%s}System/" "{%s}capabilities/{%s}DataRecord/{%s}field" % (ns['sos'], ns['sml'], ns['sml'], ns['sml'], ns['swe'], ns['swe'])) self.time_sam_val = "0" self.time_acq_val = "0" for cap in capabilities: if ('name' in cap.attrib and cap.attrib['name'] == 'Sampling time resolution'): tmpSam = int( cap.find("{%s}Quantity/{%s}value" % (ns['swe'], ns['swe'])).text) uom = cap.find("{%s}Quantity/{%s}uom" % (ns['swe'], ns['swe'])) if 'code' in uom.attrib: uomSam = uom.attrib['code'] self.time_sam_val = convertToSec[uomSam](tmpSam) else: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", ("sml:capabilities, missing uom for " "Sampling time resolution")) elif ('name' in cap.attrib and cap.attrib['name'] == 'Acquisition time resolution'): tmpAcq = int( cap.find("{%s}Quantity/{%s}value" % (ns['swe'], ns['swe'])).text) uom = cap.find("{%s}Quantity/{%s}uom" % (ns['swe'], ns['swe'])) if 'code' in uom.attrib: uomAcq = uom.attrib['code'] self.time_acq_val = convertToSec[uomAcq](tmpAcq) else: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", ("sml:capabilities, missing uom " "for Sampling time resolution")) self.systemType = None classifiers = tree.findall( "{%s}SensorDescription/{%s}member/{%s}System/" "{%s}classification/{%s}ClassifierList/{%s}classifier" % (ns['sos'], ns['sml'], ns['sml'], ns['sml'], ns['sml'], ns['sml'])) for classifier in classifiers: if ('name' in classifier.attrib and classifier.attrib['name'] == 'System Type'): val = classifier.find("{%s}Term/{%s}value" % (ns['sml'], ns['sml'])) if val is not None: self.systemType = val.text member = tree.find("{%s}SensorDescription/{%s}member" % (ns['sos'], ns['sml'])) root = et.Element("{%s}SensorML" % ns['sml']) root.attrib["{%s}schemaLocation" % ns['xsi']] = ( "http://www.opengis.net/sensorML/1.0.1 " "http://schemas.opengis.net/sensorML/1.0.1/sensorML.xsd") root.attrib["version"] = "1.0.1" root.append(member) self.xmlSensorDescription = root """ from xml.dom.minidom import parseString txt = et.tostring(root, encoding="UTF-8") self.xmlSensorDescription = parseString(txt).toprettyxml() """ ObservationTemplate = tree.find("{%s}ObservationTemplate" % ns['sos']) if ObservationTemplate is None: raise sosException.SOSException( "MissingParameterValue", "ObservationTemplate", ("ObservationTemplate parameter is " "mandatory with multiplicity 1")) Observation = ObservationTemplate.find("{%s}Observation" % ns['om']) if Observation is None: raise sosException.SOSException( "NoApplicableCode", None, "om:Observation tag is mandatory with multiplicity 1") procedure = Observation.find("{%s}procedure" % ns['om']) self.procedure = procedure.attrib["{%s}href" % ns['xlink']].split(":")[-1] if procedure is None: raise sosException.SOSException( "NoApplicableCode", None, "om:procedure tag is mandatory with multiplicity 1") self.oprDef = [] self.oprDesc = [] self.oprName = [] self.beginPosition = 'NULL' try: name = Observation.find( "{%s}observedProperty/{%s}CompositePhenomenon/{%s}name" % (ns['om'], ns['swe'], ns['gml'])) except: raise sosException.SOSException( "NoApplicableCode", None, "swe:CompositePhenomenon mandatory name element is missing" ) components = Observation.findall( "{%s}observedProperty/{%s}CompositePhenomenon/{%s}component" % (ns['om'], ns['swe'], ns['swe'])) if not components == []: for comp in components: try: self.oprDef.append(comp.attrib["{%s}href" % ns['xlink']]) except: raise sosException.SOSException( "NoApplicableCode", None, ("om:observedProperty/component attribute " "missing: 'xlink:href' required")) featureOfInterest = Observation.find("{%s}featureOfInterest" % ns['om']) if featureOfInterest is None: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest tag is mandatory with multiplicity 1" ) try: self.foiName = featureOfInterest.attrib["{%s}href" % ns['xlink']] except: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest: attribute 'xlink:href' is required") description = Observation.find( "{%s}featureOfInterest/{%s}FeatureCollection/{%s}description" % (ns['om'], ns['gml'], ns['gml'])) if not description is None: self.foiDesc = description.text else: self.foiDesc = "NULL" self.foiType = None for geomtype in sosConfig.foiGeometryType: geomtype = geomtype.split(":")[1] GMLfeature = Observation.find( "{%s}featureOfInterest/{%s}FeatureCollection/" "{%s}location/{%s}%s" % (ns['om'], ns['gml'], ns['gml'], ns['gml'], geomtype)) if not GMLfeature is None: self.foiType = geomtype self.foiSRS = GMLfeature.attrib["srsName"].split(":")[-1] self.foiGML = et.tostring( GMLfeature, encoding="UTF-8").replace( "<?xml version='1.0' encoding='UTF-8'?>", "") if self.foiType is None: raise sosException.SOSException( "NoApplicableCode", None, "not found valid GML feature, supported: %s " % (";".join(sosConfig.foiGeometryType))) result = Observation.find("{%s}result" % ns['om']) self.parameters = [] self.uoms = [] self.names = [] self.descs = [] self.constr = [] self.partime = [] if not result is None: sdr = Observation.find("{%s}result/{%s}SimpleDataRecord" % (ns['om'], ns['swe'])) da = Observation.find("{%s}result/{%s}DataArray" % (ns['om'], ns['swe'])) if sdr is not None and da is None: fields = sdr.findall("{%s}field" % ns['swe']) elif da is not None and sdr is None: fields = da.findall( "{%s}elementType/{%s}DataRecord/{%s}field" % (ns['swe'], ns['swe'], ns['swe'])) else: err_txt = ( "in <swe:result>: <swe:DataRecord> or " "<swe:DataArray> are mandatory in multiplicity 1") raise sosException.SOSException("NoApplicableCode", None, err_txt) timetag = False for field in fields: defin = None uom = None self.names.append(field.attrib['name']) tf = field.find("{%s}Time" % ns['swe']) qf = field.find("{%s}Quantity" % ns['swe']) if not tf is None and qf is None: self.partime.append(1) timetag = True self.parameters.append(tf.attrib["definition"]) uom = tf.find("{%s}uom" % ns['swe']) self.uoms.append(uom.attrib["code"]) desc = tf.find("{%s}description" % ns['swe']) if not desc is None: self.descs.append(desc.text) else: self.descs.append("NULL") elif not qf is None and tf is None: self.partime.append(0) self.parameters.append(qf.attrib["definition"]) uom = qf.find("{%s}uom" % ns['swe']) self.uoms.append(uom.attrib["code"]) desc = qf.find("{%s}description" % ns['swe']) if not desc is None: self.descs.append(desc.text) else: self.descs.append("NULL") cc = {} constraints = qf.findall("{%s}constraint" % (ns['swe'])) if len(constraints) == 0: self.constr.append(None) else: for constraint in constraints: if (constraint and "{%s}role" % ns["xlink"] in constraint.attrib): if constraint.attrib["{%s}role" % ns[ "xlink"]] == "urn:ogc:def:classifiers:x-istsos:1.0:qualityIndex:check:reasonable": crole = constraint.attrib["{%s}role" % ns["xlink"]] allow = constraint.find( "{%s}AllowedValues" % (ns['swe'])) if allow is None: err_txt = "in <swe:constraint>: <swe:AllowedValues> is mandatory in multiplicity 1" raise sosException.SOSException( "NoApplicableCode", None, err_txt) else: cvals = None if len(allow) == 1: ct = allow[0].tag if not ct in [ "{%s}min" % ns["swe"], "{%s}max" % ns["swe"], "{%s}interval" % ns["swe"], "{%s}valueList" % ns["swe"] ]: err_txt = "in <swe:constraint>: support only min, max, interval, valueList tag" raise sosException.SOSException( "NoApplicableCode", None, err_txt) xvals = allow[0].text.strip( ).split(" ") if ct == "{%s}min" % ns["swe"]: ct = "min" if not len(xvals) == 1: err_txt = "'%s' constraint support/need one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = float(xvals[0]) except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}max" % ns[ "swe"]: ct = "max" if not len(xvals) == 1: err_txt = "'%s' constraint support/need one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = float(xvals[0]) except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}interval" % ns[ "swe"]: ct = "interval" if not len(xvals) == 2: err_txt = "'%s' constraint support/need two values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = [ float(xvals[0]), float(xvals[1]) ] except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}valueList" % ns[ "swe"]: ct = "valueList" if not len(xvals) > 0: err_txt = "'%s' constraint support/need at least one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = [ float(a) for a in xvals ] except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) cc["role"] = crole cc["%s" % ct] = cvals if not cc == {}: self.constr.append(json.dumps(cc)) else: self.constr.append(None) else: err_txt = ("swe:Time or swe:Quantity is mandatory " "in multiplicity 1:N") raise sosException.SOSException( "NoApplicableCode", None, err_txt) else: err_txt = "om:result is mandatory in multiplicity 1:N" raise sosException.SOSException("NoApplicableCode", None, err_txt)
def toRegisterSensorDom(self, indent=False): """ Create a SOS register sensor request DOM element from self.procedure object """ import sys ns = { 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', 'sml': 'http://www.opengis.net/sensorML/1.0.1', 'swe': "http://www.opengis.net/swe/1.0.1", 'xlink': "http://www.w3.org/1999/xlink", 'gml': 'http://www.opengis.net/gml', 'sos': "http://www.opengis.net/sos/1.0", 'ogc': "http://www.opengis.net/ogc", 'om': "http://www.opengis.net/om/1.0", } #---map namespaces--- try: register_namespace = et.register_namespace for key in ns: register_namespace(key, ns[key]) except AttributeError: try: et._namespace_map.update(ns) for key in ns: et._namespace_map[ns[key]] = key except AttributeError: try: from xml.etree.ElementTree import _namespace_map except ImportError: try: from elementtree.ElementTree import _namespace_map except ImportError: print >> sys.stderr, ( "Failed to import ElementTree from any known place" ) for key in ns: _namespace_map[ns[key]] = key #---start creating XML ---- root = et.Element("{%s}RegisterSensor" % ns['sos']) root.attrib["{%s}schemaLocation" % ns[ 'xsi']] = "http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd" root.attrib["version"] = "1.0.0" root.attrib["service"] = "SOS" SensorDescription = et.SubElement(root, "{%s}SensorDescription" % ns['sos']) sml = self.toXML() #print >> sys.stderr, "SML:%s" % sml from StringIO import StringIO smltree, smlns = parse_and_get_ns(StringIO(sml)) member = smltree.find("{%s}member" % ns['sml']) SensorDescription.append(member) #--- ObservationTemplate = et.SubElement( root, "{%s}ObservationTemplate" % ns['sos']) Observation = et.SubElement(ObservationTemplate, "{%s}Observation" % ns['om']) procedure = et.SubElement(Observation, "{%s}procedure" % ns['om']) procedure.attrib["{%s}href" % ns[ 'xlink']] = "urn:ogc:object:procedure:x-istsos:1.0:" + self.data[ "system"] samplingTime = et.SubElement(Observation, "{%s}samplingTime" % ns['om']) TimePeriod = et.SubElement(samplingTime, "{%s}TimePeriod" % ns['gml']) beginPosition = et.SubElement(TimePeriod, "{%s}beginPosition" % ns['gml']) endPosition = et.SubElement(TimePeriod, "{%s}endPosition" % ns['gml']) observedProperty = et.SubElement(Observation, "{%s}observedProperty" % ns['om']) CompositePhenomenon = et.SubElement( observedProperty, "{%s}CompositePhenomenon" % ns['swe']) CompositePhenomenon.attrib["{%s}id" % ns['gml']] = str("comp_XXX") CompositePhenomenon.attrib["dimension"] = str(len( self.data["outputs"])) name = et.SubElement(CompositePhenomenon, "{%s}name" % ns['gml']) name.text = "timeSeriesOfObservations" for o in self.data["outputs"]: component = et.SubElement(CompositePhenomenon, "{%s}component" % ns['swe']) component.attrib["{%s}href" % ns['xlink']] = o["definition"] featureOfInterest = et.SubElement(Observation, "{%s}featureOfInterest" % ns['om']) featureOfInterest.attrib[ "{%s}href" % ns['xlink']] = self.data["location"]["properties"]["name"] FeatureCollection = et.SubElement(featureOfInterest, "{%s}FeatureCollection" % ns['gml']) #FeatureCollection = et.SubElement(featureOfInterest, "{%s}FeatureCollection" % ns['gml']) location = et.SubElement(FeatureCollection, "{%s}location" % ns['gml']) Point = et.SubElement(location, "{%s}Point" % ns['gml']) Point.attrib["{%s}id" % ns['gml']] = "gmlfoi_" + self.data["location"][ "properties"]["name"] Point.attrib["srsName"] = self.data["location"]["crs"]["properties"][ "name"] if "EPSG:" in self.data["location"]["crs"]["properties"][ "name"] else "EPSG:%s" % self.data["location"]["crs"][ "properties"]["name"] coordinates = et.SubElement(Point, "{%s}coordinates" % ns['gml']) coordinates.text = ",".join( [str(a) for a in self.data["location"]["geometry"]["coordinates"]]) result = et.SubElement(Observation, "{%s}result" % ns['om']) DataArray = et.SubElement(result, "{%s}DataArray" % ns['swe']) elementCount = et.SubElement(DataArray, "{%s}elementCount" % ns['swe']) count = et.SubElement(elementCount, "{%s}count" % ns['swe']) value = et.SubElement(count, "{%s}value" % ns['swe']) value.text = str(len(self.data["outputs"])) elementType = et.SubElement(DataArray, "{%s}elementType" % ns['swe']) elementType.attrib["name"] = "SimpleDataArray" elementType.attrib["{%s}href" % ns[ 'xlink']] = "urn:ogc:def:dataType:x-istsos:1.0:timeSeriesDataRecord" DataRecord = smltree.find( "{%s}member/{%s}System/{%s}outputs/{%s}OutputList/{%s}output/{%s}DataRecord" % (ns['sml'], ns['sml'], ns['sml'], ns['sml'], ns['sml'], ns['swe'])) elementType.append(DataRecord) encoding = et.SubElement(DataArray, "{%s}encoding" % ns['swe']) TextBlock = et.SubElement(encoding, "{%s}TextBlock" % ns['swe']) TextBlock.attrib["tokenSeparator"] = "," TextBlock.attrib["blockSeparator"] = "@" TextBlock.attrib["decimalSeparator"] = "." #values = et.SubElement(DataArray, "{%s}values" % ns['swe']) return root
def toXML(self, indent=False): """ Return the SensorML that represent the self.data object as L{string} """ import sys ns = { 'xsi': "http://www.w3.org/2001/XMLSchema-instance", 'sml': "http://www.opengis.net/sensorML/1.0.1", 'swe': "http://www.opengis.net/swe/1.0.1", 'xlink': "http://www.w3.org/1999/xlink", 'gml': 'http://www.opengis.net/gml' } #---map namespaces--- try: register_namespace = et.register_namespace for key in ns: register_namespace(key, ns[key]) except AttributeError: try: et._namespace_map.update(ns) for key in ns: et._namespace_map[ns[key]] = key except AttributeError: try: from xml.etree.ElementTree import _namespace_map except ImportError: try: from elementtree.ElementTree import _namespace_map except ImportError: print >> sys.stderr, ( "Failed to import ElementTree from any known place" ) for key in ns: _namespace_map[ns[key]] = key root = et.Element("{%s}SensorML" % ns['sml']) root.attrib["{%s}schemaLocation" % ns[ 'xsi']] = "http://www.opengis.net/sensorML/1.0.1 http://schemas.opengis.net/sensorML/1.0.1/sensorML.xsd" root.attrib["version"] = "1.0" member = et.SubElement(root, "{%s}member" % ns['sml']) system = et.SubElement(member, "{%s}System" % ns['sml']) system.attrib["{%s}id" % ns['gml']] = self.data["system_id"] #--- System Description system.append(et.Comment("System Description")) if ("keywords" in self.data) and (not self.data["description"] == ""): desc = et.SubElement(system, "{%s}description" % ns['gml']) desc.text = self.data["description"] name = et.SubElement(system, "{%s}name" % ns['gml']) name.text = self.data["system"] #--- System Search Keywords if ("keywords" in self.data) and (not self.data["keywords"] == ""): system.append(et.Comment("System Search Keywords")) keys = et.SubElement(system, "{%s}keywords" % ns['sml']) keylist = et.SubElement(keys, "{%s}KeywordList" % ns['sml']) for k in self.data["keywords"].split(","): key = et.SubElement(keylist, "{%s}keyword" % ns['sml']) key.text = k #--- System Identifiers if ("identification" in self.data) and (not self.data["identification"] == []): system.append(et.Comment("System Identifiers")) identification = et.SubElement(system, "{%s}identification" % ns['sml']) IdentifierList = et.SubElement(identification, "{%s}IdentifierList" % ns['sml']) uniqueidPresent = False for i in self.data["identification"]: if i["definition"] == 'urn:ogc:def:identifier:OGC:uniqueID': uniqueidPresent = True identifier = et.SubElement(IdentifierList, "{%s}identifier" % ns['sml']) identifier.attrib["name"] = i["name"] term = et.SubElement(identifier, "{%s}Term" % ns['sml']) term.attrib["definition"] = i["definition"] value = et.SubElement(term, "{%s}value" % ns['sml']) value.text = i["value"] if not uniqueidPresent: raise Exception( "self.data['identification']: 'uniqueID' is mandatory") #--- System Classifiers system.append(et.Comment("System Classifiers")) classification = et.SubElement(system, "{%s}classification" % ns['sml']) ClassifierList = et.SubElement(classification, "{%s}ClassifierList" % ns['sml']) for c in self.data["classification"]: classifier = et.SubElement(ClassifierList, "{%s}classifier" % ns['sml']) classifier.attrib["name"] = c["name"] term = et.SubElement(classifier, "{%s}Term" % ns['sml']) term.attrib["definition"] = c["definition"] value = et.SubElement(term, "{%s}value" % ns['sml']) value.text = c["value"] if c["name"] == "System Type": systype = True elif c["name"] == "Sensor Type": senstype = True if not systype == True and senstype == True: raise Exception( "self.data['classification']: 'System Type' and 'Sensor Type' are mandatory" ) #--- System Characteristics if ("characteristics" in self.data) and (not self.data["characteristics"] == ""): system.append(et.Comment("System Characteristics")) characteristics = et.SubElement(system, "{%s}characteristics" % ns['sml']) characteristics.attrib["{%s}href" % ns['xlink']] = self.data["characteristics"] #--- System Capabilities system.append(et.Comment("System Capabilities")) capabilities = et.SubElement(system, "{%s}capabilities" % ns['sml']) DataRecord = et.SubElement(capabilities, "{%s}DataRecord" % ns['swe']) stres = False atres = False for f in self.data["capabilities"]: field = et.SubElement(DataRecord, "{%s}field" % ns['swe']) field.attrib["name"] = f["name"] Quantity = et.SubElement(field, "{%s}Quantity" % ns['swe']) Quantity.attrib["definition"] = f["definition"] if "uom" in f and "value" in f: uom = et.SubElement(Quantity, "{%s}uom" % ns['swe']) uom.attrib["code"] = f["uom"] value = et.SubElement(Quantity, "{%s}value" % ns['swe']) value.text = f["value"] if c["name"] == "Sampling time resolution": stres = True elif c["name"] == "Acquisition time resolution": atres = True if not stres == True and atres == True: raise Exception( "self.data['capabilities']: 'Sampling time resolution' and 'Acquisition time resolution' are mandatory" ) #--- Relevant Contacts if ("contacts" in self.data) and (not self.data["contacts"] == []): system.append(et.Comment("Relevant Contacts")) for c in self.data["contacts"]: contact = et.SubElement(system, "{%s}contact" % ns['sml']) contact.attrib["{%s}role" % ns['xlink']] = c["role"] ResponsibleParty = et.SubElement( contact, "{%s}ResponsibleParty" % ns['sml']) if not c["individualName"] == "": individualName = et.SubElement( ResponsibleParty, "{%s}individualName" % ns['sml']) individualName.text = c["individualName"] organizationName = et.SubElement( ResponsibleParty, "{%s}organizationName" % ns['sml']) organizationName.text = c["organizationName"] phonetag = not c["voice"] == c["fax"] == "" addresstag = not c["deliveryPoint"] == c["city"] == c[ "administrativeArea"] == c["postalcode"] == c[ "country"] == c["email"] == "" onlineResourcetag = not c["web"] == "" if not phonetag == addresstag == onlineResourcetag == False: contactInfo = et.SubElement(ResponsibleParty, "{%s}contactInfo" % ns['sml']) if not phonetag == False: phone = et.SubElement(contactInfo, "{%s}phone" % ns['sml']) if not c["voice"] == "": voice = et.SubElement(phone, "{%s}voice" % ns['sml']) voice.text = c["voice"] if not c["fax"] == "": facsimile = et.SubElement( phone, "{%s}facsimile" % ns['sml']) facsimile.text = c["fax"] if not addresstag == False: address = et.SubElement(contactInfo, "{%s}address" % ns['sml']) if not c["deliveryPoint"] == "": deliveryPoint = et.SubElement( address, "{%s}deliveryPoint" % ns['sml']) deliveryPoint.text = c["deliveryPoint"] if not c["city"] == "": city = et.SubElement(address, "{%s}city" % ns['sml']) city.text = c["city"] if not c["administrativeArea"] == "": administrativeArea = et.SubElement( address, "{%s}administrativeArea" % ns['sml']) administrativeArea.text = c["administrativeArea"] if not c["postalcode"] == "": postalCode = et.SubElement( address, "{%s}postalCode" % ns['sml']) postalCode.text = c["postalcode"] if not c["country"] == "": country = et.SubElement(address, "{%s}country" % ns['sml']) country.text = c["country"] if not c["email"] == "": electronicMailAddress = et.SubElement( address, "{%s}electronicMailAddress" % ns['sml']) electronicMailAddress.text = c["email"] if not onlineResourcetag == False: onlineResource = et.SubElement( contactInfo, "{%s}onlineResource" % ns['sml']) onlineResource.attrib["{%s}href" % ns['xlink']] = c["web"] #--- System Documentation if ("documentation" in self.data) and (not self.data["documentation"] == []): system.append(et.Comment("System Documentation")) for d in self.data["documentation"]: documentation = et.SubElement(system, "{%s}documentation" % ns['sml']) Document = et.SubElement(documentation, "{%s}Document" % ns['sml']) description = et.SubElement(Document, "{%s}description" % ns['gml']) description.text = d["description"] if not d["date"] == "": date = et.SubElement(Document, "{%s}date" % ns['sml']) date.text = d["date"] if not d["format"] == "": format = et.SubElement(Document, "{%s}format" % ns['sml']) format.text = d["format"] onlineResource = et.SubElement( Document, "{%s}onlineResource" % ns['sml']) onlineResource.attrib["{%s}href" % ns['xlink']] = d["link"] #--- System Location system.append(et.Comment("System Location")) location = et.SubElement(system, "{%s}location" % ns['sml']) for item in self.data["classification"]: if item["name"] == "System Type": if item["value"].find("mobile") > 0: location.attrib["{%s}role" % ns[ 'xlink']] = "urn:ogc:def:dataType:x-istsos:1.0:lastPosition" Point = et.SubElement(location, "{%s}Point" % ns['gml']) if ut.valid_NCName(self.data["location"]["properties"]["name"]): Point.attrib[ "{%s}id" % ns['gml']] = self.data["location"]["properties"]["name"] else: raise Exception( "Invalid location name '%s' (gml:id only allows alphanumeric characters)" % self.data["location"]["properties"]["name"]) Point.attrib["srsName"] = "EPSG:" + str( self.data["location"]["crs"]["properties"]["name"]) coordinates = et.SubElement(Point, "{%s}coordinates" % ns['gml']) coordinates.text = ",".join( [str(a) for a in self.data["location"]["geometry"]["coordinates"]]) #--- System Interfaces if ("interfaces" in self.data) and (not self.data["interfaces"] == ""): system.append(et.Comment("System Interfaces")) interfaces = et.SubElement(system, "{%s}interfaces" % ns['sml']) InterfaceList = et.SubElement(interfaces, "{%s}InterfaceList" % ns['sml']) for i in self.data["interfaces"].split(","): interface = et.SubElement(InterfaceList, "{%s}interface" % ns['sml']) interface.attrib["name"] = i #--- System Inputs # Not yet supported in waAdmin !! if ("inputs" in self.data) and (not self.data["inputs"] == []): system.append(et.Comment("System Inputs")) inputs = et.SubElement(system, "{%s}inputs" % ns['sml']) InputList = et.SubElement(inputs, "{%s}InputList" % ns['sml']) for inp in self.data["inputs"]: inputml = et.SubElement(InputList, "{%s}input" % ns['sml']) inputml.attrib["name"] = inp["name"] Quantity = et.SubElement(inputml, "{%s}Quantity" % ns['swe']) Quantity.attrib["definition"] = inp["definition"] if not inp["description"] == "": description = et.SubElement(Quantity, "{%s}description" % ns['gml']) description.text = inp["description"] #--- System Outputs timetag = False system.append(et.Comment("System Outputs")) outputs = et.SubElement(system, "{%s}outputs" % ns['sml']) OutputList = et.SubElement(outputs, "{%s}OutputList" % ns['sml']) output = et.SubElement(OutputList, "{%s}output" % ns['sml']) output.attrib["name"] = "output data" DataRecord = et.SubElement(output, "{%s}DataRecord" % ns['swe']) DataRecord.attrib[ "definition"] = "urn:ogc:def:dataType:x-istsos:1.0:timeSeries" oid = 0 for o in self.data["outputs"]: oid += 1 field = et.SubElement(DataRecord, "{%s}field" % ns['swe']) field.attrib["name"] = o["name"] if o["name"] == "Time": timetag = True item = et.SubElement(field, "{%s}Time" % ns['swe']) item.attrib["{%s}id" % ns['gml']] = "IDT_" + str(oid) item.attrib["definition"] = o["definition"] if not o["description"] == "": description = et.SubElement(item, "{%s}description" % ns['gml']) description.text = o["description"] uom = et.SubElement(item, "{%s}uom" % ns['swe']) uom.attrib["code"] = o["uom"] # The constraint object is not mandatory if "constraint" in o and o[ "constraint"] != {}: # and o["constraint"]["role"]!="" and o["constraint"]["role"]!=None: constraint = et.SubElement(item, "{%s}constraint" % ns['swe']) # Role attribute is not mandatory if "role" in o["constraint"] and o["constraint"][ "role"] != "" and o["constraint"]["role"] != None: constraint.attrib[ "{%s}role" % ns['xlink']] = o["constraint"]["role"] AllowedTimes = et.SubElement( constraint, "{%s}AllowedTimes" % ns['swe']) interval = et.SubElement(AllowedTimes, "{%s}interval" % ns['swe']) interval.text = " ".join( [str(a) for a in o["constraint"]["interval"]]) else: item = et.SubElement(field, "{%s}Quantity" % ns['swe']) item.attrib["{%s}id" % ns['gml']] = "IDQ_" + str(oid) item.attrib["definition"] = o["definition"] if not o["description"] == "": description = et.SubElement(item, "{%s}description" % ns['gml']) description.text = o["description"] uom = et.SubElement(item, "{%s}uom" % ns['swe']) uom.attrib["code"] = o["uom"] # The constraint object is not mandatory if "constraint" in o and o[ "constraint"] != {}: # and o["constraint"]["role"]!="" and o["constraint"]["role"]!=None: #print >> sys.stderr, o['constraint'] try: ut.validateJsonConstraint(o['constraint']) except Exception as ex: raise Exception( "Constraint for observed property '%s' is not valid: %s" % (o["definition"], ex)) constraint = et.SubElement(item, "{%s}constraint" % ns['swe']) # Role attribute is not mandatory if "role" in o["constraint"] and o["constraint"][ "role"] != "" and o["constraint"]["role"] != None: constraint.attrib[ "{%s}role" % ns['xlink']] = o["constraint"]["role"] AllowedValues = et.SubElement( constraint, "{%s}AllowedValues" % ns['swe']) # Factory on constraint min/max/interval/valuelist if "interval" in o["constraint"]: interval = et.SubElement(AllowedValues, "{%s}interval" % ns['swe']) interval.text = " ".join( [str(a) for a in o["constraint"]["interval"]]) elif "valueList" in o[ "constraint"]: #.has_key("valueList"): valueList = et.SubElement(AllowedValues, "{%s}valueList" % ns['swe']) valueList.text = " ".join( [str(a) for a in o["constraint"]["valueList"]]) elif "min" in o["constraint"]: #.has_key("min"): amin = et.SubElement(AllowedValues, "{%s}min" % ns['swe']) amin.text = str(o["constraint"]["min"]) elif "max" in o["constraint"]: #.has_key("max"): amax = et.SubElement(AllowedValues, "{%s}max" % ns['swe']) amax.text = str(o["constraint"]["max"]) if timetag == False: raise Exception("self.data['outputs']: Time is mandatory") #--- System History if ("history" in self.data) and (not self.data["history"] == []): system.append(et.Comment("System History")) history = et.SubElement(system, "{%s}history" % ns['sml']) EventList = et.SubElement(history, "{%s}EventList" % ns['sml']) for h in self.data["history"]: member = et.SubElement(EventList, "{%s}member" % ns['sml']) member.attrib["name"] = h["type"] Event = et.SubElement(member, "{%s}Event" % ns['sml']) date = et.SubElement(Event, "{%s}date" % ns['sml']) date.text = h["date"] if not h["description"] == "": description = et.SubElement(Event, "{%s}description" % ns['gml']) description.text = h["description"] contact = et.SubElement(Event, "{%s}contact" % ns['sml']) contact.attrib["{%s}href" % ns['xlink']] = h["reference"]["username"] contact.attrib["{%s}arcrole" % ns['xlink']] = h["reference"]["role"] return et.tostring(root, encoding="UTF-8")
def render(DS,sosConfig): # Returning content of the SensorML try: #---parse xml tree, ns = parse_and_get_ns(DS.smlFile) except Exception as ex: raise Exception("sensorML description for procedure '%s' not found or corrupted! [%s]"%(DS.smlFile,ex)) #---map namespaces--- try: register_namespace = et.register_namespace for key in ns: register_namespace(key,ns[key]) except AttributeError: try: et._namespace_map.update(ns) for key in ns: et._namespace_map[ns[key]] = key except AttributeError: try: from xml.etree.ElementTree import _namespace_map except ImportError: try: from elementtree.ElementTree import _namespace_map except ImportError: print >> sys.stderr, ("Failed to import ElementTree from any known place") for key in ns: _namespace_map[ns[key]] = key mns = { 'xsi': "http://www.w3.org/2001/XMLSchema-instance" , 'sml': "http://www.opengis.net/sensorML/1.0.1", 'swe': "http://www.opengis.net/swe/1.0.1", 'xlink': "http://www.w3.org/1999/xlink", 'gml': 'http://www.opengis.net/gml' } for n in mns.keys(): try: ns[n] except: ns[n] = mns[n] #--- CREEATE FIELDS ACCORDING TO DATABASE OBSERVED_PROPERTIES datarecord = tree.find("{%s}member/{%s}System/{%s}outputs/{%s}OutputList/{%s}output/{%s}DataRecord" %(ns['sml'],ns['sml'],ns['sml'],ns['sml'],ns['sml'],ns['swe']) ) datarecord.clear() datarecord.attrib["definition"] = "%stimeSeries" % (sosConfig.urn['dataType']) fieldT = et.SubElement(datarecord,"{%s}field" % ns["swe"]) fieldT.attrib["name"] = "Time" time = et.SubElement(fieldT,"{%s}Time" % ns["swe"]) time.attrib["definition"] = sosConfig.urn["time"] # Adding constraint for current allowed times if (not DS.stime == None) and (not DS.etime == None): constraint = et.SubElement(time, "{%s}constraint" % ns['swe']) allowedTimes = et.SubElement(constraint, "{%s}AllowedTimes" % ns['swe']) interval = et.SubElement(allowedTimes, "{%s}interval" % ns['swe']) interval.text = "%s %s" %(DS.stime.strftime("%Y-%m-%dT%H:%M:%S.%fZ"), DS.etime.strftime("%Y-%m-%dT%H:%M:%S.%fZ")) if DS.procedureType=="insitu-mobile-point": # Adding 3d coordinates observation cord = et.SubElement(datarecord,"{%s}field" % ns["swe"]) cord.attrib["name"] = "x" quantity = et.SubElement(cord,"{%s}Quantity" % ns["swe"]) quantity.attrib["definition"] = sosConfig.urn["refsystem"] + sosConfig.istsosepsg + ":x-position" cord = et.SubElement(datarecord,"{%s}field" % ns["swe"]) cord.attrib["name"] = "y" quantity = et.SubElement(cord,"{%s}Quantity" % ns["swe"]) quantity.attrib["definition"] = sosConfig.urn["refsystem"] + sosConfig.istsosepsg + ":y-position" cord = et.SubElement(datarecord,"{%s}field" % ns["swe"]) cord.attrib["name"] = "z" quantity = et.SubElement(cord,"{%s}Quantity" % ns["swe"]) quantity.attrib["definition"] = sosConfig.urn["refsystem"] + sosConfig.istsosepsg + ":z-position" for index, field in enumerate(DS.observedProperties): fieldQ = et.SubElement(datarecord,"{%s}field" % ns["swe"]) fieldQ.attrib["name"] = field["name_opr"] quantity = et.SubElement(fieldQ,"{%s}Quantity" % ns["swe"]) quantity.attrib["definition"] = field["def_opr"] if not (field["name_uom"]=="" or field["name_uom"]==None or field["name_uom"]=="NULL"): uom = et.SubElement(quantity,"{%s}uom" % ns["swe"]) uom.attrib["code"] = field["name_uom"] """ if not (field["desc_opr"]=="" or field["desc_opr"]==None or field["desc_opr"]=="NULL"): description = et.SubElement(quantity,"{%s}description" % ns["swe"]) description.text = field["desc_opr"] """ """ # Handling constraint Permitted conigurations: {"role":"urn:ogc:def:classifiers:x-istsos:1.0:qualityIndex:check:reasonable","min":"10"} {"role":"urn:ogc:def:classifiers:x-istsos:1.0:qualityIndex:check:reasonable","max":"10"} {"role":"urn:ogc:def:classifiers:x-istsos:1.0:qualityIndex:check:reasonable","interval":["-10","10"]} {"role":"urn:ogc:def:classifiers:x-istsos:1.0:qualityIndex:check:reasonable","valueList":["1","2","3","4","5","6"]} """ if not (field["constr_pro"]=="" or field["constr_pro"]==None): try: constraintObj = json.loads(field["constr_pro"]) constraint = et.SubElement(quantity,"{%s}constraint" % ns["swe"]) # Role attribute is not mandatory if "role" in constraintObj and constraintObj["role"]!="" and constraintObj["role"]!=None: constraint.attrib[ "{%s}role" % ns['xlink'] ]= constraintObj["role"] AllowedValues = et.SubElement(constraint, "{%s}AllowedValues" % ns['swe']) # Factory on constraint min/max/interval/valuelist if "interval" in constraintObj: interval = et.SubElement(AllowedValues, "{%s}interval" % ns['swe']) interval.text = " ".join([ str(a) for a in constraintObj["interval"] ]) #interval.text = " ".join(constraintObj["interval"]) elif "valueList" in constraintObj:#.has_key("valueList"): valueList = et.SubElement(AllowedValues, "{%s}valueList" % ns['swe']) valueList.text = ", ".join([ str(a) for a in constraintObj["valueList"] ]) #valueList.text = " ".join(constraintObj["valueList"]) elif "min" in constraintObj:#.has_key("min"): amin = et.SubElement(AllowedValues, "{%s}min" % ns['swe']) amin.text = str(constraintObj["min"]) elif "max" in constraintObj:#.has_key("max"): amax = et.SubElement(AllowedValues, "{%s}max" % ns['swe']) amax.text = str(constraintObj["max"]) except Exception: raise Exception("Constraint definition invalid in the database for %s" % field["def_opr"]) #verify that gml_id does not contain blanks #(workaround to be corrected in future name sensor registration) # ------------------------------------------ # NCName stands for "non-colonized name". # NCName can be defined as an XML Schema regular expression [\i-[:]][\c-[:]]* # # So in plain English it would mean "any initial character, but not :". # The whole regular expression reads as "One initial XML name character, # but not a colon, followed by zero or more XML name characters, but not a colon." # # The practical restrictions of NCName are that it cannot contain several symbol characters # ------------------------------------------ not_allowed_NCName = [' ', '!','"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '`', '{', '|', '}', '~'] location = tree.find("{%s}member/{%s}System/{%s}location" % ( ns['sml'], ns['sml'], ns['sml'])) for feature in location: for ch in not_allowed_NCName: if ch in feature.attrib['{%s}id' % ns['gml']]: feature.attrib['{%s}id' % ns['gml']] = feature.attrib['{%s}id' %ns['gml']].replace(ch,"_") # An underscore is added to be OGC compliant # -> WALIB remove this underscore !! # @TODO: think something better if not sosConfig.urn["feature"] in feature.attrib['{%s}id' % ns['gml']]: feature.attrib['{%s}id' % ns['gml']] = "loc_%s" % ( feature.attrib['{%s}id' % ns['gml']]) # The unique identifier in the response document matches the procedure specified in the request system = tree.find("{%s}member/{%s}System" %(ns['sml'],ns['sml'])) identification = tree.find("{%s}member/{%s}System/{%s}identification" %(ns['sml'],ns['sml'],ns['sml'])) if not identification: identification = et.Element("{%s}identification" % ns["sml"]) identifierList = et.SubElement(identification, "{%s}IdentifierList" % ns["sml"]) identifier = et.SubElement(identifierList, "{%s}identifier" % ns["sml"]) term = et.SubElement(identifier, "{%s}Term" % ns["sml"]) term.attrib['definition'] = "urn:ogc:def:identifier:OGC:uniqueID" value = et.SubElement(term, "{%s}value" % ns["sml"]) value.text = system.attrib['{%s}id' % ns['gml']] system.insert(1, identification) else: identifierList = identification.find("{%s}IdentifierList" % ns["sml"]) if not identifierList: identifierList = et.SubElement(identification, "{%s}IdentifierList" % ns["sml"]) identifier = et.SubElement(identifierList, "{%s}identifier" % ns["sml"]) term = et.SubElement(identifier, "{%s}Term" % ns["sml"]) term.attrib['definition'] = "urn:ogc:def:identifier:OGC:uniqueID" value = et.SubElement(term, "{%s}value" % ns["sml"]) value.text = system.attrib['{%s}id' % ns['gml']] else: identifiers = identifierList.findall("{%s}identifier" % ns["sml"]) unique = False for identifier in identifiers: if identifier.find("{%s}Term" % ns["sml"]).attrib['definition'] == "urn:ogc:def:identifier:OGC:uniqueID": unique = True break if not unique: identifier = et.SubElement(identifierList,"{%s}identifier" % ns["sml"]) term = et.SubElement(identifier,"{%s}Term" % ns["sml"]) term.attrib['definition'] = "urn:ogc:def:identifier:OGC:uniqueID" value = et.SubElement(term,"{%s}value" % ns["sml"]) value.text = system.attrib['{%s}id' %ns['gml']] root = tree.getroot() root.attrib["xmlns"]="http://www.opengis.net/sensorML/1.0.1" root.attrib["version"]="1.0.1" return """<?xml version="1.0" encoding="UTF-8"?>\n%s""" % et.tostring(root)