This commit is contained in:
2026-06-15 16:10:24 +02:00
parent 2bdac59676
commit 8142de5216
4 changed files with 790 additions and 1 deletions
+114
View File
@@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
"""
Roztřídí DASTA XML soubory do adresářové struktury podle DATA ODBĚRU.
Zdroj: u:\\Dropbox\\Ordinace\\pomoc\\DASTA\\*.xml
Cíl: U:\\DASTA_SUBGROUPS\\RRRR\\MM\\DD\\<soubor>.xml (kopie, originál zůstává)
Datum odběru = první element <dat_du> v souboru (první potomek prvního <vr>).
Hodnota má formát DTS (2016-06-20T08:00:00) nebo DT (2017-05-18T07:30)
v obou případech začíná YYYY-MM-DD, takže rok/měsíc/den čteme z prvních znaků.
Speciální případy:
_BEZ_DATUMU soubor neobsahuje žádný <dat_du>
_CHYBY soubor se nepodařilo naparsovat
Použití:
python roztrid_dle_odberu.py # zdroj = výchozí (Dropbox)
python roztrid_dle_odberu.py U:\\DASTA # jiný zdrojový adresář
python roztrid_dle_odberu.py U:\\DASTA --dry-run # jen vypíše, co by udělal
"""
from __future__ import annotations
import re
import shutil
import sys
from collections import Counter
from pathlib import Path
from xml.etree import ElementTree as ET
ZDROJ_VYCHOZI = Path(r"u:\dasta")
CIL = Path(r"U:\DASTA_SUBGROUPS")
# Záchytný regex pro případ, že ElementTree selže (poškozená hlavička apod.)
_RE_DAT_DU = re.compile(rb"<dat_du[^>]*>\s*(\d{4})-(\d{2})-(\d{2})")
def datum_odberu(cesta: Path) -> tuple[str, str, str] | None:
"""Vrátí (rok, měsíc, den) z prvního <dat_du>, nebo None když chybí."""
raw = cesta.read_bytes()
# Rychlá a robustní cesta: najdi první <dat_du> v bytech.
m = _RE_DAT_DU.search(raw)
if m:
return m.group(1).decode(), m.group(2).decode(), m.group(3).decode()
# Záloha přes ElementTree (kdyby byl dat_du formátovaný jinak)
try:
root = ET.fromstring(raw)
el = root.find(".//dat_du")
if el is not None and el.text:
d = el.text.strip()
return d[0:4], d[5:7], d[8:10]
except ET.ParseError:
raise
return None
def main() -> None:
dry = "--dry-run" in sys.argv
pozicni = [a for a in sys.argv[1:] if not a.startswith("--")]
zdroj = Path(pozicni[0]) if pozicni else ZDROJ_VYCHOZI
soubory = sorted(zdroj.glob("*.xml"))
print(f"Zdroj: {zdroj}")
print(f"Cíl: {CIL}")
print(f"Nalezeno souborů: {len(soubory)}"
f"{' [DRY-RUN]' if dry else ''}")
print("-" * 60)
if not dry:
CIL.mkdir(parents=True, exist_ok=True)
stat = Counter()
roky = Counter()
chyby: list[str] = []
for src in soubory:
try:
d = datum_odberu(src)
except ET.ParseError as e:
d = None
cilovy_dir = CIL / "_CHYBY"
chyby.append(f"{src.name}: parse error {e}")
stat["chyba"] += 1
else:
if d is None:
cilovy_dir = CIL / "_BEZ_DATUMU"
stat["bez_datumu"] += 1
else:
rok, mes, den = d
cilovy_dir = CIL / rok / mes / den
stat["ok"] += 1
roky[rok] += 1
dst = cilovy_dir / src.name
if dry:
continue
cilovy_dir.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst)
print("Hotovo:")
print(f" zařazeno dle data odběru : {stat['ok']}")
print(f" bez data (_BEZ_DATUMU) : {stat['bez_datumu']}")
print(f" chyby parsování (_CHYBY) : {stat['chyba']}")
if roky:
print("\nRozložení podle roku:")
for rok in sorted(roky):
print(f" {rok}: {roky[rok]}")
if chyby:
print("\nDetail chyb:")
for c in chyby:
print(f" {c}")
if __name__ == "__main__":
main()