1
0
Files
Rihards Gailums 8c2a006427 MK-noteikumi-as-Code 0.1: vienota datu struktūra MK noteikumiem un pirmie četri noteikumi
Datu struktūra schemas/mk-noteikumi-0.1.xsd; rīki convert.py (vestnesis.lv un likumi.lv), build_all.py (lejuplāde, pārveide, pārbaude pret avota lapu), validate.py. Noteikumi Nr. 322 (2006), Nr. 982 (2006), Nr. 635 (2023), Nr. 821 (2023) no oficiālās publikācijas — likumi.lv slēgts, vēlākie grozījumi nav iestrādāti. Datu līgums contracts/B19-mk-noteikumi.odcs.yaml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016679RwmHsuTFfxt26wP6rk
2026-10-22 17:38:04 +00:00

78 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Pārbauda visas data/*.xml datnes:
1. atbilst XSD schemas/mk-noteikumi-0.1.xsd (arī identifikatoru unikalitāte);
2. datnes nosaukums = noteikumu identifikators, un identifikators = gads un numurs no Act;
3. Source/SHA256 = sources/<id>.txt sha256;
4. katrs teksts (Text, Note, Title, LegalBasis, Lead, Item, Line, Heading) ir avota teksta datnē tādā pašā secībā;
5. katra elementa identifikators sākas ar noteikumu identifikatoru, punkta identifikators atbilst drukātajam numuram.
python3 tools/validate.py → kopsavilkums; izejas kods 1, ja kāda pārbaude neizdodas
"""
import glob
import hashlib
import os
import re
import sys
from lxml import etree
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
NS = {"n": "urn:pppa:vpk:mk-noteikumi:0.1"}
SUPC = "⁰¹²³⁴⁵⁶⁷⁸⁹"
schema = etree.XMLSchema(etree.parse(f"{ROOT}/schemas/mk-noteikumi-0.1.xsd"))
def pid(num):
return "p" + re.sub("[" + SUPC + "]+", lambda m: "s" + m.group(0).translate(str.maketrans(SUPC, "0123456789")), num)
def check(path):
errs = []
doc = etree.parse(path)
if not schema.validate(doc):
errs += [f"XSD: {e.message}" for e in list(schema.error_log)[:5]]
r = doc.getroot()
did = r.get("id")
if os.path.basename(path) != f"{did}.xml":
errs.append(f"datnes nosaukums {os.path.basename(path)} ≠ {did}.xml")
num, adopted = r.findtext("n:Act/n:Number", namespaces=NS), r.findtext("n:Act/n:Adopted", namespaces=NS) or ""
if did != f"lv-mkn-{adopted[:4]}-{num}":
errs.append(f"identifikators {did} ≠ lv-mkn-{adopted[:4]}-{num}")
src = f"{ROOT}/{r.findtext('n:Source/n:File', namespaces=NS)}"
if not os.path.exists(src):
return errs + [f"nav avota datnes {src}"]
body = open(src, encoding="utf-8").read()
if hashlib.sha256(body.encode("utf-8")).hexdigest() != r.findtext("n:Source/n:SHA256", namespaces=NS):
errs.append("SHA256 nesakrīt ar avota datni")
pos, missing = 0, []
for e in r.iter():
if not isinstance(e.tag, str):
continue
tag = etree.QName(e).localname
if tag in ("Text", "Note", "LegalBasis", "Lead", "Line", "Heading") or (tag == "Title" and etree.QName(e.getparent()).localname != "Act"):
for part in (e.text or "").split("\n"):
i = body.find(part, pos)
if i < 0:
missing.append(f"{tag}: {part[:70]}")
else:
pos = i
if e is not r and e.get("id") and not e.get("id").startswith(did + "."):
errs.append(f"{e.get('id')} nesākas ar {did}")
if tag == "Point" and not e.get("n").endswith(")") and not e.get("id").endswith("." + pid(e.get("n"))):
errs.append(f"punkts n={e.get('n')} id={e.get('id')}")
errs += [f"nav avotā secībā — {m}" for m in missing[:5]]
return errs
if __name__ == "__main__":
bad = 0
for p in sorted(glob.glob(f"{ROOT}/data/*.xml")):
e = check(p)
r = etree.parse(p).getroot()
pts = len(r.findall(".//n:Point", NS))
print(f"{'OK ' if not e else 'FAIL'} {os.path.basename(p)} punkti {pts}")
for x in e:
print(" ", x)
bad += bool(e)
sys.exit(1 if bad else 0)