""" yaml_generator.py Fælles YAML-generering til brug med udpak_semistruktur. Importeres af xsd_til_yaml.py, jsonschema_til_yaml.py og elastic_til_yaml.py. """ from __future__ import annotations import os from schema_dataklasser import XsdFelt, XsdSkabelonRef, XsdKompleksType, XsdListeElement # ============================================================ # Hjælpefunktioner # ============================================================ def _find_fælles_prefix(liste_elementer: list) -> int: if not liste_elementer: return 0 # Udelad rod-elementet (første element med korteste sti) alle_stier = [el.rod_sti.split(".") for el in liste_elementer if len(el.rod_sti.split(".")) > 1] if not alle_stier: return 0 korteste = min(len(s) for s in alle_stier) fælles = 0 for i in range(korteste): if len(set(s[i] for s in alle_stier)) == 1: fælles += 1 else: break return min(fælles, korteste - 1) def _byg_choice_grupper(liste_elementer: list) -> dict[str, dict]: """ Grupperer liste-elementer der deler samme rod op til choice-niveauet. Returnerer dict: rod_sti → { 'fælles_rod': str, 'valg': [str], # fx ['Entity', 'Individual'] 'element_navn': str, # fx 'Address' 'samlet_rod': str # fx 'CARF_OECD...UserID.[Entity, Individual].Address' } """ from collections import defaultdict grupper: dict[str, list] = defaultdict(list) for el in liste_elementer: dele = el.rod_sti.split(".") # Nøglen er: alt undtagen næstsidste led (choice-leddet) if len(dele) >= 2: nøgle = ".".join(dele[:-2]) + "." + dele[-1] # fjern choice-leddet grupper[nøgle].append(el) resultat = {} for nøgle, elementer in grupper.items(): if len(elementer) > 1: valg = [el.rod_sti.split(".")[-2] for el in elementer] fælles_rod = ".".join(elementer[0].rod_sti.split(".")[:-2]) element_navn = elementer[0].rod_sti.split(".")[-1] samlet = f"{fælles_rod}.[{', '.join(valg)}].{element_navn}" for el in elementer: resultat[el.rod_sti] = { 'fælles_rod': fælles_rod, 'valg': valg, 'element_navn': element_navn, 'samlet_rod': samlet } return resultat def _anvend_forkortelser(navn: str, forkortelser: dict[str, str]) -> str: """Anvender forkortelser case-insensitivt.""" resultat = navn for langt, kort in forkortelser.items(): resultat = resultat.replace(langt.lower(), kort.lower()) resultat = resultat.replace(langt, kort) return resultat def _xsd_type_til_yaml(xsd_type: str) -> dict: """Konverterer XSD-type til YAML-attributter.""" t = xsd_type.lower() if "decimal" in t: return {"type": "decimal", "decimaler": 2} if "integer" in t or ("int" in t and "string" not in t): return {"type": "integer"} if "boolean" in t: return {"type": "boolean"} if "datetime" in t: return {"type": "date", "dato_ind": '"%Y-%m-%dT%H:%M:%S"', "dato_ud": '"SYBASE"'} if "date" in t: return {"type": "date", "dato_ind": '"%Y-%m-%d"', "dato_ud": '"%d-%m-%Y"'} return {} def _skriv_felt(felt: XsdFelt, indryk: str, forkortelser: dict, liste_navne: set = set(), fil_navne_index: dict = {}) -> list[str]: # Tjek på felt_ref – ikke navn – da navn kan være forkortet rod_del = felt.felt_ref.split(".")[0] if "." in felt.felt_ref else "" er_i_liste_fil = rod_del and rod_del in liste_navne linjer = [] navn = _anvend_forkortelser(felt.yaml_navn, forkortelser) # if rod_del: # print(f" DEBUG: rod_del='{rod_del}' er_i_liste_fil={er_i_liste_fil} liste_navne_sample={list(liste_navne)[:5]}") if er_i_liste_fil: fil_navn = fil_navne_index.get(rod_del, f"udtræk_{rod_del.lower()}.yaml") linjer.append(f'') linjer.append(f'{indryk}# OBS: {rod_del} har sin egen udtræk-fil: {fil_navn}') linjer.append(f'{indryk}# - navn: {navn}') linjer.append(f'{indryk}# felt: "{felt.felt_ref}"') else: linjer.append(f'') navn_str = f'"{navn}"' if navn.startswith("#") else navn linjer.append(f'{indryk}- navn: {navn_str}') linjer.append(f'{indryk} felt: "{felt.felt_ref}"') for k, v in _xsd_type_til_yaml(felt.xsd_type).items(): linjer.append(f'{indryk} {k}: {v}') if felt.påkrævet: linjer.append(f'{indryk} påkrævet: true') if felt.er_liste: linjer.append(f'{indryk} join: true') linjer.append(f'{indryk} join_separator: ", "') linjer.append(f'{indryk} # OBS: Kan forekomme flere gange (maxOccurs > 1)') return linjer def _skriv_skabelon_ref(ref: XsdSkabelonRef, indryk: str, forkortelser: dict, liste_navne: set = set(), tomme_skabeloner: set = set(), fil_navne_index: dict = {}) -> list[str]: linjer = [] prefix_navn = _anvend_forkortelser(ref.prefix_navn, forkortelser) # Tjek om prefix_felt matcher et liste-element – med eller uden punktum rod_del = ref.prefix_felt.split(".")[0] if "." in ref.prefix_felt else ref.prefix_felt er_i_liste_fil = rod_del and rod_del in liste_navne # Tjek om skabelonen er tom (alle felter udkommenteret) er_tom_skabelon = ref.skabelon_navn in tomme_skabeloner if er_i_liste_fil or er_tom_skabelon: linjer.append(f'') if er_i_liste_fil: fil_navn = fil_navne_index.get(rod_del, f"udtræk_{rod_del.lower()}.yaml") linjer.append(f'{indryk}# OBS: {rod_del} har sin egen udtræk-fil: {fil_navn}') else: linjer.append(f'{indryk}# OBS: {ref.skabelon_navn} skabelonen er tom – alle felter har egne udtræk-filer') linjer.append(f'{indryk}# - skabelon: {ref.skabelon_navn}') linjer.append(f'{indryk}# prefix_felt: {ref.prefix_felt}') linjer.append(f'{indryk}# prefix_navn: "{prefix_navn}"') return linjer if ref.er_choice: linjer.append(f'') linjer.append(f'{indryk}# Vælg ét alternativ (choice):') else: linjer.append(f'') linjer.append(f'{indryk}- skabelon: {ref.skabelon_navn}') linjer.append(f'{indryk} prefix_felt: {ref.prefix_felt}') linjer.append(f'{indryk} prefix_navn: "{prefix_navn}"') if ref.er_choice: linjer.append(f'{indryk} hvis_findes: {ref.prefix_felt}') if ref.er_liste: element_basis = ref.element_navn.lower().split(".")[-1] fil_navn_hint = fil_navne_index.get( ref.element_navn.split(".")[-1], f"udtræk_{element_basis}.yaml" ) linjer.append(f'{indryk} # OBS: Kan forekomme flere gange (maxOccurs > 1).') linjer.append(f'{indryk} # Overvej om det skal udtrækkes i en separat fil.') linjer.append(f'{indryk} # Se evt. {fil_navn_hint}') return linjer def _har_aktive_felter(kt: XsdKompleksType, liste_navne: set[str]) -> bool: """Returnerer True hvis skabelonen har mindst ét aktivt felt der ikke er udkommenteret fordi det har sin egen udtræk-fil.""" return any( not (isinstance(f, XsdSkabelonRef) and (f.prefix_felt.split(".")[0] if "." in f.prefix_felt else f.prefix_felt) in liste_navne) and not (isinstance(f, XsdFelt) and (f.felt_ref.split(".")[0] if "." in f.felt_ref else "") in liste_navne) for f in kt.felter ) # ============================================================ # Generator: skabeloner.yaml # ============================================================ def generer_skabeloner_yaml( komplekse_typer: dict[str, XsdKompleksType], output_mappe: str, forkortelser: dict[str, str] = {}, liste_navne: set[str] = set(), liste_elementer: list = [] # ← tilføj ) -> None: fælles_prefix_længde = _find_fælles_prefix(liste_elementer) fil_navne_index: dict[str, str] = {} for el in liste_elementer: rod_dele = el.rod_sti.split(".") unikke_dele = rod_dele[fælles_prefix_længde:] if len(rod_dele) > fælles_prefix_længde else rod_dele fil_del = _anvend_forkortelser("_".join(unikke_dele).lower(), forkortelser) # Behold kun første registrering per element-navn if el.element_navn not in fil_navne_index: fil_navne_index[el.element_navn] = f"udtræk_{fil_del}.yaml" linjer = [] linjer.append("# =============================================================================") linjer.append("# skabeloner.yaml") linjer.append("#") linjer.append("# Auto-genereret feltskabeloner fra XSD.") linjer.append("# Brug prefix_felt og prefix_navn når skabelonen inkluderes.") linjer.append("# =============================================================================") linjer.append("") linjer.append("kolonne_skabeloner:") linjer.append("") # Byg sæt af tomme skabeloner tomme_skabeloner = { kt.navn.replace("_Type", "").replace("Type", "").lower() for kt in komplekse_typer.values() if kt.felter and not kt.er_ekstern and not _har_aktive_felter(kt, liste_navne) } relevante = {n: kt for n, kt in komplekse_typer.items() if kt.felter and not kt.er_ekstern and _har_aktive_felter(kt, liste_navne)} for type_navn, kt in relevante.items(): skabelon_navn = type_navn.replace("_Type", "").replace("Type", "").lower() linjer.append(f" # {type_navn}") if not _har_aktive_felter(kt, liste_navne): linjer.append(f" {skabelon_navn}: []") linjer.append("") continue linjer.append(f" {skabelon_navn}:") for felt in kt.felter: if isinstance(felt, XsdSkabelonRef): linjer.extend(_skriv_skabelon_ref( felt, indryk=" ", forkortelser=forkortelser, liste_navne=liste_navne, tomme_skabeloner=tomme_skabeloner, fil_navne_index=fil_navne_index )) elif isinstance(felt, XsdFelt): linjer.extend(_skriv_felt( felt, indryk=" ", forkortelser=forkortelser, liste_navne=liste_navne, fil_navne_index=fil_navne_index )) linjer.append("") sti = os.path.join(output_mappe, "skabeloner.yaml") with open(sti, "w", encoding="utf-8") as f: f.write("\n".join(linjer)) print(f" Skrev: {sti}") # ============================================================ # Generator: choice udtræk-filer # ============================================================ def generer_choice_udtræk_yaml( choice_elementer: list, komplekse_typer: dict, liste_elementer: list, output_mappe: str, prefix: str = "udtræk", forkortelser: dict = {}, db_schema: str = "dbo", tabel_prefix: str = "", output_type: str = "begge", historik: str = "t2" ) -> None: from schema_dataklasser import XsdChoiceElement, XsdSkabelonRef, XsdFelt liste_navne = {el.element_navn for el in liste_elementer} fælles_prefix_længde = _find_fælles_prefix(liste_elementer) for ce in choice_elementer: # Find den overliggende komplekse type overliggende_type = None rod_element_navn = ce.rod_sti.split(".")[-1] for el in liste_elementer: if el.element_navn == rod_element_navn and el.type_navn: type_navn_rent = el.type_navn.split(":")[-1] if ":" in el.type_navn else el.type_navn overliggende_type = komplekse_typer.get(type_navn_rent) break for alt_navn, alt_skabelon, alt_sti in ce.alternativer: # Byg filnavn med samme prefix-logik som generer_udtræk_yaml rod_dele = ce.rod_sti.split(".") unikke_dele = rod_dele[fælles_prefix_længde:] if len(rod_dele) > fælles_prefix_længde else rod_dele rod_del_str = _anvend_forkortelser("_".join(unikke_dele).lower(), forkortelser) alt_forkortet = _anvend_forkortelser(alt_navn.lower(), forkortelser) fil_del = f"{rod_del_str}_{alt_forkortet}" fil_navn = f"{prefix}_{fil_del}.yaml" hvis_finder_sti = f"{ce.element_navn}.{alt_navn}" prefix_navn = _anvend_forkortelser( f"{ce.element_navn.lower()}_{alt_navn.lower()}_".replace(".", "_"), forkortelser ) linjer = [] linjer.append("# =============================================================================") linjer.append(f"# {fil_navn}") linjer.append("#") linjer.append(f"# Auto-genereret udtræk for {rod_element_navn} – {alt_navn} alternativ.") linjer.append(f"# Rod-sti: {ce.rod_sti}") linjer.append(f"# Kører kun hvis {hvis_finder_sti} eksisterer i XML.") if ce.overliggende: linjer.append("#") linjer.append("# Udfyld nøgle-skabeloner i nøgler.yaml inden brug.") linjer.append("# =============================================================================") linjer.append("") linjer.append("output_filer:") linjer.append("") linjer.append(f" - rod: {ce.rod_sti}") linjer.append(f" hvis_findes: {hvis_finder_sti}") linjer.append(f" kolonner:") # Nøgler if ce.overliggende: linjer.append(f" # Nøgler fra overliggende niveauer – udfyld i nøgler.yaml") for ov_navn in ce.overliggende: skabelon_navn = _anvend_forkortelser( f"{ov_navn.lower()}_nøgle", forkortelser ) linjer.append(f" - skabelon: {skabelon_navn}") linjer.append("") # Choice-alternativets skabelon linjer.append(f" # {alt_navn} felter") linjer.append(f" - skabelon: {alt_skabelon}") linjer.append(f" prefix_felt: {ce.element_navn}.{alt_navn}") linjer.append(f' prefix_navn: "{prefix_navn}"') # Øvrige felter fra den overliggende type if overliggende_type and overliggende_type.felter: ikke_choice_felter = [ f for f in overliggende_type.felter if not (isinstance(f, XsdSkabelonRef) and f.er_choice) and not (isinstance(f, XsdFelt) and f.er_choice) ] if ikke_choice_felter: linjer.append("") linjer.append(f" # Øvrige felter fra {rod_element_navn}") for felt in ikke_choice_felter: if isinstance(felt, XsdSkabelonRef): linjer.extend(_skriv_skabelon_ref( felt, " ", forkortelser, liste_navne )) elif isinstance(felt, XsdFelt): linjer.extend(_skriv_felt( felt, " ", forkortelser, liste_navne )) linjer.append("") linjer.append(f" outputs:") if output_type in ("fil", "begge"): linjer.append(f" - fil_navn: \"{fil_del}_{{yyyy}}{{mm}}{{dd}}.txt\"") linjer.append(f" overskrifter: true") linjer.append("") if output_type in ("tabel", "begge"): tabel_navn = f"{tabel_prefix}{fil_del}" linjer.append(f" - tabel:") linjer.append(f" staging: {db_schema}.{tabel_navn}_tmp") linjer.append(f" blivende: {db_schema}.{tabel_navn}") linjer.append(f" historik: {historik}") linjer.append(f" # TODO: Angiv forretningsnøgler") linjer.append(f" forretnings_nøgler: [__NØGLE__]") linjer.append(f" tekniske_nøgler: [løbenummer]") linjer.append(f" ekstra_kolonner:") linjer.append(f" - navn: løbenummer") linjer.append(f' ddl_type: "int identity"') linjer.append(f" placering: start") linjer.append("") sti = os.path.join(output_mappe, fil_navn) with open(sti, "w", encoding="utf-8") as f: f.write("\n".join(linjer)) print(f" Skrev: {sti}") # ============================================================ # Generator: nøgler.yaml # ============================================================ def generer_nøgler_yaml( liste_elementer: list[XsdListeElement], output_mappe: str, forkortelser: dict[str, str] = {} ) -> None: # Find unikke overliggende niveauer overliggende: dict[str, str] = {} for el in liste_elementer: rod_dele = el.rod_sti.split(".") for ov_navn in el.overliggende: if ov_navn not in overliggende: try: idx = rod_dele.index(ov_navn) overliggende[ov_navn] = ".".join(rod_dele[:idx + 1]) except ValueError: overliggende[ov_navn] = f"__{ov_navn.upper()}__" if not overliggende: return linjer = [] linjer.append("# =============================================================================") linjer.append("# nøgler.yaml") linjer.append("#") linjer.append("# Nøgle-skabeloner der binder udtræk-filer til overliggende niveauer.") linjer.append("# UDFYLD: Erstat __FELT__ med den korrekte forretningsnøgle.") linjer.append("# =============================================================================") linjer.append("") linjer.append("kolonne_skabeloner:") linjer.append("") for ov_navn, ov_rod_sti in overliggende.items(): skabelon_navn = _anvend_forkortelser(f"{ov_navn.lower()}_nøgle", forkortelser) linjer.append(f" # Nøgle fra {ov_navn}-niveau") linjer.append(f" # TODO: Angiv den korrekte forretningsnøgle for {ov_navn}") linjer.append(f" {skabelon_navn}:") linjer.append(f" - navn: __FELT__") linjer.append(f" felt: \"__FELT__\" # fx \"@id\" eller \"nr\"") linjer.append(f" rod: {ov_rod_sti}") linjer.append("") sti = os.path.join(output_mappe, "nøgler.yaml") with open(sti, "w", encoding="utf-8") as f: f.write("\n".join(linjer)) print(f" Skrev: {sti}") def generer_udtræk_yaml( liste_elementer: list[XsdListeElement], komplekse_typer: dict[str, XsdKompleksType], output_mappe: str, prefix: str = "udtræk", min_felter: int = 1, forkortelser: dict[str, str] = {}, db_schema: str = "dbo", tabel_prefix: str = "", output_type: str = "begge", historik: str = "t2" ) -> None: # Beregn fælles prefix på tværs af alle rod-stier fælles_prefix_længde = _find_fælles_prefix(liste_elementer) fil_navne_index: dict[str, str] = {} for el in liste_elementer: rod_dele = el.rod_sti.split(".") unikke_dele = rod_dele[fælles_prefix_længde:] if len(rod_dele) > fælles_prefix_længde else rod_dele fil_del = _anvend_forkortelser("_".join(unikke_dele).lower(), forkortelser) if el.element_navn not in fil_navne_index: fil_navne_index[el.element_navn] = f"udtræk_{fil_del}.yaml" # Byg choice-grupper til kommentar-generering (ikke filnavne) choice_grupper = _byg_choice_grupper(liste_elementer) # Byg sæt af liste-element navne til udkommentering liste_navne = {el.element_navn for el in liste_elementer} for el in liste_elementer: # Byg unikt filnavn fra rod-stien minus fælles prefix rod_dele = el.rod_sti.split(".") unikke_dele = rod_dele[fælles_prefix_længde:] if len(rod_dele) > fælles_prefix_længde else rod_dele fil_del = _anvend_forkortelser( "_".join(unikke_dele).lower(), forkortelser ) fil_navn = f"{prefix}_{fil_del}.yaml" gruppe = choice_grupper.get(el.rod_sti) linjer = [] linjer.append("# =============================================================================") linjer.append(f"# {fil_navn}") linjer.append("#") linjer.append(f"# Auto-genereret udtræk for {el.element_navn}.") linjer.append(f"# Rod-sti: {el.rod_sti}") if el.er_simpel: linjer.append("#") linjer.append(f"# OBS: Dette element er simpelt ({el.element_navn} har få felter).") linjer.append(f"# Det er foldet ind som join-kolonne i skabelon: {el.join_i_skabelon}") linjer.append(f"# Denne fil er udkommenteret i config – fjern udkommentering for fuldt udtræk.") if el.overliggende: linjer.append("#") linjer.append("# Udfyld nøgle-skabeloner i nøgler.yaml inden brug.") if gruppe: linjer.append("#") linjer.append("# OBS: Dette element forekommer i flere choice-grene:") for valg in gruppe['valg']: sti = f"{gruppe['fælles_rod']}.{valg}.{gruppe['element_navn']}" linjer.append(f"# - {sti}") linjer.append("# Disse kan samles i én fil ved at ændre rod til en rod med varianter:") linjer.append(f"# rod: {gruppe['samlet_rod']}") linjer.append("# Tilføj evt. en kolonne til at skelne grenene:") linjer.append("# - navn: bruger_type") linjer.append("# type: rod_variant") linjer.append("# =============================================================================") linjer.append("") linjer.append("output_filer:") linjer.append("") linjer.append(f" - rod: {el.rod_sti}") linjer.append(f" kolonner:") # Nøgler if el.overliggende: linjer.append(f" # Nøgler fra overliggende niveauer – udfyld i nøgler.yaml") for ov_navn in el.overliggende: skabelon_navn = _anvend_forkortelser( f"{ov_navn.lower()}_nøgle", forkortelser ) linjer.append(f" - skabelon: {skabelon_navn}") linjer.append("") # Felter fra elementets type eller inline felter type_navn_rent = _strip_prefix(el.type_navn) if el.type_navn else "" kt = komplekse_typer.get(type_navn_rent) if kt and kt.felter and not kt.er_ekstern: skabelon_navn = type_navn_rent.replace("_Type", "").replace("Type", "").lower() linjer.append(f" # Felter fra {el.element_navn} – se skabeloner.yaml") linjer.append(f" - skabelon: {skabelon_navn}") elif el.felter: linjer.append(f" # Felter fra {el.element_navn}") for felt in el.felter: if isinstance(felt, XsdSkabelonRef): linjer.extend(_skriv_skabelon_ref( felt, " ", forkortelser, liste_navne, fil_navne_index=fil_navne_index )) elif isinstance(felt, XsdFelt): linjer.extend(_skriv_felt( felt, " ", forkortelser, liste_navne # ← tilføj liste_navne )) elif el.er_simpel: linjer.append(f" # Feltets egen værdi") linjer.append(f" - navn: {el.element_navn}") linjer.append(f" felt: \".\"") linjer.append("") linjer.append(f" outputs:") if output_type in ("fil", "begge"): linjer.append(f" - fil_navn: \"{fil_del}_{{yyyy}}{{mm}}{{dd}}.txt\"") linjer.append(f" overskrifter: true") linjer.append("") if output_type in ("tabel", "begge"): tabel_navn = f"{tabel_prefix}{fil_del}" linjer.append(f" - tabel:") linjer.append(f" staging: {db_schema}.{tabel_navn}_tmp") linjer.append(f" blivende: {db_schema}.{tabel_navn}") linjer.append(f" historik: {historik}") linjer.append(f" # TODO: Angiv forretningsnøgler") linjer.append(f" forretnings_nøgler: [__NØGLE__]") linjer.append(f" tekniske_nøgler: [løbenummer]") linjer.append(f" ekstra_kolonner:") linjer.append(f" - navn: løbenummer") linjer.append(f' ddl_type: "int identity"') linjer.append(f" placering: start") linjer.append("") linjer.append("") sti = os.path.join(output_mappe, fil_navn) with open(sti, "w", encoding="utf-8") as f: f.write("\n".join(linjer)) print(f" Skrev: {sti}") # ============================================================ # Generator: config_xxx.yaml # ============================================================ def generer_hoved_config( liste_elementer: list[XsdListeElement], xsd_sti: str, output_mappe: str, prefix: str = "udtræk", forkortelser: dict[str, str] = {} ) -> None: xsd_basis = os.path.splitext(os.path.basename(xsd_sti))[0] # Beregn fælles prefix – samme logik som generer_udtræk_yaml fælles_prefix_længde = _find_fælles_prefix(liste_elementer) linjer = [] linjer.append("# =============================================================================") linjer.append(f"# config_{xsd_basis}.yaml") linjer.append("#") linjer.append("# Auto-genereret hoved-config.") linjer.append("# Tilpas config-sektionen med korrekte stier og indstillinger.") linjer.append("# =============================================================================") linjer.append("") linjer.append("include:") linjer.append(" - skabeloner.yaml") linjer.append(" - nøgler.yaml") linjer.append("") normale = [] simple = [] for el in liste_elementer: rod_dele = el.rod_sti.split(".") unikke_dele = rod_dele[fælles_prefix_længde:] if len(rod_dele) > fælles_prefix_længde else rod_dele fil_del = _anvend_forkortelser( "_".join(unikke_dele).lower(), forkortelser ) fil = f"{prefix}_{fil_del}.yaml" if el.er_simpel: simple.append((fil, el)) else: normale.append((fil, el)) for fil, _ in normale: linjer.append(f" - {fil}") if simple: linjer.append("") linjer.append(" # Simple lister – foldet ind som join-kolonner i skabelonerne:") linjer.append(" # Fjern udkommentering for fuldt udtræk i stedet for join.") for fil, el in simple: linjer.append(f" # - {fil} (join i skabelon: {el.join_i_skabelon})") linjer.append("") linjer.append("config:") linjer.append(f" input_fil: {xsd_basis}.xml") linjer.append(" output_path: __OUTPUT_PATH__") linjer.append(" logfil: log_{yyyy}{mm}{dd}.txt") linjer.append(" log_niveau: info") linjer.append(" log_output: begge") linjer.append(" encoding: utf-8") linjer.append(' separator: "\\t"') linjer.append(" skrivetilstand: w") linjer.append(' dato_ind: "%Y-%m-%d"') linjer.append(' dato_ud: "%d-%m-%Y"') sti = os.path.join(output_mappe, f"config_{xsd_basis}.yaml") with open(sti, "w", encoding="utf-8") as f: f.write("\n".join(linjer)) print(f" Skrev: {sti}") def _strip_prefix(type_navn: str) -> str: if not type_navn or ":" not in type_navn: return type_navn prefix, lokalt = type_navn.split(":", 1) if prefix in ("xs", "xsd"): return type_navn return lokalt