fundamend


Namefundamend JSON
Version 0.23.1 PyPI version JSON
download
home_pageNone
SummaryXML basierte Formate und DatemModelle für die Energiewirtschaft in Deutschland
upload_time2025-10-10 06:19:59
maintainerNone
docs_urlNone
authorNone
requires_python>=3.11
licenseMIT
keywords ahb bdew mig marktkommunikation xml
VCS
bugtrack_url
requirements annotated-types efoli pydantic pydantic-core pytz typing-extensions typing-inspection
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # FUNDAMEND - Formate und DAtenModelle für die ENergiewirtschaft in Deutschland

Dieses Repository enthält das Python-Paket `fundamend`, das XML-basierte MIGs und AHBs als Python-Objekte einliest.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
![Python Versions (officially) supported](https://img.shields.io/pypi/pyversions/fundamend.svg)
![Pypi status badge](https://img.shields.io/pypi/v/fundamend)
![Unittests status badge](https://github.com/Hochfrequenz/xml-fundamend-python/workflows/Unittests/badge.svg)
![Coverage status badge](https://github.com/Hochfrequenz/xml-fundamend-python/workflows/Coverage/badge.svg)
![Linting status badge](https://github.com/Hochfrequenz/xml-fundamend-python/workflows/Linting/badge.svg)
![Black status badge](https://github.com/Hochfrequenz/xml-fundamend-python/workflows/Formatting/badge.svg)

## Sinn und Zweck
Seit 2024 bietet der BDEW (endlich) maschinenlesbare MIG- und AHB-Spezifikationen an, wo zuvor nur PDF oder Word-Dateien veröffentlicht wurden.
Das ist ein wichtiger Schritt für eine echte Digitalisierung der Marktkommunikation im deutschen Energiemarkt.

Die nun maschinenlesbaren Informationen über den Aufbau von EDIFACT-Nachrichten sind XML-basiert.

Dieses Repository enthält ein kleines Python-Paket, das die XML-Dateien einliest und als vollständig typisierte Python-Objekte zur Verfügung stellt, damit sich niemand mit XML herumschlagen muss (also am Ende des Tages Model Binding).
Das ist alles.

Hochfrequenz stellt mit [migmose](https://github.com/Hochfrequenz/migmose) und [kohlrahbi](https://github.com/Hochfrequenz/kohlrahbi) auch Tools bereit, um maschinenlesbare MIGs bzw. AHBs aus `.docx`-Dateien zu scrapen.

## Installation und Verwendung
Das Paket ist auf PyPI verfügbar und kann mit pip installiert werden:
```bash
pip install fundamend
```

### Message Implementation Guides (MIG) deserialisieren
```python
from pathlib import Path
from fundamend import MigReader, MessageImplementationGuide

# Angenommen, mig_utilts.xml enthält:
# <?xml version="1.0" encoding="UTF-8"?>
# <M_UTILTS Versionsnummer="1.1c"
#    Veroeffentlichungsdatum="24.10.2023"
#    Author="BDEW">
# ...
# </M_UTILTS>

reader = MigReader(Path("pfad/zur/mig_utils.xml"))
mig = reader.read()
assert isinstance(mig, MessageImplementationGuide)
assert mig.format == "UTILTS"
```

### Anwendungshandbuch (AHB) deserialisieren
```python
from pathlib import Path
from fundamend import AhbReader, Anwendungshandbuch

# Angenommen, ahb_utilts.xml enthält:
# <?xml version="1.0" encoding="UTF-8"?>
# <AHB Versionsnummer="1.1d"
#    Veroeffentlichungsdatum="02.04.2024"
#    Author="BDEW">
#    <AWF Pruefidentifikator="25001" Beschreibung="Berechnungsformel" Kommunikation_von="NB an MSB / LF">
#    ...
#   </AWF>
# </AHB>

reader = AhbReader(Path("pfad/zur/ahb_utils.xml"))
ahb = reader.read()
assert isinstance(ahb, Anwendungshandbuch)
assert {awf.pruefidentifikator for awf in ahb.anwendungsfaelle} == {
    "25001",
    "25002",
    "25003",
    "25004",
    "25005",
    "25006",
    "25007",
    "25008",
    "25009",
}
```

Die vollständigen Beispiele finden sich in den [unittests](unittests):
- Beispiel [AHB UTILTS](unittests/example_ahb_utilts_11d.py)
- Beispiel [MIG UTILTS](https://github.com/Hochfrequenz/xml-fundamend-python/blob/main/unittests/example_migs.py)

### Pydantic
Die Datenmodelle, die von `AhbReader` und `MigReader` zurückgegeben werden, sind pydantic Objekte.

Mit Pydantic können die Ergebnisse auch leicht bspw. als JSON exportiert werden (was auch über ein CLI-Tool im nächsten Abschnitt) noch einfacher möglich ist.
```python
from pathlib import Path

from pydantic import RootModel
from fundamend import Anwendungshandbuch, AhbReader

ahb = AhbReader(Path("UTILTS_AHB_1.1d_Konsultationsfassung_2024_04_02.xml")).read()
ahb_json = RootModel[Anwendungshandbuch](ahb).model_dump(mode="json")
```

Das Ergebnis sieht dann so aus:
```json
{
  "veroeffentlichungsdatum": "2024-04-02",
  "autor": "BDEW",
  "versionsnummer": "1.1d",
  "anwendungsfaelle": [
    {
      "pruefidentifikator": "25001",
      "beschreibung": "Berechnungsformel",
      "kommunikation_von": "NB an MSB / LF",
      "format": "UTILTS",
      "segments": [
        {
          "id": "UNH",
          "name": "Nachrichten-Kopfsegment",
          "number": "00001",
          "ahb_status": "Muss",
          "data_elements": [
            {
              "id": "D_0062",
              "name": "Nachrichten-Referenznummer",
              "codes": []
            },
```

### SQL Models
Die Daten aus den XML-Dateien (Stand 2025-02-10 nur AHBs) lassen sich auch in Datenbanken persistieren.
Die dazu verwendeten [SQLModel](https://sqlmodel.tiangolo.com/)-Klassen lassen sich mit `fundamend[sqlmodel]` installieren.
Instanzen der Pydantic-Klassen lassen sich in SQL-Models überführen und umgekehrt:
```python
from fundamend.models.anwendungshandbuch import Anwendungshandbuch as PydanticAnwendunghandbuch
from fundamend.sqlmodels.anwendungshandbuch import Anwendungshandbuch as SqlAnwendungshandbuch

my_sql_model = SqlAnwendungshandbuch.from_model(pydantic_ahb)
pydantic_ahb = my_sql_model.to_model()
```

#### Befüllen einer Datenbank mit AHB-Informationen
In den XML-Rohdaten sind die Informationen aus den AHBs theoretisch beliebig tief verschachtelt, weil jede Segmentgruppe ihrerseits wieder Segmentgruppen enthalten kann.
Diese Rekursion ist so auch in den SQL-Model-Klassen und der Datenbank abgebildet.
Dieses Paket liefert eine Hilfsfunktion, die die AHBs wieder "flach" zieht, sodass die Datenstruktur mit den flachen AHBs aus bspw. den PDF-Dateien vergleichbar ist, ohne jedoch die Strukturinformationen zu verlieren.
Dazu wird eine rekursive Common Table Expression (CTE) verwendet, um eine zusätzliche Hilfstabelle `ahb_hierarchy_materialized` zu befüllen.

Die Möglichkeiten einer solchen AHB-Datenbank mit Strukturinformationen (die es in der Form in den PDF-AHBs nicht gibt) schafft viele denkbare Anwendungen.
Was wenn man die Datenbank als Grundlage nähme, um eine Frontend für AHBs zu bauen, das bequemer nutzbar ist als PDFs mit mehr als 1000 Seiten in denen man nur schlecht suchen kann? Das gibt es: [ahbesser](https://github.com/Hochfrequenz/ahbesser) aka [AHB-Tabellen](https://ahb-tabellen.hochfrequenz.de/).
Was wenn man die Datenbank als Grundlage nähme, um ein Frontend zu bauen, das AHBs in verschiedenen Versionen vergleicht und einen lesbaren Diff erzeugt der anders als die Änderungshistorie der PDFs sogar vollständig ist? Das gibt es: [ahlbatross](https://github.com/Hochfrequenz/ahlbatross).

```python
# pip install fundamend[sqlmodel]
from pathlib import Path
from fundamend.sqlmodels.ahbview import create_db_and_populate_with_ahb_view, AhbHierarchyMaterialized
from sqlmodel import Session, create_engine, select

ahb_paths = [
    Path("UTILTS_AHB_1.1c_Lesefassung_2023_12_12_ZPbXedn.xml"),
    # add more AHB XML files here
]
sqlite_file = create_db_and_populate_with_ahb_view(ahb_paths)  # copy the file to somewhere else if necessary
engine = create_engine(f"sqlite:///{sqlite_file}")
with Session(bind=engine) as session:
    stmt = select(AhbHierarchyMaterialized).where(AhbHierarchyMaterialized.pruefidentifikator == "25001").order_by(
        AhbHierarchyMaterialized.sort_path
    )
    results = session.exec(stmt).all()
```
oder in plain SQL:
```sql
-- sqlite dialect
SELECT path,
       type,
       segmentgroup_name,
       segmentgroup_ahb_status,
       segment_id,
       segment_name,
       segment_ahb_status,
       dataelementgroup_id,
       dataelementgroup_name,
       dataelement_id,
       dataelement_name,
       dataelement_ahb_status,
       code_value,
       code_name,
       code_ahb_status
FROM ahb_hierarchy_materialized
WHERE pruefidentifikator = '25001'
ORDER BY sort_path;
```
<details>
<summary>Ergebnisse des `SELECT`</summary>
<br>
... 125 andere Zeilen ...

| path | type | segmentgroup\_name | segmentgroup\_ahb\_status | segment\_id | segment\_name | segment\_ahb\_status | dataelementgroup\_id | dataelementgroup\_name | dataelement\_id | dataelement\_name | dataelement\_ahb\_status | code\_value |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| Vorgang &gt; Bestandteil des Rechenschritts | segment\_group | Bestandteil des Rechenschritts | Muss \[2006\] | null | null | null | null | null | null | null | null | null |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts | segment | Bestandteil des Rechenschritts | Muss \[2006\] | SEQ | Bestandteil des Rechenschritts | Muss | null | null | null | null | null | null |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts &gt; Handlung, Code | dataelement | Bestandteil des Rechenschritts | Muss \[2006\] | SEQ | Bestandteil des Rechenschritts | Muss | null | null | D\_1229 | Handlung, Code | null | null |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts &gt; Handlung, Code &gt; Bestandteil des Rechenschritts | code | Bestandteil des Rechenschritts | Muss \[2006\] | SEQ | Bestandteil des Rechenschritts | Muss | null | null | D\_1229 | Handlung, Code | null | Z37 |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts &gt; Information über eine Folge | dataelementgroup | Bestandteil des Rechenschritts | Muss \[2006\] | SEQ | Bestandteil des Rechenschritts | Muss | C\_C286 | Information über eine Folge | null | null | null | null |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts &gt; Information über eine Folge &gt; Rechenschrittidentifikator | dataelement | Bestandteil des Rechenschritts | Muss \[2006\] | SEQ | Bestandteil des Rechenschritts | Muss | C\_C286 | Information über eine Folge | D\_1050 | Rechenschrittidentifikator | X \[913\] | null |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID | segment | Bestandteil des Rechenschritts | Muss \[2006\] | RFF | Referenz auf eine Zeitraum-ID | Muss | null | null | null | null | null | null |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID &gt; Referenz | dataelementgroup | Bestandteil des Rechenschritts | Muss \[2006\] | RFF | Referenz auf eine Zeitraum-ID | Muss | C\_C506 | Referenz | null | null | null | null |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID &gt; Referenz &gt; Referenz, Qualifier | dataelement | Bestandteil des Rechenschritts | Muss \[2006\] | RFF | Referenz auf eine Zeitraum-ID | Muss | C\_C506 | Referenz | D\_1153 | Referenz, Qualifier | null | null |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID &gt; Referenz &gt; Referenz, Qualifier &gt; Referenz auf Zeitraum-ID | code | Bestandteil des Rechenschritts | Muss \[2006\] | RFF | Referenz auf eine Zeitraum-ID | Muss | C\_C506 | Referenz | D\_1153 | Referenz, Qualifier | null | Z46 |
| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID &gt; Referenz &gt; Referenz auf Zeitraum-ID | dataelement | Bestandteil des Rechenschritts | Muss \[2006\] | RFF | Referenz auf eine Zeitraum-ID | Muss | C\_C506 | Referenz | D\_1154 | Referenz auf Zeitraum-ID | X \[914\] ∧ \[937\] \[59\] | null |

...
</details>

<details>
<summary>Finde heraus, welche Zeilen in einem Prüfidentifikator zwischen zwei Versionen hinzukommen</summary>
<br>

```sql
    with fv2504 as (SELECT *
                FROM ahb_hierarchy_materialized
                WHERE pruefidentifikator = '55014'
                  and edifact_format_version = 'FV2504'
                ORDER BY sort_path ASC),
     fv2410 as (SELECT *
                FROM ahb_hierarchy_materialized
                WHERE pruefidentifikator = '55014'
                  and edifact_format_version = 'FV2410'
                ORDER BY sort_path ASC)
SELECT fv2504.path
FROM fv2504
         LEFT JOIN fv2410 on fv2504.id_path = fv2410.id_path
WHERE fv2410.id is null -- alle zeilen, die so im fv2410 ahb nicht vorhanden waren
ORDER BY fv2504.sort_path;
```

</details>

### CLI Tool für XML➡️JSON Konvertierung
Mit
```bash
pip install fundamend[cli]
```
Kann ein CLI-Tool in der entsprechenden venv installiert werden, das einzelne MIG- und AHB-XML-Dateien in entsprechende JSONs konvertiert:
```bash
(myvenv): fundamend xml2json --xml-path path/to/mig.xml
```
erzeugt `path/to/mig.json`. Und
```bash
(myvenv): fundamend xml2json --xml-path path/to/my/directory
```
konvertiert alle XML-Dateien im entsprechenden Verzeichnis.

### JSON Schemas
Das fundamend Datenmodell ist auch als JSON Schema verfügbar: [`json_schemas`](json_schemas).

## Verwendung und Mitwirken
Der Code ist MIT-lizenziert und kann daher frei verwendet werden.
Wir freuen uns über Pull Requests an den main-Branch dieses Repositories.

## Hochfrequenz
Die [Hochfrequenz Unternehmensberatung GmbH](https://www.hochfrequenz.de) ist eine Beratung für Energieversorger im deutschsprachigen Raum.
Wir arbeiten größtenteils remote, haben aber auch Büros in Berlin, Bremen, Leipzig, Köln und Grünwald und attraktive [Stellenangebote](https://www.hochfrequenz.de/index.php/karriere/aktuelle-stellenausschreibungen/full-stack-entwickler).

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "fundamend",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": null,
    "keywords": "AHB, BDEW, MIG, Marktkommunikation, XML",
    "author": null,
    "author_email": "Hochfrequenz Unternehmensberatung GmbH <info+github@hochfrequenz.de>",
    "download_url": "https://files.pythonhosted.org/packages/43/5f/e49e689636c4573ad23d3d8503924026e030b5baf4d70bdbbdd427e190ba/fundamend-0.23.1.tar.gz",
    "platform": null,
    "description": "# FUNDAMEND - Formate und DAtenModelle f\u00fcr die ENergiewirtschaft in Deutschland\n\nDieses Repository enth\u00e4lt das Python-Paket `fundamend`, das XML-basierte MIGs und AHBs als Python-Objekte einliest.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n![Python Versions (officially) supported](https://img.shields.io/pypi/pyversions/fundamend.svg)\n![Pypi status badge](https://img.shields.io/pypi/v/fundamend)\n![Unittests status badge](https://github.com/Hochfrequenz/xml-fundamend-python/workflows/Unittests/badge.svg)\n![Coverage status badge](https://github.com/Hochfrequenz/xml-fundamend-python/workflows/Coverage/badge.svg)\n![Linting status badge](https://github.com/Hochfrequenz/xml-fundamend-python/workflows/Linting/badge.svg)\n![Black status badge](https://github.com/Hochfrequenz/xml-fundamend-python/workflows/Formatting/badge.svg)\n\n## Sinn und Zweck\nSeit 2024 bietet der BDEW (endlich) maschinenlesbare MIG- und AHB-Spezifikationen an, wo zuvor nur PDF oder Word-Dateien ver\u00f6ffentlicht wurden.\nDas ist ein wichtiger Schritt f\u00fcr eine echte Digitalisierung der Marktkommunikation im deutschen Energiemarkt.\n\nDie nun maschinenlesbaren Informationen \u00fcber den Aufbau von EDIFACT-Nachrichten sind XML-basiert.\n\nDieses Repository enth\u00e4lt ein kleines Python-Paket, das die XML-Dateien einliest und als vollst\u00e4ndig typisierte Python-Objekte zur Verf\u00fcgung stellt, damit sich niemand mit XML herumschlagen muss (also am Ende des Tages Model Binding).\nDas ist alles.\n\nHochfrequenz stellt mit [migmose](https://github.com/Hochfrequenz/migmose) und [kohlrahbi](https://github.com/Hochfrequenz/kohlrahbi) auch Tools bereit, um maschinenlesbare MIGs bzw. AHBs aus `.docx`-Dateien zu scrapen.\n\n## Installation und Verwendung\nDas Paket ist auf PyPI verf\u00fcgbar und kann mit pip installiert werden:\n```bash\npip install fundamend\n```\n\n### Message Implementation Guides (MIG) deserialisieren\n```python\nfrom pathlib import Path\nfrom fundamend import MigReader, MessageImplementationGuide\n\n# Angenommen, mig_utilts.xml enth\u00e4lt:\n# <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n# <M_UTILTS Versionsnummer=\"1.1c\"\n#    Veroeffentlichungsdatum=\"24.10.2023\"\n#    Author=\"BDEW\">\n# ...\n# </M_UTILTS>\n\nreader = MigReader(Path(\"pfad/zur/mig_utils.xml\"))\nmig = reader.read()\nassert isinstance(mig, MessageImplementationGuide)\nassert mig.format == \"UTILTS\"\n```\n\n### Anwendungshandbuch (AHB) deserialisieren\n```python\nfrom pathlib import Path\nfrom fundamend import AhbReader, Anwendungshandbuch\n\n# Angenommen, ahb_utilts.xml enth\u00e4lt:\n# <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n# <AHB Versionsnummer=\"1.1d\"\n#    Veroeffentlichungsdatum=\"02.04.2024\"\n#    Author=\"BDEW\">\n#    <AWF Pruefidentifikator=\"25001\" Beschreibung=\"Berechnungsformel\" Kommunikation_von=\"NB an MSB / LF\">\n#    ...\n#   </AWF>\n# </AHB>\n\nreader = AhbReader(Path(\"pfad/zur/ahb_utils.xml\"))\nahb = reader.read()\nassert isinstance(ahb, Anwendungshandbuch)\nassert {awf.pruefidentifikator for awf in ahb.anwendungsfaelle} == {\n    \"25001\",\n    \"25002\",\n    \"25003\",\n    \"25004\",\n    \"25005\",\n    \"25006\",\n    \"25007\",\n    \"25008\",\n    \"25009\",\n}\n```\n\nDie vollst\u00e4ndigen Beispiele finden sich in den [unittests](unittests):\n- Beispiel [AHB UTILTS](unittests/example_ahb_utilts_11d.py)\n- Beispiel [MIG UTILTS](https://github.com/Hochfrequenz/xml-fundamend-python/blob/main/unittests/example_migs.py)\n\n### Pydantic\nDie Datenmodelle, die von `AhbReader` und `MigReader` zur\u00fcckgegeben werden, sind pydantic Objekte.\n\nMit Pydantic k\u00f6nnen die Ergebnisse auch leicht bspw. als JSON exportiert werden (was auch \u00fcber ein CLI-Tool im n\u00e4chsten Abschnitt) noch einfacher m\u00f6glich ist.\n```python\nfrom pathlib import Path\n\nfrom pydantic import RootModel\nfrom fundamend import Anwendungshandbuch, AhbReader\n\nahb = AhbReader(Path(\"UTILTS_AHB_1.1d_Konsultationsfassung_2024_04_02.xml\")).read()\nahb_json = RootModel[Anwendungshandbuch](ahb).model_dump(mode=\"json\")\n```\n\nDas Ergebnis sieht dann so aus:\n```json\n{\n  \"veroeffentlichungsdatum\": \"2024-04-02\",\n  \"autor\": \"BDEW\",\n  \"versionsnummer\": \"1.1d\",\n  \"anwendungsfaelle\": [\n    {\n      \"pruefidentifikator\": \"25001\",\n      \"beschreibung\": \"Berechnungsformel\",\n      \"kommunikation_von\": \"NB an MSB / LF\",\n      \"format\": \"UTILTS\",\n      \"segments\": [\n        {\n          \"id\": \"UNH\",\n          \"name\": \"Nachrichten-Kopfsegment\",\n          \"number\": \"00001\",\n          \"ahb_status\": \"Muss\",\n          \"data_elements\": [\n            {\n              \"id\": \"D_0062\",\n              \"name\": \"Nachrichten-Referenznummer\",\n              \"codes\": []\n            },\n```\n\n### SQL Models\nDie Daten aus den XML-Dateien (Stand 2025-02-10 nur AHBs) lassen sich auch in Datenbanken persistieren.\nDie dazu verwendeten [SQLModel](https://sqlmodel.tiangolo.com/)-Klassen lassen sich mit `fundamend[sqlmodel]` installieren.\nInstanzen der Pydantic-Klassen lassen sich in SQL-Models \u00fcberf\u00fchren und umgekehrt:\n```python\nfrom fundamend.models.anwendungshandbuch import Anwendungshandbuch as PydanticAnwendunghandbuch\nfrom fundamend.sqlmodels.anwendungshandbuch import Anwendungshandbuch as SqlAnwendungshandbuch\n\nmy_sql_model = SqlAnwendungshandbuch.from_model(pydantic_ahb)\npydantic_ahb = my_sql_model.to_model()\n```\n\n#### Bef\u00fcllen einer Datenbank mit AHB-Informationen\nIn den XML-Rohdaten sind die Informationen aus den AHBs theoretisch beliebig tief verschachtelt, weil jede Segmentgruppe ihrerseits wieder Segmentgruppen enthalten kann.\nDiese Rekursion ist so auch in den SQL-Model-Klassen und der Datenbank abgebildet.\nDieses Paket liefert eine Hilfsfunktion, die die AHBs wieder \"flach\" zieht, sodass die Datenstruktur mit den flachen AHBs aus bspw. den PDF-Dateien vergleichbar ist, ohne jedoch die Strukturinformationen zu verlieren.\nDazu wird eine rekursive Common Table Expression (CTE) verwendet, um eine zus\u00e4tzliche Hilfstabelle `ahb_hierarchy_materialized` zu bef\u00fcllen.\n\nDie M\u00f6glichkeiten einer solchen AHB-Datenbank mit Strukturinformationen (die es in der Form in den PDF-AHBs nicht gibt) schafft viele denkbare Anwendungen.\nWas wenn man die Datenbank als Grundlage n\u00e4hme, um eine Frontend f\u00fcr AHBs zu bauen, das bequemer nutzbar ist als PDFs mit mehr als 1000 Seiten in denen man nur schlecht suchen kann? Das gibt es: [ahbesser](https://github.com/Hochfrequenz/ahbesser) aka [AHB-Tabellen](https://ahb-tabellen.hochfrequenz.de/).\nWas wenn man die Datenbank als Grundlage n\u00e4hme, um ein Frontend zu bauen, das AHBs in verschiedenen Versionen vergleicht und einen lesbaren Diff erzeugt der anders als die \u00c4nderungshistorie der PDFs sogar vollst\u00e4ndig ist? Das gibt es: [ahlbatross](https://github.com/Hochfrequenz/ahlbatross).\n\n```python\n# pip install fundamend[sqlmodel]\nfrom pathlib import Path\nfrom fundamend.sqlmodels.ahbview import create_db_and_populate_with_ahb_view, AhbHierarchyMaterialized\nfrom sqlmodel import Session, create_engine, select\n\nahb_paths = [\n    Path(\"UTILTS_AHB_1.1c_Lesefassung_2023_12_12_ZPbXedn.xml\"),\n    # add more AHB XML files here\n]\nsqlite_file = create_db_and_populate_with_ahb_view(ahb_paths)  # copy the file to somewhere else if necessary\nengine = create_engine(f\"sqlite:///{sqlite_file}\")\nwith Session(bind=engine) as session:\n    stmt = select(AhbHierarchyMaterialized).where(AhbHierarchyMaterialized.pruefidentifikator == \"25001\").order_by(\n        AhbHierarchyMaterialized.sort_path\n    )\n    results = session.exec(stmt).all()\n```\noder in plain SQL:\n```sql\n-- sqlite dialect\nSELECT path,\n       type,\n       segmentgroup_name,\n       segmentgroup_ahb_status,\n       segment_id,\n       segment_name,\n       segment_ahb_status,\n       dataelementgroup_id,\n       dataelementgroup_name,\n       dataelement_id,\n       dataelement_name,\n       dataelement_ahb_status,\n       code_value,\n       code_name,\n       code_ahb_status\nFROM ahb_hierarchy_materialized\nWHERE pruefidentifikator = '25001'\nORDER BY sort_path;\n```\n<details>\n<summary>Ergebnisse des `SELECT`</summary>\n<br>\n... 125 andere Zeilen ...\n\n| path | type | segmentgroup\\_name | segmentgroup\\_ahb\\_status | segment\\_id | segment\\_name | segment\\_ahb\\_status | dataelementgroup\\_id | dataelementgroup\\_name | dataelement\\_id | dataelement\\_name | dataelement\\_ahb\\_status | code\\_value |\n| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |\n| Vorgang &gt; Bestandteil des Rechenschritts | segment\\_group | Bestandteil des Rechenschritts | Muss \\[2006\\] | null | null | null | null | null | null | null | null | null |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts | segment | Bestandteil des Rechenschritts | Muss \\[2006\\] | SEQ | Bestandteil des Rechenschritts | Muss | null | null | null | null | null | null |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts &gt; Handlung, Code | dataelement | Bestandteil des Rechenschritts | Muss \\[2006\\] | SEQ | Bestandteil des Rechenschritts | Muss | null | null | D\\_1229 | Handlung, Code | null | null |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts &gt; Handlung, Code &gt; Bestandteil des Rechenschritts | code | Bestandteil des Rechenschritts | Muss \\[2006\\] | SEQ | Bestandteil des Rechenschritts | Muss | null | null | D\\_1229 | Handlung, Code | null | Z37 |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts &gt; Information \u00fcber eine Folge | dataelementgroup | Bestandteil des Rechenschritts | Muss \\[2006\\] | SEQ | Bestandteil des Rechenschritts | Muss | C\\_C286 | Information \u00fcber eine Folge | null | null | null | null |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Bestandteil des Rechenschritts &gt; Information \u00fcber eine Folge &gt; Rechenschrittidentifikator | dataelement | Bestandteil des Rechenschritts | Muss \\[2006\\] | SEQ | Bestandteil des Rechenschritts | Muss | C\\_C286 | Information \u00fcber eine Folge | D\\_1050 | Rechenschrittidentifikator | X \\[913\\] | null |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID | segment | Bestandteil des Rechenschritts | Muss \\[2006\\] | RFF | Referenz auf eine Zeitraum-ID | Muss | null | null | null | null | null | null |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID &gt; Referenz | dataelementgroup | Bestandteil des Rechenschritts | Muss \\[2006\\] | RFF | Referenz auf eine Zeitraum-ID | Muss | C\\_C506 | Referenz | null | null | null | null |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID &gt; Referenz &gt; Referenz, Qualifier | dataelement | Bestandteil des Rechenschritts | Muss \\[2006\\] | RFF | Referenz auf eine Zeitraum-ID | Muss | C\\_C506 | Referenz | D\\_1153 | Referenz, Qualifier | null | null |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID &gt; Referenz &gt; Referenz, Qualifier &gt; Referenz auf Zeitraum-ID | code | Bestandteil des Rechenschritts | Muss \\[2006\\] | RFF | Referenz auf eine Zeitraum-ID | Muss | C\\_C506 | Referenz | D\\_1153 | Referenz, Qualifier | null | Z46 |\n| Vorgang &gt; Bestandteil des Rechenschritts &gt; Referenz auf eine Zeitraum-ID &gt; Referenz &gt; Referenz auf Zeitraum-ID | dataelement | Bestandteil des Rechenschritts | Muss \\[2006\\] | RFF | Referenz auf eine Zeitraum-ID | Muss | C\\_C506 | Referenz | D\\_1154 | Referenz auf Zeitraum-ID | X \\[914\\] \u2227 \\[937\\] \\[59\\] | null |\n\n...\n</details>\n\n<details>\n<summary>Finde heraus, welche Zeilen in einem Pr\u00fcfidentifikator zwischen zwei Versionen hinzukommen</summary>\n<br>\n\n```sql\n    with fv2504 as (SELECT *\n                FROM ahb_hierarchy_materialized\n                WHERE pruefidentifikator = '55014'\n                  and edifact_format_version = 'FV2504'\n                ORDER BY sort_path ASC),\n     fv2410 as (SELECT *\n                FROM ahb_hierarchy_materialized\n                WHERE pruefidentifikator = '55014'\n                  and edifact_format_version = 'FV2410'\n                ORDER BY sort_path ASC)\nSELECT fv2504.path\nFROM fv2504\n         LEFT JOIN fv2410 on fv2504.id_path = fv2410.id_path\nWHERE fv2410.id is null -- alle zeilen, die so im fv2410 ahb nicht vorhanden waren\nORDER BY fv2504.sort_path;\n```\n\n</details>\n\n### CLI Tool f\u00fcr XML\u27a1\ufe0fJSON Konvertierung\nMit\n```bash\npip install fundamend[cli]\n```\nKann ein CLI-Tool in der entsprechenden venv installiert werden, das einzelne MIG- und AHB-XML-Dateien in entsprechende JSONs konvertiert:\n```bash\n(myvenv): fundamend xml2json --xml-path path/to/mig.xml\n```\nerzeugt `path/to/mig.json`. Und\n```bash\n(myvenv): fundamend xml2json --xml-path path/to/my/directory\n```\nkonvertiert alle XML-Dateien im entsprechenden Verzeichnis.\n\n### JSON Schemas\nDas fundamend Datenmodell ist auch als JSON Schema verf\u00fcgbar: [`json_schemas`](json_schemas).\n\n## Verwendung und Mitwirken\nDer Code ist MIT-lizenziert und kann daher frei verwendet werden.\nWir freuen uns \u00fcber Pull Requests an den main-Branch dieses Repositories.\n\n## Hochfrequenz\nDie [Hochfrequenz Unternehmensberatung GmbH](https://www.hochfrequenz.de) ist eine Beratung f\u00fcr Energieversorger im deutschsprachigen Raum.\nWir arbeiten gr\u00f6\u00dftenteils remote, haben aber auch B\u00fcros in Berlin, Bremen, Leipzig, K\u00f6ln und Gr\u00fcnwald und attraktive [Stellenangebote](https://www.hochfrequenz.de/index.php/karriere/aktuelle-stellenausschreibungen/full-stack-entwickler).\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "XML basierte Formate und DatemModelle f\u00fcr die Energiewirtschaft in Deutschland",
    "version": "0.23.1",
    "project_urls": {
        "Changelog": "https://github.com/Hochfrequenz/xml-fundamend-python/releases",
        "Homepage": "https://github.com/Hochfrequenz/xml-fundamend-python"
    },
    "split_keywords": [
        "ahb",
        " bdew",
        " mig",
        " marktkommunikation",
        " xml"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "1eb039045c08c097fd4597ee1689b67024e42d439d2ac4db75877c77acd1c58f",
                "md5": "1ffbf764f791f27a2a633d728976c941",
                "sha256": "63ac987c74b6fdd73e9bb614cb990aec8f0f7fc91f4f7e00819be30000ecbaf4"
            },
            "downloads": -1,
            "filename": "fundamend-0.23.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1ffbf764f791f27a2a633d728976c941",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11",
            "size": 47137,
            "upload_time": "2025-10-10T06:19:57",
            "upload_time_iso_8601": "2025-10-10T06:19:57.965802Z",
            "url": "https://files.pythonhosted.org/packages/1e/b0/39045c08c097fd4597ee1689b67024e42d439d2ac4db75877c77acd1c58f/fundamend-0.23.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "435fe49e689636c4573ad23d3d8503924026e030b5baf4d70bdbbdd427e190ba",
                "md5": "a9277c94e359c98a1b305b58c5f80fc4",
                "sha256": "13744e1e069b8ad1568b3266a6cc05e07eaf26982a67871017bf8e02a4e56fb9"
            },
            "downloads": -1,
            "filename": "fundamend-0.23.1.tar.gz",
            "has_sig": false,
            "md5_digest": "a9277c94e359c98a1b305b58c5f80fc4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 47347,
            "upload_time": "2025-10-10T06:19:59",
            "upload_time_iso_8601": "2025-10-10T06:19:59.691220Z",
            "url": "https://files.pythonhosted.org/packages/43/5f/e49e689636c4573ad23d3d8503924026e030b5baf4d70bdbbdd427e190ba/fundamend-0.23.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-10 06:19:59",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Hochfrequenz",
    "github_project": "xml-fundamend-python",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "annotated-types",
            "specs": [
                [
                    "==",
                    "0.7.0"
                ]
            ]
        },
        {
            "name": "efoli",
            "specs": [
                [
                    "==",
                    "2.1.1"
                ]
            ]
        },
        {
            "name": "pydantic",
            "specs": [
                [
                    "==",
                    "2.12.0"
                ]
            ]
        },
        {
            "name": "pydantic-core",
            "specs": [
                [
                    "==",
                    "2.41.1"
                ]
            ]
        },
        {
            "name": "pytz",
            "specs": [
                [
                    "==",
                    "2025.2"
                ]
            ]
        },
        {
            "name": "typing-extensions",
            "specs": [
                [
                    "==",
                    "4.15.0"
                ]
            ]
        },
        {
            "name": "typing-inspection",
            "specs": [
                [
                    "==",
                    "0.4.2"
                ]
            ]
        }
    ],
    "tox": true,
    "lcname": "fundamend"
}
        
Elapsed time: 2.19317s