WFS - Web Feature Service¶
Eksempel på bruk av en offentlig tilgjengelig WFS-tjeneste:
Denne presentasjonen kan lastes ned som Jupter Notebook-fil (høyreklikk, lagre som ..):
NTNU 24.02.2025 - Sverre Stikbakke
import requests # for å sende http-kall
import xml.dom.minidom # for å håndtere xml-filer
import geopandas as gpd # for å vise GML-filer som kart
Funksjon som sender kall til WFS-tjenesten¶
- url: url til WFS-tjeneste
- request: XML tekst-streng, kodet som byte-string med encode-funksjon
- outfile: filnavn på XML/GML-fil
def wfs_request(url, request, outfile):
response = requests.post(url, request)
doc = xml.dom.minidom.parseString(response.content.decode())
xml_response = doc.toprettyxml()
with open(outfile, 'w', encoding = 'utf-8') as f:
f.write(xml_response)
Url til tjenesten¶
url = 'https://wfs.geonorge.no/skwms1/wfs.vannkraft'
GetCapabilities-kall¶
Utformingen av dette kallet er helt uavhengig av innholdet i tjenesten. Det brukes derfor samme kall til alle tjenester.
Vi er spesielt interessert i resultatet under FeatureTypeList
.
getcapabilities = """<?xml version="1.0" encoding="UTF-8"?>
<GetCapabilities
service = "WFS"
version = "2.0.0"
xmlns = "http://www.opengis.net/wfs/2.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.opengis.net/wfs http://schemas.opengis.net/wfs/2.0/wfs.xsd"/>
""".encode()
DescribeFeatureType¶
Dette kallet tilpasses den aktuelle tjenesten basert på resultatet av GetCapabilities-kallet.
- XML namespace, her:
xmlns:app="http://skjema.geonorge.no/SOSI/produktspesifikasjon/Vannkraft/1.3"
- TypeName, her:
app:InnsjøRegulert
Resultatet av kallet beskriver hvilke egenskaper (attributter) den aktuelle objekttypen (TypeName) har.
describefeaturetype = """<?xml version="1.0" encoding="UTF-8"?>
<DescribeFeatureType
service = "WFS"
version = "2.0.0"
xmlns = "http://www.opengis.net/wfs/2.0"
xmlns:app ="http://skjema.geonorge.no/SOSI/produktspesifikasjon/Vannkraft/1.3"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd">
<TypeName>app:InnsjøRegulert</TypeName>
</DescribeFeatureType>
""".encode()
GetFeature - uten Filter Encoding¶
Dette kallet henter objekter fra tjenesten. Namespace og Typename må spesifiseres.
Her er det ikke noen spesifisering av hvordan objekter skal velges ut. Resultatet blir derfor tilfeldig, men det kan være en første test på å få ut et objekt fra tjenesten. Kallet spør i utgangspunktet etter alle objekter av den aktuelle objekttypen. Det er derfor viktig å begrense antallet objekter med count
. Legg merke til:
- wfs:Query
- typeNames
- srsName
getfeature = """<?xml version="1.0" encoding="UTF-8"?>
<GetFeature
service = "WFS"
version = "2.0.0"
count = "1"
xmlns = "http://www.opengis.net/wfs/2.0"
xmlns:app="http://skjema.geonorge.no/SOSI/produktspesifikasjon/Vannkraft/1.3">
<Query typeNames = "app:InnsjøRegulert" srsName="urn:ogc:def:crs:EPSG::25832">
</Query>
</GetFeature>
""".encode()
GetFeature - med Filter Encoding¶
Dette kallet er utvidet med et fes:Filter
-element. Filteret er av type BBOX som er oppgitt som en gml:Envelope
.
fes:ValueReference
henviser til område
som er navnet på geometri-egenskapen i objekttypen. Denne opplysningen kunne vi finne basert på resultatet av DescribeFeatureType-kallet, under InnsjøRegulert
. Legg merke til at kallet også er utvidet med to nye namespaces:
- xmlns:fes, for Filter Encoding
- xmlns:gml, for GML
getfeatureBBOX = """<?xml version="1.0" encoding="UTF-8"?>
<GetFeature
version = "2.0.0"
xmlns = "http://www.opengis.net/wfs/2.0"
xmlns:fes = "http://www.opengis.net/fes/2.0"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:app="http://skjema.geonorge.no/SOSI/produktspesifikasjon/Vannkraft/1.3">
<Query typeNames = "app:InnsjøRegulert" srsName="urn:ogc:def:crs:EPSG::25832">
<fes:Filter>
<fes:BBOX>
<fes:ValueReference>område</fes:ValueReference>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::25832">
<gml:lowerCorner>586500 6735500</gml:lowerCorner>
<gml:upperCorner>596500 6745500</gml:upperCorner>
</gml:Envelope>
</fes:BBOX>
</fes:Filter>
</Query>
</GetFeature>
""".encode()
Utføring av kallene¶
wfs_request(url, getcapabilities, 'getcapabilities.xml')
wfs_request(url, describefeaturetype, 'describefeaturetype.xml')
# wfs_request(url, getfeature, 'features.gml')
wfs_request(url, getfeatureBBOX, 'features.gml')
Presentasjon av resultat-fil¶
# skjuler warnings i cellen nedenfor
import warnings
warnings.filterwarnings('ignore')
features = gpd.read_file('features.gml', download_schema="no")
features.info()
<class 'geopandas.geodataframe.GeoDataFrame'> RangeIndex: 3 entries, 0 to 2 Data columns (total 25 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 gml_id 3 non-null object 1 lokalId 3 non-null object 2 navnerom 3 non-null object 3 versjonId 3 non-null float64 4 datauttaksdato 3 non-null object 5 oppdateringsdato 3 non-null object 6 status 3 non-null object 7 konsesjonStatus 3 non-null int32 8 konsesjonStatusDato 3 non-null object 9 idriftsattAar 1 non-null float64 10 vannkraftverkNr 3 non-null int32 11 vannkraftverkNavn 3 non-null object 12 elvenavnHierarki 3 non-null object 13 magasinNr 3 non-null int32 14 magasinNavn 3 non-null object 15 magasinAreal 3 non-null float64 16 volumOppdemt 1 non-null float64 17 magasinKategori 3 non-null int32 18 lavesteRegulerteVannstand 1 non-null float64 19 høyesteRegulerteVannstand 1 non-null float64 20 magasinFormål 3 non-null object 21 kdbNr 3 non-null int32 22 spID 1 non-null object 23 delfeltNr 3 non-null int32 24 geometry 3 non-null geometry dtypes: float64(6), geometry(1), int32(6), object(12) memory usage: 660.0+ bytes
features.bounds
minx | miny | maxx | maxy | |
---|---|---|---|---|
0 | 574719.999 | 6677539.569 | 630586.005 | 6779617.995 |
1 | 588864.740 | 6737213.615 | 589118.598 | 6737678.122 |
2 | 588399.029 | 6736330.577 | 588522.028 | 6736366.842 |
features
gml_id | lokalId | navnerom | versjonId | datauttaksdato | oppdateringsdato | status | konsesjonStatus | konsesjonStatusDato | idriftsattAar | ... | magasinAreal | volumOppdemt | magasinKategori | lavesteRegulerteVannstand | høyesteRegulerteVannstand | magasinFormål | kdbNr | spID | delfeltNr | geometry | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | app.innsjoregulert.791 | 0441afa2-cd1f-4cb0-acae-c053371734e6 | http://skjema.geonorge.no/SOSI/produktspesifik... | 1.3 | 2025-02-24T04:37:21 | 2611-02-05T03:36:40 | D | 5 | 2591-06-08T14:23:20 | 1912.0 | ... | 375.82 | 1312.0 | 1 | 119.33 | 122.94 | Kraftproduksjon | 794 | 00422 | 1905 | POLYGON ((574882.001 6779599.002, 574797 67796... |
1 | app.innsjoregulert.2153 | ba48a9a5-bd4a-497e-a852-33282c8e6911 | http://skjema.geonorge.no/SOSI/produktspesifik... | 1.3 | 2025-02-24T04:37:51 | 2611-02-05T03:36:40 | D | 5 | 2598-09-26T05:16:40 | NaN | ... | 0.04 | NaN | 2 | NaN | NaN | Kraftproduksjon | 707 | None | 1167 | POLYGON ((588998.713 6737616.81, 588998.037 67... |
2 | app.innsjoregulert.2156 | 904f4589-dc86-4387-b524-8efe647e44f1 | http://skjema.geonorge.no/SOSI/produktspesifik... | 1.3 | 2025-02-24T04:37:51 | 2611-02-05T03:36:40 | D | 5 | 2599-09-04T01:20:00 | NaN | ... | 0.00 | NaN | 2 | NaN | NaN | Kraftproduksjon | 625 | None | 3041 | POLYGON ((588512.665 6736366.352, 588507.281 6... |
3 rows × 25 columns
features.plot(figsize=(10,10))
<Axes: >