diff --git a/validation/error-test-files/AF/af10115-fail.sbgn b/validation/error-test-files/AF/af10115-fail.sbgn new file mode 100644 index 0000000..76daaf7 --- /dev/null +++ b/validation/error-test-files/AF/af10115-fail.sbgn @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/validation/error-test-files/AF/af10115-pass.sbgn b/validation/error-test-files/AF/af10115-pass.sbgn new file mode 100644 index 0000000..8adfb86 --- /dev/null +++ b/validation/error-test-files/AF/af10115-pass.sbgn @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/validation/rules/sbgn_af.sch b/validation/rules/sbgn_af.sch index 759d648..5e45832 100755 --- a/validation/rules/sbgn_af.sch +++ b/validation/rules/sbgn_af.sch @@ -32,6 +32,7 @@ Schematron validation for SBGN AF + @@ -259,6 +260,43 @@ Schematron validation for SBGN AF + + + + + Illegal overlapping nodes are not allowed in SBGN AF. + + + diff --git a/validation/validate.py b/validation/validate.py new file mode 100644 index 0000000..4d45b97 --- /dev/null +++ b/validation/validate.py @@ -0,0 +1,124 @@ +import subprocess +from pathlib import Path + +# -------------------- +# Global configuration +# -------------------- + +SAXON_JAR = Path("lib/saxon9he.jar") +SCHEMATRON_DIR = Path("schematron") +RULES_DIR = Path("rules") +TESTS_DIR = Path("error-test-files") +SVRL_ROOT = Path("svrl") + + +# -------------------- +# Utility +# -------------------- + +def run(cmd): + print("▶", " ".join(cmd)) + subprocess.run(cmd, check=True) + + +# -------------------- +# Compile step +# -------------------- + +def compile_schematron(language: str): + """ + Compile Schematron rules for a given SBGN language (pd / er / af) + into an XSLT validator. + """ + language = language.lower() + + sch_file = RULES_DIR / f"sbgn_{language}.sch" + step1 = Path(f"sbgn_{language}.step1.sch") + step2 = Path(f"sbgn_{language}.step2.sch") + validator = Path(f"sbgn_{language}_validator.xsl") + + print(f"\n=== Compiling Schematron for {language.upper()} ===") + + # Step 1: expand includes + run([ + "java", "-jar", str(SAXON_JAR), + "-s:" + str(sch_file), + "-xsl:" + str(SCHEMATRON_DIR / "iso_dsdl_include.xsl"), + "-o:" + str(step1) + ]) + + # Step 2: expand abstract patterns + run([ + "java", "-jar", str(SAXON_JAR), + "-s:" + str(step1), + "-xsl:" + str(SCHEMATRON_DIR / "iso_abstract_expand.xsl"), + "-o:" + str(step2) + ]) + + # Step 3: compile to SVRL-producing XSLT + run([ + "java", "-jar", str(SAXON_JAR), + "-s:" + str(step2), + "-xsl:" + str(SCHEMATRON_DIR / "iso_svrl_for_xslt1.xsl"), + "-o:" + str(validator) + ]) + + print(f" Validator created: {validator}") + return validator + + +# -------------------- +# Validation step +# -------------------- + +def validate_sbgn(language: str, sbgn_file: Path): + """ + Validate a single SBGN file and write SVRL output. + """ + language = language.upper() + + validator = Path(f"sbgn_{language.lower()}_validator.xsl") + svrl_dir = SVRL_ROOT / language + svrl_dir.mkdir(parents=True, exist_ok=True) + + output = svrl_dir / (sbgn_file.stem + ".svrl") + + print(f"\n=== Validating {sbgn_file.name} ({language}) ===") + + run([ + "java", "-jar", str(SAXON_JAR), + "-s:" + str(sbgn_file), + "-xsl:" + str(validator), + "-o:" + str(output) + ]) + + print(f"SVRL written to {output}") + + +# -------------------- +# Batch validation +# -------------------- + +def validate_all(language: str): + """ + Validate all test files for a given language. + """ + language = language.upper() + test_dir = TESTS_DIR / language + + for sbgn in sorted(test_dir.glob("*.sbgn")): + validate_sbgn(language, sbgn) + + +# -------------------- +# Entry point +# -------------------- + +if __name__ == "__main__": + + pd = "pd" + af = "af" + er = "er" + #compile_schematron(pd) + compile_schematron(af) + validate_all(af)