예제 #1
0
    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))
예제 #2
0
    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)
            """
            """
예제 #3
0
    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)
예제 #4
0
    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
예제 #5
0
    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")
예제 #6
0
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)