Files
Projektwissen/docs/wissen/wfs_dienste.md
T
DanielandClaude Sonnet 5 ce795cdc6f Referenzwissen ALKIS/WFS und ALKIS-7-Umstellungscheckliste ergaenzt
Neu in docs/wissen: wfs_dienste.md (ALKIS-WFS-Endpunkte der saechsischen
Dienste, erprobte Anfragen je Objektart, die vom WAF blockierten
Normfaelle) und alkis_objektarten.md (die von sn_verfahrensgebiet
genutzten AAA-Objektarten mit Attributen, Filterkonventionen und den
FlurbG-Werten von artderfestlegung).

Neu in docs/konzept: 09_alkis7_umstellung.md - Vergleich ALKIS 6 (GID 6.0)
gegen ALKIS 7 (GID 7.1) und die konkrete Anpassungsliste fuer
sn_verfahrensgebiet (fest verdrahteter NAS-Namespace, abgeflachte
WFS-Feldnamen, Codelisten, Tests). Als offene Baustelle 14 in STATUS.md
verlinkt.

Quellmaterial (OK-AAA 7.1.2, ALKIS-FSK 2.1.0, EA-Modellexporte, ~180 MB)
liegt lokal unter referenz/ und wird per .gitignore nicht versioniert;
Herkunft ist in alkis_objektarten.md dokumentiert.

Querverweise aus externe_dienste.md, fallstricke.md, docs/README.md
ergaenzt; Glossar um NAS, ZUSO/REO, OK-AAA erweitert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NqvdHqySjQMVowB3G3Vf3U
2026-09-04 15:05:07 +02:00

138 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# WFS-Dienste (ALKIS Sachsen)
Lebendes Dokument. Was die Plugins an WFS-Diensten ansprechen, wie sich diese Dienste **tatsächlich**
verhalten (nicht wie die Norm es vorsieht) und welche Anfragen erprobt funktionieren.
Betrifft ausschließlich **`sn_verfahrensgebiet`** (`functions/*_alkis*.py`). `sn_plan41` nutzt kein ALKIS/WFS,
sondern die VLN-Karten-API. Objektarten und Attribute im Detail: [`alkis_objektarten.md`](alkis_objektarten.md).
Quelle der Erkenntnisse: Sondierungsskripte in `referenz/wfs/` (nicht versioniert) und der Code selbst.
## Die drei Endpunkte
| Kürzel im Code | URL | WFS-Version | Geometrie | Verwendung |
|---|---|---|---|---|
| „vereinfacht" (`ALKIS_VEREINF_URL`) | `https://geodienste.sachsen.de/aaa/public_alkis/vereinf/wfs` | 2.0.0 | ja | `ave:KatasterBezirk` → Gemarkungen mit Fläche |
| „SF" (`ALKIS_SF_URL`) | `https://geodienste.sachsen.de/aaa/public_alkis/sf/wfs` | 2.0.0 | teils | `adv:AX_Flurstueck`, `adv:AX_BauRaumOderBodenordnungsrecht`, `adv:AX_PunktortTA`, `adv:AX_Grenzpunkt` |
| „NAS" (nur erwähnt) | – | – | – | `adv:AX_Gemarkung` hätte **keine** Geometrie, deshalb wird stattdessen `ave:KatasterBezirk` genommen |
CRS durchgängig **EPSG:25833** (ETRS89 / UTM 33N). In KVP-Parametern als `urn:ogc:def:crs:EPSG::25833`,
in der QGIS-WFS-URI als `srsname='EPSG:25833'`.
## Was der Dienst blockiert – die harten Grenzen
Ein Web Application Firewall vor `geodienste.sachsen.de` schränkt den Dienst gegenüber der WFS-2.0-Norm ein:
| Was | Verhalten | Beleg |
|---|---|---|
| **POST** (`GetFeature` als XML-Body) | blockiert | `referenz/wfs/_test_wfs_post.py` |
| **`FILTER`-XML mit GML-`Envelope`/`BBOX`** in der GET-URL | blockiert | `referenz/wfs/_test_wfs_bbox.py`, `grenzpunkt_alkis.py` Kopf |
| **KVP-Parameter `BBOX=minx,miny,maxx,maxy,crs`** | **funktioniert** – so wird PunktortTA räumlich gefiltert | `_punktort_ta_bbox_param()` |
| **`FILTER` mit `fes:ResourceId rid="…"`** in der GET-URL | funktioniert (`ImplementsResourceId=TRUE`) | `_test_wfs_get.py`, Grenzpunkt-Batches |
| **URL-Länge** | ~8192 Bytes; darüber 414/Abbruch | Batchgröße 100 IDs (~54 Byte/ID URL-kodiert) |
| **`COUNT`** | Serverlimit, im Code auf 20 000 gesetzt (`_MAX_FEATURES`) | `grenzpunkt_alkis.py` |
| **Serverseitiger Filter auf `gehoertZu`/`istTeilVon`** | nicht möglich (`ErrorInPropertyName`) | `grenzpunkt_alkis.py` Kopf |
| **`AX_Grenzpunkt` per BBOX** | nicht möglich – Objektart ohne eigene Geometrie | siehe unten |
Folgerung: **Nicht „vereinfachen", ohne gegen den Dienst zu testen.** Die scheinbar umständlichen
Mehrschritt-Strategien (BBOX → PunktortTA → GML-IDs → Grenzpunkt-Batches → Client-Join; Flurstücke
gemarkungsweise einzeln) sind die Antwort auf genau diese Grenzen.
## Anfragen je Objektart (erprobt)
### `ave:KatasterBezirk` (vereinfachter Dienst) → Gemarkungen
QGIS-WFS-Layer, **ohne** serverseitigen Filter (Dienst kann es nicht), danach Client-seitige Verschneidung
per `QgsGeometry.intersects` mit der Verfahrensgebiets-Geometrie:
```
url='https://geodienste.sachsen.de/aaa/public_alkis/vereinf/wfs'
typename='ave:KatasterBezirk' srsname='EPSG:25833'
```
Attribute: `schluessel` (voller Katasterbezirksschlüssel, **letzte 4 Stellen = Gemarkungsnummer**),
`ave_name` (Bezeichnung). Sachsen hat ≈ 2 000 Katasterbezirke – der Komplettabruf ist vertretbar.
### `adv:AX_BauRaumOderBodenordnungsrecht` (SF) → Verfahrensgebiet
Serverseitiger Attributfilter über die QGIS-WFS-URI (`sql=`):
```
url='…/sf/wfs' typename='adv:AX_BauRaumOderBodenordnungsrecht' srsname='EPSG:25833'
sql=SELECT * FROM AX_BauRaumOderBodenordnungsrecht WHERE bezeichnung LIKE '<vkz5>%'
```
`<vkz5>` = die **ersten 5 Stellen** der Verfahrenskennziffer (`get_variable("verfahrensnummer")[:5]`);
die Daten im Dienst führen teils abweichende Suffixe. Geladene Attribute:
`artderfestlegung`, `ausfuehrendestelle_ax_dienststelle_schluessel_stelle`, `adv_name`, `bezeichnung`,
`datumanordnung`, `datumbesitzeinweisung`, `datumrechtskraft`, `datumabgabe`.
Gruppierung im Plugin nach `(adv_name, bezeichnung)`.
### `adv:AX_Flurstueck` (SF)
**Eine WFS-Anfrage pro Gemarkung** (Sammelabfrage mit mehreren Nummern läuft ins Feature-Limit),
Ergebnisse in einen Memory-Layer zusammengeführt:
```
url='…/sf/wfs' typename='adv:AX_Flurstueck' srsname='EPSG:25833'
sql=SELECT * FROM AX_Flurstueck
WHERE gemarkung_ax_gemarkung_schluessel_gemarkungsnummer = '<gemarkungsnummer4>'
```
### `adv:AX_PunktortTA` (SF) → Trägerpunkt für Grenzpunkte
Roh-GET mit KVP-`BBOX`, GML-Antwort wird selbst geparst (`xml.etree`):
```
SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature
&TYPENAMES=adv:AX_PunktortTA
&SRSNAME=urn:ogc:def:crs:EPSG::25833
&COUNT=20000
&BBOX=<minx>,<miny>,<maxx>,<maxy>,urn:ogc:def:crs:EPSG::25833
```
Geometrieattribut `position`. Referenz auf den Grenzpunkt: Feldname je NAS-Version unterschiedlich –
Kandidaten in dieser Reihenfolge geprüft: `istTeilVon` (NAS 6.x), `gehoertZu`, `gehoertZuAX_Grenzpunkt`.
Wert kommt als `xlink:href` (`urn:adv:oid:DE…`) oder flach. Optional wird
`adv:qualitaetsangaben/adv:genauigkeitsstufe` in das Feld
`qualitaetsangaben_ax_dqpunktort_genauigkeitsstufe` gezogen.
### `adv:AX_Grenzpunkt` (SF)
Kein BBOX (ZUSO ohne eigene Geometrie). Abruf über die aus PunktortTA gewonnenen GML-IDs,
**Batches à 100**, GET mit `ResourceId`-Filter:
```
SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature
&TYPENAMES=adv:AX_Grenzpunkt&COUNT=20000
&FILTER=<fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0">
<fes:ResourceId rid="DE…"/> … (bis zu 100)
</fes:Filter>
```
Danach Client-seitiger Join `PunktortTA.<referenzfeld>` ↔ `AX_Grenzpunkt.gml_id`; Grenzpunkt-Attribute
im Ergebnis mit Präfix `gp_`.
## Fehlerantworten, die im Betrieb auftauchen
| Antwort | Bedeutung | Reaktion im Code |
|---|---|---|
| HTTP 403 / HTML-Seite statt XML | WAF hat POST oder GML-XML-Filter geblockt | auf GET + KVP/ResourceId ausweichen |
| `ExceptionReport` mit `ErrorInPropertyName` | Attribut ist nicht serverseitig filterbar | Attribut client-seitig filtern |
| gültiger Layer, `featureCount() == 0` | Dienst liefert ohne (unterstützten) Filter nichts | Diagnosemeldung, leere Liste, manueller Fallback |
| HTTP 414 | URL zu lang | Batchgröße senken |
## Offene Punkte
- Die vier Skripte in `referenz/wfs/` sind Wegwerf-Sondierungen. Wenn Bedarf besteht, sie regelmäßig
laufen zu lassen (Dienst-Regression erkennen), gehören sie als `scripts/wfs_probe.py` ins Projektwissen –
mit Netzkennzeichnung, kein Unittest.
- `ave:KatasterBezirk` vs. Schreibweise `Katasterbezirk`/`KatasterBezirk`: im Code uneinheitlich
dokumentiert, maßgeblich ist der Wert in `gemarkung_alkis.py` (`ave:KatasterBezirk`).
## Siehe auch
- [`alkis_objektarten.md`](alkis_objektarten.md) – Objektarten und Attribute
- [`externe_dienste.md`](externe_dienste.md) – alle externen Dienste im Überblick
- [`fallstricke.md`](fallstricke.md) – Abschnitt „Daten und Dienste"
- `referenz/alkis/` (lokal, nicht versioniert) – OK-AAA 7.1.2, ALKIS-FSK 2.1.0