FBSchl-Feldsuche tolerant gegenüber abweichenden Feldnamen

Manche Shape-Exporte liefern das Feld "FBSchl" mit angehängtem Punkt
(z.B. "FBSchl.") oder abweichender Groß-/Kleinschreibung. Der bisherige
exakte Namensvergleich (fields().indexFromName) erkannte das Feld dann
nicht und meldete fälschlich "Feld fehlt", die Datei wurde nicht
eingelesen.

- _normalisiere_feldname(): entfernt alle Nicht-alphanumerischen Zeichen
  und normalisiert auf Kleinbuchstaben
- _finde_fbschl_index(): exakter Namensabgleich zuerst, sonst Fallback auf
  normalisierten Vergleich über alle Felder

Fixes #44

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Michael Otto
2026-09-02 11:43:34 +02:00
co-authored by Claude Sonnet 5
parent 70c14783c5
commit 3c0e6e5a19
+57 -1
View File
@@ -42,6 +42,7 @@ oder kein Ergebnis liefert, bricht den Workflow ab.
from __future__ import annotations from __future__ import annotations
import os import os
import re
import shutil import shutil
import tempfile import tempfile
import zipfile import zipfile
@@ -106,6 +107,57 @@ _GEBIETSTYP_LAYER_NAMEN = {
# Interne Hilfsfunktionen # Interne Hilfsfunktionen
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def _normalisiere_feldname(name: str) -> str:
"""Normalisiert einen Feldnamen für den toleranten Vergleich.
Entfernt alle Zeichen außer Buchstaben/Ziffern (z.B. Punkte, Leerzeichen,
Unterstriche) und wandelt in Kleinbuchstaben um. Hintergrund: manche
Shape-Exporte liefern den Feldnamen ``FBSchl`` mit einem angehängten
Punkt (``FBSchl.``) oder abweichender Groß-/Kleinschreibung, wodurch ein
exakter Namensvergleich das Feld fälschlich als fehlend meldet (#44).
Parameters
----------
name :
Roher Feldname.
Returns
-------
str
Normalisierter Feldname (nur Kleinbuchstaben/Ziffern).
"""
return re.sub(r"[^a-zA-Z0-9]", "", name).lower()
def _finde_fbschl_index(raw_layer) -> int:
"""Sucht den Feldindex von ``FBSchl`` tolerant gegenüber Abweichungen im
Namen (Groß-/Kleinschreibung, angehängte Sonderzeichen wie ein Punkt).
Versucht zuerst den exakten Namen; schlägt das fehl, wird über alle
Felder mit normalisiertem Namensvergleich gesucht (siehe
:func:`_normalisiere_feldname`).
Parameters
----------
raw_layer :
Dateibasierter Shapefile-Layer.
Returns
-------
int
Feldindex, oder ``-1`` wenn kein passendes Feld gefunden wurde.
"""
idx = raw_layer.fields().indexFromName(FBSCHL_FELD)
if idx >= 0:
return idx
ziel = _normalisiere_feldname(FBSCHL_FELD)
for feld_idx, feld in enumerate(raw_layer.fields()):
if _normalisiere_feldname(feld.name()) == ziel:
return feld_idx
return -1
def _ermittle_gebietstyp_aus_fbschl(raw_layer) -> Tuple[Optional[str], Optional[str]]: def _ermittle_gebietstyp_aus_fbschl(raw_layer) -> Tuple[Optional[str], Optional[str]]:
"""Prüft das Feld ``FBSchl`` und ermittelt den Gebietstyp. """Prüft das Feld ``FBSchl`` und ermittelt den Gebietstyp.
@@ -113,6 +165,10 @@ def _ermittle_gebietstyp_aus_fbschl(raw_layer) -> Tuple[Optional[str], Optional[
zurück, damit der Aufrufer Fehler mehrerer Dateien sammeln und am Ende zurück, damit der Aufrufer Fehler mehrerer Dateien sammeln und am Ende
gemeinsam anzeigen kann. gemeinsam anzeigen kann.
Die Feldsuche ist tolerant gegenüber Abweichungen im Namen (z.B. ein
angehängter Punkt ``FBSchl.`` in manchen Shape-Exporten, siehe #44) –
siehe :func:`_finde_fbschl_index`.
Parameters Parameters
---------- ----------
raw_layer : raw_layer :
@@ -127,7 +183,7 @@ def _ermittle_gebietstyp_aus_fbschl(raw_layer) -> Tuple[Optional[str], Optional[
``fehlertext`` beschreibt die Ursache (fehlendes Feld oder ``fehlertext`` beschreibt die Ursache (fehlendes Feld oder
unbekannter Wert). unbekannter Wert).
""" """
idx = raw_layer.fields().indexFromName(FBSCHL_FELD) idx = _finde_fbschl_index(raw_layer)
if idx < 0: if idx < 0:
return None, f"Feld '{FBSCHL_FELD}' fehlt (Shape entspricht nicht dem erwarteten Inhalt)." return None, f"Feld '{FBSCHL_FELD}' fehlt (Shape entspricht nicht dem erwarteten Inhalt)."