From 7bd423c4588d8c52f9c8a250d8c5d771ffbed18d Mon Sep 17 00:00:00 2001 From: Philip Helger Date: Tue, 3 Feb 2026 17:30:09 +0100 Subject: [PATCH] Resolve "Wrong Schematron/XSLTs lead to positive validation result (GitHub 165)" --- .../impl/CollectingErrorEventHandler.java | 2 +- .../tasks/SchematronValidationAction.java | 11 +- .../cmd/CommandlineApplicationTest.java | 11 +- .../de/kosit/validationtool/impl/Helper.java | 13 +- .../input/simple-xslt-runtime-error.xml | 23 ++ .../xslt-runtime-error/repository/report.xsl | 44 ++++ .../repository/simple-xslt-runtime-error.xsl | 231 ++++++++++++++++++ .../xslt-runtime-error/repository/simple.xsd | 30 +++ .../scenarios-with-xslt-runtime-error.xml | 61 +++++ 9 files changed, 417 insertions(+), 9 deletions(-) create mode 100644 src/test/resources/examples/invalid/xslt-runtime-error/input/simple-xslt-runtime-error.xml create mode 100644 src/test/resources/examples/invalid/xslt-runtime-error/repository/report.xsl create mode 100644 src/test/resources/examples/invalid/xslt-runtime-error/repository/simple-xslt-runtime-error.xsl create mode 100644 src/test/resources/examples/invalid/xslt-runtime-error/repository/simple.xsd create mode 100644 src/test/resources/examples/invalid/xslt-runtime-error/scenarios-with-xslt-runtime-error.xml diff --git a/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java b/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java index be10111..042dd95 100644 --- a/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java +++ b/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java @@ -47,7 +47,7 @@ public class CollectingErrorEventHandler implements ValidationEventHandler, Erro private static final int DEFAULT_ABORT_COUNT = 50; - private static final int stopProcessCount = DEFAULT_ABORT_COUNT; + private final int stopProcessCount = DEFAULT_ABORT_COUNT; private final List errors = new ArrayList<>(); diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java index ae85023..90ad899 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java @@ -23,9 +23,6 @@ import javax.xml.transform.dom.DOMSource; import org.oclc.purl.dsdl.svrl.SchematronOutput; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - import de.kosit.validationtool.impl.CollectingErrorEventHandler; import de.kosit.validationtool.impl.ConversionService; import de.kosit.validationtool.impl.Scenario; @@ -33,7 +30,8 @@ import de.kosit.validationtool.impl.Scenario.Transformation; import de.kosit.validationtool.model.reportInput.CreateReportInput; import de.kosit.validationtool.model.reportInput.ValidationResultsSchematron; import de.kosit.validationtool.model.reportInput.ValidationResultsSchematron.Results; - +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import net.sf.saxon.dom.NodeOverNodeInfo; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.XdmDestination; @@ -71,6 +69,11 @@ public class SchematronValidationAction implements CheckAction { transformer.setInitialContextNode(document); transformer.transform(); + // If we reach this line, it means no Exception was thrown :-) + if (e.hasErrors()) { + log.error("XSLT errors found: " + e.getErrorDescription()); + } + final ValidationResultsSchematron.Results r = new ValidationResultsSchematron.Results(); r.setSchematronOutput(this.conversionService.readDocument( new DOMSource(NodeOverNodeInfo.wrap(result.getXdmNode().getUnderlyingNode()).getOwnerDocument()), diff --git a/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java index b9b2ed8..dce14d4 100644 --- a/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java +++ b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java @@ -139,6 +139,15 @@ public class CommandlineApplicationTest { assertThat(CommandLine.getErrorOutput()).contains(RESULT_OUTPUT); } + @Test + public void testValidMinimalConfigurationXSLTRuntimeError() { + final String[] args = { "-s", Paths.get(Simple.SCENARIOS_XSLT_RUNTIME_ERROR).toString(), "-h", "-o", + this.output.toAbsolutePath().toString(), "--serialize-report-input", + Paths.get(Simple.SIMPLE_XSLT_RUNTIME_ERROR).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(CommandLine.getErrorOutput()).contains(RESULT_OUTPUT); + } + @Test public void testValidNamingConfiguration() { final String[] args = { "-s", Paths.get(Simple.SCENARIOS).toString(), "-r", Paths.get(Simple.REPOSITORY_URI).toString(), @@ -159,7 +168,7 @@ public class CommandlineApplicationTest { @Test public void testValidDirectoryInput() { final String[] args = { "-s", Paths.get(Simple.SCENARIOS).toString(), "-o", this.output.toString(), "-r", - Paths.get(Simple.REPOSITORY_URI).toString(), Paths.get(Simple.EXAMPLES).toString() }; + Paths.get(Simple.REPOSITORY_URI).toString(), Paths.get(Simple.INPUT).toString() }; CommandLineApplication.mainProgram(args); assertThat(CommandLine.getErrorOutput()).contains("Processing 9 object(s) completed"); } diff --git a/src/test/java/de/kosit/validationtool/impl/Helper.java b/src/test/java/de/kosit/validationtool/impl/Helper.java index 00da5a3..25d6158 100644 --- a/src/test/java/de/kosit/validationtool/impl/Helper.java +++ b/src/test/java/de/kosit/validationtool/impl/Helper.java @@ -49,15 +49,18 @@ public class Helper { public static final URI ROOT = EXAMPLES_DIR.resolve("simple/"); - public static final URI EXAMPLES = ROOT.resolve("input/"); + public static final URI INPUT = ROOT.resolve("input/"); public static final URI SIMPLE_VALID = ROOT.resolve("input/simple.xml"); + public static final URI SIMPLE_XSLT_RUNTIME_ERROR = EXAMPLES_DIR + .resolve("invalid/xslt-runtime-error/input/simple-xslt-runtime-error.xml"); + public static final URI FOO = ROOT.resolve("input/foo.xml"); - public static final URI FOO_SCHEMATRON_INVALID = EXAMPLES.resolve("foo-schematron-invalid.xml"); + public static final URI FOO_SCHEMATRON_INVALID = INPUT.resolve("foo-schematron-invalid.xml"); - public static final URI FOO_CUSTOM_LEVEL_ERROR = EXAMPLES.resolve("foo-custom-level-error.xml"); + public static final URI FOO_CUSTOM_LEVEL_ERROR = INPUT.resolve("foo-custom-level-error.xml"); public static final URI REJECTED = ROOT.resolve("input/withManualReject.xml"); @@ -65,6 +68,9 @@ public class Helper { public static final URI SCENARIOS_WITH_RELATIVE_PATHS = ROOT.resolve("scenarios-with-relative-paths.xml"); + public static final URI SCENARIOS_XSLT_RUNTIME_ERROR = EXAMPLES_DIR + .resolve("invalid/xslt-runtime-error/scenarios-with-xslt-runtime-error.xml"); + public static final URI OTHER_SCENARIOS = ROOT.resolve("otherScenarios.xml"); public static final URI ERROR_SCENARIOS = ROOT.resolve("scenarios-with-errors.xml"); @@ -101,6 +107,7 @@ public class Helper { public static class Invalid { + // Is the typo in the name on purpose??? public static final URI ROOT = EXAMPLES_DIR.resolve("invaid/"); public static final URI SCENARIOS = ROOT.resolve("scenarios.xml"); diff --git a/src/test/resources/examples/invalid/xslt-runtime-error/input/simple-xslt-runtime-error.xml b/src/test/resources/examples/invalid/xslt-runtime-error/input/simple-xslt-runtime-error.xml new file mode 100644 index 0000000..cdbd1cf --- /dev/null +++ b/src/test/resources/examples/invalid/xslt-runtime-error/input/simple-xslt-runtime-error.xml @@ -0,0 +1,23 @@ + + + abc + def + + + + + diff --git a/src/test/resources/examples/invalid/xslt-runtime-error/repository/report.xsl b/src/test/resources/examples/invalid/xslt-runtime-error/repository/report.xsl new file mode 100644 index 0000000..6eb7471 --- /dev/null +++ b/src/test/resources/examples/invalid/xslt-runtime-error/repository/report.xsl @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/invalid/xslt-runtime-error/repository/simple-xslt-runtime-error.xsl b/src/test/resources/examples/invalid/xslt-runtime-error/repository/simple-xslt-runtime-error.xsl new file mode 100644 index 0000000..8a8f0de --- /dev/null +++ b/src/test/resources/examples/invalid/xslt-runtime-error/repository/simple-xslt-runtime-error.xsl @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / + + + + + + *: + + [namespace-uri()=' + + '] + + + + [ + + ] + + + + / + + @ + + + @*[local-name()=' + + ' and namespace-uri()=' + + '] + + + + + + + + + / + + + [ + + ] + + + + /@ + + + + + + + / + + + [ + + ] + + + + /@ + + + + + + + + + + + + + + + + + + + + + + + + . + + + + + U + + U + + + + U. + + n + + + + U. + + _ + + _ + + + + + + + + + +   +   +   + + + + + + + + + + + + + + + + Schematron Simple + + + + + + + + + + + + + + content-2 + + + + The decimal value of s:inner should be 1. + + + + + + + + + + + + diff --git a/src/test/resources/examples/invalid/xslt-runtime-error/repository/simple.xsd b/src/test/resources/examples/invalid/xslt-runtime-error/repository/simple.xsd new file mode 100644 index 0000000..04d5923 --- /dev/null +++ b/src/test/resources/examples/invalid/xslt-runtime-error/repository/simple.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/invalid/xslt-runtime-error/scenarios-with-xslt-runtime-error.xml b/src/test/resources/examples/invalid/xslt-runtime-error/scenarios-with-xslt-runtime-error.xml new file mode 100644 index 0000000..f1c13a6 --- /dev/null +++ b/src/test/resources/examples/invalid/xslt-runtime-error/scenarios-with-xslt-runtime-error.xml @@ -0,0 +1,61 @@ + + + XSLT-Runtime-Error-TestSuite + QA + 2026-03-02 + +

Szenario für Tests

+
+ + + Simple + +

Teste Fehlerfall.

+
+ http://www.xoev.de/de/validator/framework/1/createreportinput + http://validator.kosit.de/test-sample + http://validator.kosit.de/test-report + / + + + + Sample Schema + repository/simple.xsd + + + + + Sample Schematron + repository/simple-xslt-runtime-error.xsl + + + + + Report für eRechnung + repository/report.xsl + + +
+ + + + default + repository/report.xsl + + +
+