Files
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

6.9 KiB
Raw Permalink Blame History

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. 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