diff --git a/sos4py/sos_2_0_0.py b/sos4py/sos_2_0_0.py index 2f5c3bc..9a04f79 100644 --- a/sos4py/sos_2_0_0.py +++ b/sos4py/sos_2_0_0.py @@ -16,12 +16,13 @@ from owslib.swe.observation.om import MeasurementObservation from owslib.etree import etree from owslib import ows +from urllib.parse import urlencode import pandas as pd import geopandas as gpd from shapely.geometry import Point import pyproj import inspect -from .util import get_namespaces, nspv, TimePeriod, parseGDAReferencedElement, gda_member, check_list_param +from .util import get_namespaces, nspv, gda_member, gda2_member, check_list_param, check_gda_references namespaces = get_namespaces() @@ -139,15 +140,20 @@ def get_data_availability(self, procedures=None, observedProperties=None, featur for kw in kwargs: request[kw] = kwargs[kw] - request_gda = openURL(base_url, request, method, username=self.username, password=self.password, **url_kwargs).read() + data = urlencode(request) + request_gda = openURL(base_url, data, method, username=self.username, password=self.password, **url_kwargs).read() gda = etree.fromstring(request_gda) - if gda.tag == nspath_eval("ows:ExceptionReport", namespaces): raise ows.ExceptionReport(gda) + final = None gdaMembers = gda.findall(nspath_eval("gda:dataAvailabilityMember", namespaces)) - final = list(map(gda_member, gdaMembers)) - return(final) + if gdaMembers is None or len(gdaMembers) == 0: + gdaMembers = gda.findall(nspath_eval("gda2:dataAvailabilityMember", namespaces)) + final = list(map(gda2_member, gdaMembers)) + else: + final = list(map(gda_member, gdaMembers)) + return(check_gda_references(final)) def get_feature_of_interest(self, featuresOfInterest=None, observedProperties=None, procedures=None, responseFormat=None, method=None, **kwargs): """Performs "GetFeatureOfInterest" request @@ -203,7 +209,8 @@ def get_feature_of_interest(self, featuresOfInterest=None, observedProperties=No for kw in kwargs: request[kw] = kwargs[kw] - response = openURL(base_url, request, method, + data = urlencode(request) + response = openURL(base_url, data, method, username=self.username, password=self.password, **url_kwargs).read() try: tr = etree.fromstring(response) @@ -331,7 +338,8 @@ def get_observation(self, responseFormat=None, offerings=None, observedPropertie for kw in kwargs: request[kw] = kwargs[kw] - response = openURL(base_url, request, method, username=self.username, password=self.password, **url_kwargs).read() + data = urlencode(request) + response = openURL(base_url, data, method, username=self.username, password=self.password, **url_kwargs).read() try: tr = etree.fromstring(response) diff --git a/sos4py/util.py b/sos4py/util.py index bfabf77..f397767 100644 --- a/sos4py/util.py +++ b/sos4py/util.py @@ -14,17 +14,23 @@ from owslib.util import nspath_eval, testXMLAttribute, extract_time from owslib.namespaces import Namespaces import pandas as pd +from owslib.etree import etree +PHENOMENON_TIME_ID = 'PhenomenonTimeId' +PHENOMENON_TIME = 'PhenomenonTime' +START_TIME = 'StartTime' +END_TIME = 'EndTime' def get_namespaces(): n = Namespaces() ns = n.get_namespaces(["fes", "gml32", "ogc", "om20", "sa", "sml", "swe20", "swes", "wml2", "xlink", "xsi"]) - ns["gda"] = 'http://www.opengis.net/sosgda/1.0' ns["ns"] = "http://www.opengis.net/gml/3.2" ns["ows"] = n.get_namespace("ows110") ns["sams"] = "http://www.opengis.net/samplingSpatial/2.0" ns["sf"] = "http://www.opengis.net/sampling/2.0" ns["sos"] = n.get_namespace("sos20") + ns["gda"] = 'http://www.opengis.net/sosgda/1.0' + ns["gda2"] = 'http://www.opengis.net/sosgda/2.0' return ns def nspv(path): @@ -35,46 +41,76 @@ def TimePeriod(start, end): ''' gml TimePeriod construction ''' return ("start: " + str(start) + " " + "end: " + str(end)) -def parseGDAReferencedElement(gdaMembers, elementName): +def parseGDAReferencedElement(gdaMember, elementName): """Function to parse an element of a "GetDataAvailability" member""" - element = testXMLAttribute(gdaMembers.find(nspv(elementName)), nspv("xlink:href")) + element = testXMLAttribute(gdaMember.find(nspv(elementName)), nspv("xlink:href")) return(element) -def gda_member(gdaMembers): +def gda2_member(gdaMember): + return gda_member(gdaMember, 'gda2') + +def gda_member(gdaMember, gdaPrefix='gda'): """Function to parse each "GetDataAvailability" member""" #Prefixes - gdaPrefix = "gda" gdaProcedureName = gdaPrefix + ":procedure" gdaObservedPropertyName = gdaPrefix + ":observedProperty" gdaFeatureOfInterestName = gdaPrefix + ":featureOfInterest" + gdaOfferingName = gdaPrefix + ":offering" + gdaPhenomenonTime = gdaPrefix + ":phenomenonTime" + gdaResultTime = gdaPrefix + ":resultTime" #Applying a parsing function to the elements - procedure_gda = parseGDAReferencedElement(gdaMembers, gdaProcedureName) - observedProperty_gda = parseGDAReferencedElement(gdaMembers, gdaObservedPropertyName) - featureOfInterest_gda = parseGDAReferencedElement(gdaMembers, gdaFeatureOfInterestName) + procedure_gda = parseGDAReferencedElement(gdaMember, gdaProcedureName) + observedProperty_gda = parseGDAReferencedElement(gdaMember, gdaObservedPropertyName) + featureOfInterest_gda = parseGDAReferencedElement(gdaMember, gdaFeatureOfInterestName) + offering_gda = parseGDAReferencedElement(gdaMember, gdaOfferingName) ''' Determine if phenomenonTime is instant or period. This depend on the type of observation ''' - instant_element = gdaMembers.find(nspv( - "gda:phenomenonTime/gml32:TimeInstant")) - - if instant_element is not None: - phenomenonTime_gda = extract_time(instant_element) + pt_gml_id = parseGDAReferencedElement(gdaMember, gdaPhenomenonTime) + if pt_gml_id is not None: + phenomenonTime_gda = None + resultTime_gda = None + start = None + end = None else: - start = extract_time(gdaMembers.find(nspv( - "gda:phenomenonTime/gml32:TimePeriod/gml32:beginPosition"))) - end = extract_time(gdaMembers.find(nspv( - "gda:phenomenonTime/gml32:TimePeriod/gml32:endPosition"))) - phenomenonTime_gda = TimePeriod(start, end) - resultTime_gda = extract_time(gdaMembers.find(nspv( - "gda:resultTime/gml32:TimeInstant/gml32:timePosition"))) + instant_element = gdaMember.find(nspv( + gdaPhenomenonTime + "/gml32:TimeInstant")) + if instant_element is not None: + pt_gml_id = testXMLAttribute(instant_element, nspv("gml32:id")) + phenomenonTime_gda = extract_time(instant_element) + else: + period_element = gdaMember.find(nspv(gdaPhenomenonTime + "/gml32:TimePeriod")) + pt_gml_id = testXMLAttribute(period_element, nspv("gml32:id")) + start = extract_time(period_element.find(nspv("gml32:beginPosition"))) + end = extract_time(period_element.find(nspv("gml32:endPosition"))) + phenomenonTime_gda = TimePeriod(start, end) + resultTime_gda = extract_time(gdaMember.find(nspv(gdaResultTime + "/gml32:TimeInstant/gml32:timePosition"))) #Constructing the results - gda_values = [procedure_gda, observedProperty_gda, featureOfInterest_gda, phenomenonTime_gda, start, end, resultTime_gda] - gda_index = ['Procedure', 'ObservedProperty','FeatureOfInterest', 'PhenomenonTime', 'StartTime', 'EndTime', 'ResultTime'] + gda_values = [procedure_gda, observedProperty_gda, featureOfInterest_gda, offering_gda, pt_gml_id, phenomenonTime_gda, start, end, resultTime_gda] + gda_index = ['Procedure', 'ObservedProperty','FeatureOfInterest', 'Offering', PHENOMENON_TIME_ID, PHENOMENON_TIME, START_TIME, END_TIME, 'ResultTime'] a = pd.Series(gda_values, index=gda_index, name="gda_member") return(a) +def _get_gda_for_id(id, gdaMembers): + validId = id.replace('#', '') + for gdaMember in gdaMembers: + if gdaMember.get(PHENOMENON_TIME_ID) == validId: + return gdaMember + return None + +def check_gda_references(gdaMembers): + for gdaMember in gdaMembers: + if gdaMember.get(PHENOMENON_TIME_ID).startswith('#'): + data = _get_gda_for_id(gdaMember.get(PHENOMENON_TIME_ID), gdaMembers) + if data is not None: + gdaMember.at[PHENOMENON_TIME_ID] = None + gdaMember.at[PHENOMENON_TIME] = data.get(PHENOMENON_TIME) + gdaMember.at[START_TIME] = data.get(START_TIME) + gdaMember.at[END_TIME] = data.get(END_TIME) + return gdaMembers + def check_list_param(list_param): ''' Check parameters conditions and if the condition is not satisfied the program will stop and give an assertion error ''' correctness = (isinstance(list_param, list) and \