News and noteworthy - phax/ph-schematron GitHub Wiki
v10.1.0 - 2026-09-22
-
The Saxon
Processorobjects of the pure engines are now secured too -ph-schematron-pure-xpathandph-schematron-pure-xslttalk to Saxon through the s9api instead of through JAXP, so they never went throughSchematronTransformerFactoryand consequently had no security constraints at all:doc(),document()andunparsed-text()happily dereferenced any remote URL (Server Side Request Forgery). A cross-engine test (SchematronRemoteAccessTestinph-schematron-it) now runs a local HTTP server and asserts that no engine performs a single outbound request for any of those functions, and that a local resource is still resolved by all of them.- Added
SchematronProcessorFactoryinph-schematron-api- the s9api counterpart ofSchematronTransformerFactory.SchematronProcessorFactory.createProcessor ()returns anet.sf.saxon.s9api.Processorwith the Schematron security defaults applied,getDefault ()returns the shared one that all engines use unless aProcessoris configured explicitly, andmakeProcessorSecure (Processor, String...)applies the defaults to an existing one. It offers the same customization surface as its JAXP sibling:setAllowExternalFunctions (boolean),setAllowedRemoteSchemes (String...)andsetProcessorCustomizer (Consumer<Processor>), the latter being invoked last so that it can also relax a setting again. - Added
SaxonSecureResourceResolverinph-schematron-api- a SaxonResourceResolverthat denies all remote URL schemes. It blocks exactly the schemes that ph-commons'XMLResourceSchemeHelperconsiders remote (http,https,ftpandftps), so the pure engines and the XSLT based engines now agree on what "remote" means. Local schemes (file,jar, OSGibundle, ...) are untouched, and a nested JAR URL such asjar:http://host/x.jar!/y.xmlis resolved against its inner scheme, so it cannot be used as a bypass. A blocked URI raises anXPathExceptionrather than returningnull, becausenullis Saxon's signal for "not handled" and would let Saxon fetch the URI itself. -
Incompatible change: the
Processorobjects created byXPathConfigBuilder(including the public constantXPathConfigBuilder.DEFAULT_PROCESSOR), byXQueryAsXPathFunctionConverter, bySchematronPureXsltConfig.Builderand bySchematronResourcePureXslt.Buildernow come fromSchematronProcessorFactory, so they- deny all remote resource access of
doc(),document(),unparsed-text(),collection(),json-doc(),fn:transform()andxsl:source-document, - disable external functions (
FeatureKeys.ALLOW_EXTERNAL_FUNCTIONS), which is what Saxon does forFEATURE_SECURE_PROCESSING- see the ph-commons entry below for the consequences. Extension functions registered viaXPathConfigBuilder.setExtensionFunctions (...)orProcessor.registerExtensionFunction (...)are considered trusted by Saxon and keep working, - and honour
SchematronTransformerFactory.setAllowXInclude (boolean), so that one switch now covers every engine. AProcessorthat is passed in explicitly -SchematronResourcePureXslt.builder (...).processor (...)orXPathConfigBuilder.setProcessor (...)- is not touched, so an application that brings its own Saxon configuration keeps full control (and full responsibility).
- deny all remote resource access of
- Not changed, because it was already safe: no engine expands an external entity of an XML instance that is handed in as a
javax.xml.transform.Source.
- Added
-
Bugfix: the
SchematronPureXsltCachenever produced a cache hit across twoSchematronResourcePureXsltinstances. Its cache key containedSystem.identityHashCodeof the SaxonProcessor, while every builder allocated a freshProcessor- so every resource compiled its own copy of the very same stylesheet. The cache key is now(resourceID, phase, xsltVersion, tracing)and the builders default to the sharedSchematronProcessorFactory.getDefault (). To keep that safe, aProcessorthat is not the shared default now counts as a custom hook - like a customURIResolverorErrorListener- and bypasses the cache, unlessforceCacheResult (true)is set. Otherwise a caller with its ownProcessor(e.g. carrying extension functions) could receive anXsltExecutablethat was compiled with a different configuration. -
Updated to ph-commons 12.5.0 (released 2026-09-21), which continues the "security by default" work in
ph-xmland changes the XML processing defaults of all XSLT based engines (ph-schematron-isosch,ph-schematron-xslt,ph-schematron-schxslt,ph-schematron-schxslt2). The bundled ISO Schematron, SchXslt 1.x and SchXslt 2.x stylesheet chains are unaffected - they use neither extension functions norxsl:result-document, and all their includes are class path based - so a setup that validates with local Schematron files keeps working unchanged.ph-schematron-pure-xpathandph-schematron-pure-xsltare not affected by the ph-commons change itself, because they do not useSchematronTransformerFactory- they are secured separately, see the entry above.-
Security fix: remote resource resolution in XSLT processing is now really denied, and no longer only logged.
The v10.0.1 entry below claimed that a blocked resolution "returns
null, so Saxon applies its own (restricted) default resolution" - that was wrong. Saxon treatsnullas "not handled" and then opened the URI itself, sodocument(),xsl:importandxsl:includestill reached an attacker chosen host (SSRF), despite the warning in the log. ph-commons'DefaultTransformURIResolvernow resolves a blocked resource to an empty document instead, which cannot be bypassed:document()evaluates to an empty node set, and anxsl:import/xsl:includefails to compile withXTSE0165.unparsed-text()is blocked as well, but reports the obscureResolver for unparsed-text() returned non-StreamSource, because Saxon requires aStreamSourcefor a non-XML resource and the blocked resource is a DOM document. To allow specific remote schemes again, hand in aURIResolverthat permits them -...builder (...).uriResolver (new DefaultTransformURIResolver ().setAllowedRemoteSchemes ("http", "https")). Note that a resolver which returnsnullfor a remote href no longer results in the remote resource being fetched by a fallback resolver - a resolver now has to resolve what it wants to allow. -
Bugfix:
SchematronProviderXSLTPrebuild, and thereforeSchematronResourceXSLT, no longer wraps the caller suppliedURIResolverin anotherDefaultTransformURIResolver. With the changed ph-commons semantics that wrapper ended the resolution of a remote href itself, so it silently overrode a caller supplied resolver that deliberately allowed a remote scheme. The wrapper was redundant anyway - the builder ofSchematronXSLTConfigalready defaults to aDefaultTransformURIResolverwith the resource's parent directory as base URL, exactly like the other XSLT based engines. -
Incompatible change:
FEATURE_SECURE_PROCESSINGis now enabled on everyTransformerFactorycreated bySchematronTransformerFactory, becauseXMLFactory.defaultCustomizeTransformerFactory (TransformerFactory)of ph-commons applies it. Saxon implements secure processing by settingFeatureKeys.ALLOW_EXTERNAL_FUNCTIONStofalse, so in a custom Schematron or XSLT file:-
xsl:result-documentwith anhrefno longer compiles - the error isXTSE0010("xsl:result-document is disabled when extension functions are disabled"). -
system-property()with a name in no namespace returns the empty string instead of the JVM system property. A prefixed name likesystem-property('xsl:vendor')is unaffected, and so are thesystem-property('xsl:product-name')calls of the SchXslt 1.x stylesheets. -
environment-variable(),available-environment-variables()andavailable-system-properties()return the empty sequence. - a reflexive Java call (a
java:namespace URI) is rejected with "External function calls have been disabled". This only matters with Saxon-PE/EE, because Saxon-HE - the edition this project depends on - never supported reflexive calls in the first place. - extension functions that are registered programmatically on the Saxon
Processor, e.g. from...builder (...).transformerFactoryCustomizer (...), keep working: Saxon considers anExtensionFunctionDefinitiontrusted and allows calls to it even with external functions disabled. To opt out completely, setaTF.setAttribute (FeatureKeys.ALLOW_EXTERNAL_FUNCTIONS, Boolean.TRUE)from atransformerFactoryCustomizeror from the globalSchematronTransformerFactory.setTransformerFactoryCustomizer (Consumer)- the customizer runs after the ph-commons defaults are applied.
-
-
DefaultEntityResolver- the default entity resolver ofAbstractSchematronResourcefor reading the Schematron resource - now blocks remote URL schemes as well and resolves such an entity to an empty document. Class path andfilebased entities are unaffected. Note that the default parser settings disallow DOCTYPE declarations anyway, so the resolver is not reached for an external entity under the default settings. -
RelaxNGCompactSchemaCache.getValidator (...), as used bySchematronValidator, now hands theLSResourceResolverof itsSchemaFactoryto the createdValidator, so that the RELAX NG validation of a Schematron file resolves external resources through the blockingSimpleLSResourceResolveras well. ph-commons additionally tries to deny the external DTD and schema access of thatValidator, which JING does not support - this logs the two harmless warnings "Validator does not recognize property 'ACCESS_EXTERNAL_DTD'" and "... 'ACCESS_EXTERNAL_SCHEMA'" per created validator.
-
Security fix: remote resource resolution in XSLT processing is now really denied, and no longer only logged.
The v10.0.1 entry below claimed that a blocked resolution "returns
- New tests for all the XML processing defaults described above:
SchematronSecureProcessingTestinph-schematron-xslt,SchematronRemoteAccessTestinph-schematron-it,SchematronProcessorFactoryTestandSaxonSecureResourceResolverTestinph-schematron-apiplusSchematronTransformerFactoryTest.testSecureProcessingEnabledByDefault. -
Reviewed the
@Immutable/@ThreadSafe/@NotThreadSafeannotations of all classes of all modules, and corrected them where they did not match the actual thread safety of the class.-
Bugfix:
SchematronTransformerFactoryandSchematronProcessorFactorywere declared@Immutable, although both hold mutable static state. Their customizer field (setTransformerFactoryCustomizer (Consumer)resp.setProcessorCustomizer (Consumer)) was neithervolatilenor guarded, so a customizer set from one thread was not guaranteed to be visible to another one. Both fields are now guarded by aSimpleReadWriteLock- like the error level determinator ofSVRLHelper- and both classes are now declared@ThreadSafe. -
SVRLLocationBeautifierRegistrywas declared@NotThreadSafe, although it holds no mutable state at all. It is now declared@Immutable. - Added the missing annotation to 51 classes that carried none.
No behaviour changed for these - they only document what the classes already did.
Noteworthy for callers: the Schematron model readers and writers (
PSReader,PSWriter,PSWriterSettings), the collecting and logging error handlers,XPathConfigBuilderandDefaultSchematronIncludeResolverare@NotThreadSafeand must not be shared between threads, whereasPSBoundSchemaCacheis@ThreadSafe.
-
Bugfix:
v10.0.2 - 2026-09-07
- (pure) Foreign (non-Schematron) elements are now reported as warnings - fixes #186.
The pure XPath engine (
SchematronResourcePureXPath) can only evaluate Schematron elements and XPath expressions, so elements from other namespaces - typically XSLT ones like<xsl:function>or<xsl:variable>- were silently ignored so far. Now one warning per foreign element is sent to the configuredIPSErrorHandlerwhen the schema is bound, naming the element and its namespace URI. UseSchematronResourcePureXsltor one of the XSLT based engines if the XSLT elements need to be evaluated. The new helperPSForeignElementVisitor.forEachForeignElement (PSSchema, BiConsumer)inph-schematron-modelperforms the underlying model walk and is engine independent. -
New
SaxonDOMSourceto opt into Saxon's native tree model for DOM based validation - see #198. When an XML instance is passed to an XSLT based engine as ajavax.xml.transform.dom.DOMSource, Saxon wraps the DOM and evaluates every XPath step against that wrapper. For large documents - in particular ones with long sibling lists - this repeated navigation dominates the validation runtime. The new classcom.helger.schematron.saxon.SaxonDOMSourceinph-schematron-apiis aDOMSourcesubclass that acts as a marker: pass it instead of a plainDOMSourcetoapplySchematronValidation (Source),applySchematronValidationToSVRL (Source)orgetSchematronValidity (Source)and the engine builds the transformer's configured native Saxon tree once per validation, instead of navigating the wrapped DOM. TheNodebased overloads always create a plainDOMSource, so one of theSourcebased methods must be used to opt in. All XSLT based engines honour it -SchematronResourceXSLT,SchematronResourceSCH,SchematronResourceSchXslt_XSLT2andSchematronResourceSchXslt2- but only if the wrapped node is aDocumentand the running transformer is a Saxon one. In every other case it behaves exactly like a regularDOMSource. The original DOM is never modified and the converted tree is not cached, so a singleSaxonDOMSourcecan be reused across validations and across engines with different Saxon configurations, and later modifications of the DOM are picked up by the next validation. Because the transformation runs on a snapshot, two semantics differ from a regularDOMSource: DOM object identity is not retained, and base URIs are resolved against the source's system ID while the tree is built. Stay with a regularDOMSourceif the stylesheet or an extension function requires the original DOM nodes or the wrapped DOM behaviour. This is purely opt-in - existing code keeps the previous wrapped DOM behaviour.
v10.0.1 - 2026-08-17
-
XInclude processing is now disabled by default in all XSLT-based engines (
ph-schematron-isosch,ph-schematron-xslt,ph-schematron-schxslt,ph-schematron-schxslt2). It was unconditionally enabled since #86 and allowed a Schematron file to pull in arbitrary local and remote resources. The new switchSchematronTransformerFactory.setAllowXInclude (boolean)(defaultfalse, seeSchematronTransformerFactory.DEFAULT_ALLOW_XINCLUDE) re-enables it. Because the createdTransformerFactoryobjects and the XSLT templates derived from them are cached internally, the switch must be set before the first Schematron file is processed. -
Updated to SchXslt2 1.11.2 (from 1.11.1) - affects
ph-schematron-schxslt2only. The upstream release (2026-07-20) fixes the placement of some attributes in the SVRL report and adds a RELAX NG grammar for the generated SVRL:-
xml:*attributes are no longer copied wholesale into the report.svrl:textnow only receives@xml:langand@xml:space(in addition to@see,@iconand@fpi), andsvrl:dir,svrl:emphandsvrl:spanno longer copy anyxml:*attribute at all. Code that evaluated e.g.xml:baseorxml:idon these SVRL elements no longer finds them. - The
schxslt2JAR now also contains the RELAX NG compact grammarscontent/svrl.rncandcontent/svrl-schxslt.rnc. According to their headers they aim to be equivalent to the official SVRL grammar published in the 2025 edition of ISO Schematron, section D3.
-
-
Remote resource resolution in XSLT processing is denied by default. This is not a change of this release but a consequence of the ph-commons version in use (since ph-commons 12.3.2, so it is effective since ph-schematron v10.0.0) that was so far undocumented:
the shared Saxon
TransformerFactoryofSchematronTransformerFactory.getDefault ()uses ph-commons'DefaultTransformURIResolver, which resolves no remote URL scheme at all, to prevent Server Side Request Forgery (SSRF) via XSLTdocument(),xsl:importorxsl:include. Class path andfilebased resolution is unaffected, so setups where all XSLT documents reside locally keep working unchanged. A blocked resolution is logged as a warning and returnsnull, so Saxon applies its own (restricted) default resolution. To allow specific remote schemes again, pass an own resolver toSchematronTransformerFactory.createTransformerFactory (ErrorListener, URIResolver), e.g.new DefaultTransformURIResolver ().setAllowedRemoteSchemes ("http", "https").
v10.0.0 - 2026-07-16
-
New submodule
ph-schematron-isosch— the SCH → XSLT preprocessing half ofph-schematron-xslt(the ISO Schematron stylesheet chain) was extracted into its own artifact.ph-schematron-xsltkeeps only the "apply a pre-built XSLT to an XML instance" side. See the Migrations page for the moved classes, package locations and the Maven dependency to add. -
New submodule
ph-schematron-model— the engine-agnostic data model, the SCH XML reader/writer, the error handler types and the preprocessor were extracted fromph-schematron-pureinto a much smaller artifact (no Saxon, no XPath evaluation). Consumers that only parse / serialize / preprocess Schematron schemas can now depend onph-schematron-modeldirectly. Packages were renamed to drop the.pure.segment — see the Migrations page for the rename table and a sed snippet to migrate imports. -
New submodule
ph-schematron-pure-xslt— pure-Java engine that generates an XSLT 3.0 stylesheet from the parsedPSSchema(no external ISO Schematron stylesheet chain) and runs it through Saxons9api. Entry pointSchematronResourcePureXsltacceptsURIResolver,ErrorListenerand a configurable XSLT version, supports<xsl:*>pass-through (xsl:function,xsl:key,xsl:include, ...) from foreign children of<sch:schema>and<xsl:choose>-bodied<sch:let>. Also shipsSchematronToXsltConverter— a stand-alone SCH → XSLT tool that emits to a W3C DOMDocument/String/OutputStream/Writer/File. The underlyingPureXsltStylesheetGenerator.generate(...)returns a DOMDocumentso the runtime can hand it straight to SaxonXsltCompiler.compile(new DOMSource(...))without a serialize-then-parse round trip. The engine's classes follow thePureXslt*naming convention (PureXsltStylesheetGenerator,PureXsltQueryBindingTransform,PureXsltTelemetry,EPureXsltVersion) so they don't clash with the ISO-XSLT engine's similarly-named types. Both wired into the Maven plugin (schematronProcessingEngine="pure-xslt") and the Ant task. -
ph-schematron-pure-xsltversion-conformant output (XSLT 1.0 / 2.0 / 3.0).EPureXsltVersionnow covers XSLT 1.0, 2.0 and 3.0 (default3.0), selectable viaSchematronResourcePureXslt.builder().xsltVersion(...),SchematronPureXsltConfigandSchematronToXsltConverter.setXsltVersion(...). The generated stylesheet is now kept conformant to the chosen version — previously the SVRL@locationwas always populated with the XPath 3.0fn:path(), so a stylesheet targeting 2.0 or 1.0 would not compile on a strict processor. The@locationcomputation is now version-appropriate:fn:path()on 3.0, a generatedphsch:pathxsl:functionon 2.0, and recursivephsch-pathmode templates (noxsl:function) on 1.0. The XSLT 1.0 output was verified end-to-end against the JDK-bundled Xalan (XSLTC), i.e. a genuine XSLT 1.0 processor, for both non-namespaced and namespaced instances.EPureXsltVersionalso gainedisLT(...)/isLE(...)version-ordering helpers. Caveat: the built-in engine executes on Saxon-HE 12, which is an XSLT 3.0 processor — selecting1.0/2.0there only activates XSLT backwards-compatibility mode, not a true down-level engine. Whether a schema actually runs under a lower version additionally depends on the XPath used in its owntest/contextexpressions (passed through verbatim); aqueryBinding="xslt2"schema using e.g.matches()still needs a 2.0+ XPath at runtime regardless of the emitted@version. -
Engine naming consolidated.
SchematronResourcePureis now a deprecated source-compatible alias ofSchematronResourcePureXPath(the canonical name; covariant setters keep chained code compiling).ESchematronModeis merged intoESchematronEngine— the latter now also covers the previous Mode-onlyXSLT_PREBUILTvalue and accepts every pre-v10 id (schematron,sch,schxslt-xslt2,pure-saxon, ...) as aliases. The Maven-pluginschematronProcessingEngineand Ant-taskschematronProcessingEnginecontinue to accept the old strings unchanged. -
SchematronValidationMojonow supportsschxslt2. The Maven plugin'svalidategoal previously only handledschxslt(v1); selectingschematronProcessingEngine="schxslt2"now resolves toSchematronResourceSchXslt2(SchXslt v2 / XSLT 3). ThephaseName,languageCodeandparametersparameters apply. -
Ant task now supports
schxslt2. The AntSchematrontask gained aSCHXSLT2engine branch resolving toSchematronResourceSchXslt2(SchXslt v2 / XSLT 3), so it now handles all six engine values (pure-xpath,pure-xslt,iso-schematron,schxslt,schxslt2,xslt) just like thevalidategoal. Theph-schematron-schxslt2dependency was added toph-schematron-ant-task. -
ph-telemetryintegration. BothSchematronResourcePureXPathandSchematronResourcePureXsltexposesetTelemetry(boolean)andsetPerAssertionTelemetry(boolean). When enabled, the engines emit OpenTelemetry-shaped spans (schematron.validate,schematron.parse,schematron.preprocess,schematron.generate,schematron.compile,schematron.execute, optionalschematron.assertion), counters (schematron.assertions.failed,schematron.reports.fired,schematron.rules.fired,schematron.patterns.active) and aschematron.validate.durationhistogram. Zero runtime cost when noITelemetryTracerSPI/ITelemetryMeterSPIis registered — ph-telemetry degrades to no-op silently. Maven coordinates ofph-telemetrymoved fromcom.helger.commons:ph-telemetry(formerly bundled with ph-commons) to the standalone repositorycom.helger.telemetry:ph-telemetry(current version1.0.0-SNAPSHOT). The Java packagecom.helger.telemetryis unchanged, so source-level imports continue to work; onlypom.xml<dependency>entries that referenced the artifact directly need theirgroupIdupdated. -
New
ph-schematron-benchmarkssubmodule runs the previously-test-only Main benchmarks as JMH suites. -
Schematron edition awareness in the model (
ph-schematron-model). The PS-model is now aware of which ISO/IEC 19757-3 edition each schema is targeting and can read/write/validate the full grammar of all four published editions (2006 / 2016 / 2020 / 2025). Specifically:-
ESchematronVersiongainsSCHEMATRON_2025(withLATESTrepointed at it), angetEditionYear()accessor returning the four-digit year string used by the newschematronEditionattribute, agetFromEditionYearOrNull(String)look-up, and anisOlderThan(ESchematronVersion)ordering helper. -
PS-model elements completed. New top-level classes
PSGroup,PSLibrary,PSRules,PSProperties,PSProperty. New baseAbstractPSPatternLikeextracted so thatPSPatternandPSGroupare siblings (aninstanceof PSPatternno longer matches aPSGroup). New attributes:let@as(2025),phase@from/@when(2025),rule@visit-each/@severity(2025),assert@severityandreport@severity(2025), directpattern@role/group@role(2025),pattern@documents/group@documents(2016),extends@href(2016),diagnostic@role(2020 RNC), schema-level<extends>/<param>/<rules>/<group>(2025),assert@properties/report@propertiesIDREFS (2016), andschema/library<properties>containers (2016).flagis now a list-of-tokens datatype (v4) —IPSHasFlagexposesgetAllFlags()/addFlag(...)andsetFlag(String)splits on whitespace.dir/emph/spanaccept the v4 dynamic group (<value-of>and<name>). -
PSSchema.getSchematronEdition()/setSchematronEdition(...)carry the new 2025schematronEditionattribute (typedESchematronVersion). Reading an unrecognised attribute value emits a warning through the registered error handler. -
Library root.
PSReader.readLibrary()andreadLibraryFromXML(IMicroElement)parse a<library>root document (the 2025 alternative to<schema>);PSLibrary.getAsMicroElement()writes it back. -
Central
PSVersionChecker. Walks aPSSchemaand emits warnings for every feature whose introducing edition is newer than the schema's declaredschematronEdition(or whenever no edition is declared). All warnings route through one private_warnFeatureUnavailable(...)method so the wording, severity or channel can be changed in a single place. The check is invoked automatically at the end ofPSReader.readSchemaFromXML(...)and at the start of everyPSWriter.write*(...)/getXMLString(...)call (the latter using an internalLoggingPSErrorHandlerby default, overridable viaPSWriter.setErrorHandler(...)).queryBindingvalues (xslt2,xslt3,xpath3,xpath31,xquery3,xquery31,xslt4,xpath4,xquery4, ...) are mapped to their introducing edition and flagged whenever an explicit older edition is declared. -
Validation tightened to v4 RNC three-branch shape on
PSPattern/PSGroup: is-a forbids<rule>and<let>, concrete (non-abstract / non-is-a) forbids<param>, abstract now allows<param>and<let>(newly permitted in 2025 — pre-2025 schemas using them are flagged throughPSVersionChecker, not as a hard error).
-
- Other v10 changes (engine renames
pure→pure-xpath, module folder renames,ESchematronModedeprecation details, etc.) are documented in the Migrations page.
v9.2.0 - 2026-05-31
- Updated to SchXslt2 v1.10.3
-
ph-schematron-puremigrated from JAXP XPath to the Saxon s9api. Schematron expressions are now compiled and evaluated as XPath 3.1 (default; configurable via the newEXPathVersionenum — supports1.0/2.0/3.0/3.1/4.0). User-facing entry points (SchematronResourcePure,IPSBoundSchema,IPSValidationHandler,IPSErrorHandler) keep their DOMNode/NodeListsignatures; the breaking changes are concentrated inIXPathConfig/XPathConfig/XPathConfigBuilderand in the bound-schema internals. See the Migrations wiki page. - (pure)
XPathConfigBuilderreplacessetXPathFactory(...)/setXPathFactoryClass(...)/setGlobalXPathFactory(...)/setXPathVariableResolver(...)/setXPathFunctionResolver(...)withsetProcessor(Processor),setXPathVersion(EXPathVersion),addExtensionFunction(ExtensionFunction)/addAllExtensionFunctions(...), andaddExternalVariable(QName, XdmValue)/addAllExternalVariables(...). - (pure) Custom function resolvers based on
javax.xml.xpath.XPathFunction/MapBasedXPathFunctionResolver(from ph-commons) are no longer wired into the engine. Migrate by implementingnet.sf.saxon.s9api.ExtensionFunction; arguments now arrive asXdmValue[]instead ofList<Object>of DOMNodes. - (pure)
XQueryAsXPathFunctionConverter.loadXQuery(InputStream)returnsICommonsList<ExtensionFunction>instead ofMapBasedXPathFunctionResolver. Feed the returned list intoXPathConfigBuilder.addAllExtensionFunctions(...). The wrapper around an XQueryUserFunctionnow exposes the actual declared argument and resultSequenceTypes, so Saxon applies the same automatic coercion (atomization, cardinality checks, type promotion) that it would for a built-in function — this fixes the long-standingDOMNodeWrapper cannot be cast to AtomicValueerror when calling e.g.functx:are-distinct-values(...). - (pure)
XPathFunctionFromUserFunctionnow implementsExtensionFunction(Saxon-typed throughout). - (pure)
XPathEvaluationHelperis reshaped aroundXPathExecutable/XdmItem/XdmValue. Variants such asevaluateAsNodeList(...)returning DOMNodeListare gone; useevaluateAsXdmNodes(...)orevaluate(...). - (pure)
XPathLetVariableResolverno longer implementsjavax.xml.xpath.XPathVariableResolver. It is now a per-threadQName→XdmValuestore used internally during validation. - (pure) New
XPathEvaluationContext(thread-local) is published as part of the SPI. The bound schema installs one pervalidate(...)call; the SVRL handler uses it to re-wrap DOM nodes against the same Saxon document wrapper and to read the currently-effective<let>variable bindings. - (pure) The bound-schema and bound-element types (
PSXPathBoundSchema,PSXPathBoundRule,PSXPathBoundAssertReport,PSXPathBoundElement,PSXPathVariables,IPSXPathVariables) now hold SaxonXPathExecutableinstances instead ofjavax.xml.xpath.XPathExpression. -
Behavioural consequence (XPath 1.0 → 3.1). Expressions that were silently re-interpreted under XPath 1.0 (single-item conversion, implicit string coercion,
eq/nebeing syntax errors, etc.) now behave per the XPath 3.1 spec. Schematrons that target XPath 2.0/3.x in theirqueryBindingattribute work as written; Schematrons relying on XPath 1.0 quirks may need adjustment. - (pure) Saxon TinyTree input path.
SchematronResourcePure.getAsNode(...)now parses the input XML straight into a Saxon TinyTree (viaProcessor.newDocumentBuilder()) and presents it as a DOM facade (net.sf.saxon.dom.NodeOverNodeInfo/DocumentOverNodeInfo). Every overload ofapplySchematronValidationToSVRL,getSchematronValidityandapplySchematronValidationthat takes aSourceorIHasInputStreamgoes through this path. The internal validation loop short-circuits the DOM-bridge (DocumentWrapper.wrap) when it sees a Saxon-backed facade, so XPath evaluation runs directly against the TinyTree. Measured on JDK 21 against a ~1 MiB document with a representative schema, parse-only is ~28 % slower (Saxon's parser vs Xerces), validate-only is ~8 % faster, total wall-time is ~6 % faster. The win grows for more XPath-heavy schemas / repeated validations of the same document. SeeMainBenchmarkDomVsTinyTreeinph-schematron-pure/src/test/java. Caveats: when a customEntityResolveris configured the TinyTree path is bypassed (so the resolver is honoured); the returned DOM facade is read-only (mutating operations throwNOT_SUPPORTED_ERR); overloads taking a pre-builtorg.w3c.dom.Nodekeep their existing behaviour. - (pure)
<let>element bodies are now read instead of being silently discarded — fixes #189. The body text content is taken as a plain XPath expression when thevalueattribute is absent. XSLT-style bodies (<xsl:for-each>,<xsl:value-of>...) still cannot be evaluated by the pure engine, but instead of the cryptic<let> has no 'value'failure the user now gets a clear, actionable warning naming the offending child element. Full XSLT-body support is tracked for a future, separate Saxon-XPath-and-XSLT engine module.
v9.1.1 - 2025-12-10
- Added new enumeration
ESchematronEngineto list the supported engines - Added new submodule
ph-schematron-schxslt2that deals with SchXslt2 (requiring XSLT 3.0 engine) - The Maven Plugin goal
convertcan now handle different Schematron engines via the newschematronEngineparameter
v9.1.0 - 2025-11-16
- Updated to Saxon 12.9
- Updated to ph-commons 12.1.0
- Using JSpecify annotations
v9.0.1 - 2025-09-04
- The XSLT based transformations use the
Sourcebased source as the basis. See #192 - thx @Lukvargen
v9.0.0 - 2025-08-25
- Requires Java 17 as the minimum version
- Updated to ph-commons 12.0.0
- Updated to Saxon 12.8
v8.0.6 - 2025-03-10
- Updated SVRL XML Schema to support specific SchXslt elements (
metadata,suppressed-rule,message-codeandmessage-category)
v8.0.5 - 2024-12-18
- (pure) Added method
PSReader.setSchematronIncludeResolverto define a custom Schematron include resolver
v8.0.4 - 2024-12-05
- Updated to SchXslt 1.10.1
- The XSLT binding will emit the attribute
documentsfor SVRL elementactive-patternparallel to the previousdocumentto ensure ISO 2016 compliance. - (pure) Fixed a concurrency issue with XPath variables in multi-threaded environments. See #182 and #183 - thx @bertrand-lorentz
v8.0.3 - 2024-08-23
- Provided the possibility to customize the created
TransformerFactoryused for XSLT transformations. See #176 - thx @SvenHaul - (pure) Fixed variable evaluation order. See #177 and PR #178 - thx @bertrand-lorentz
v8.0.2 - 2024-07-29
- Updated to SchXslt 1.10
- (pure) Improved the type auto detection for "for loop expressions". See #173 - thx @bertrand-lorentz
- (pure) Improved the type auto detection for "filter expressions". See #175 - thx @bertrand-lorentz
v8.0.1 - 2024-07-17
- Updated to Saxon 12.5
- The default SVRL to error level mapper changed
cautionfromWARNINGtoINFORMATIONaccording to official sources. See #168 - thx @costas80 - Improved the error handling in "pure" mode, in case a test expression does not evaluate properly. See #171 - thx @gediminasre
- Improved the type detection of test expressions in "pure" mode if Saxon is used as the XSLT engine. See #170 - thx @bertrand-lorentz
v8.0.0 - 2024-03-09
- Updated to Saxon 12.4
- Updated to ph-commons 11.1.4
- Updated to jvnet JAXB Maven Plugin
- The variable resolution problem in pure mode was resolved by a kind contribution in #164 - thx @bertrand-lorentz
- All deprecated elements, marked as "forRemoval" were removed
- Renamed interface
ISchematronXSLTValidatortoISchematronOutputValidator - Renamed method
ISchematronXSLTValidator.getSchematronValiditytoISchematronOutputValidator.getSchematronOutputValidity - Renamed all implementing classes
SchematronXSLTValidator*toSchematronOutputValidityDeterminator* - Renamed methods
ISchematronXSLTBasedResource.(get|set)XSLTValidatorto(get|set)OutputValidityDeterminator - Added new
SchematronDebugdebug log methods - Removed the experimental parallel validation in
PSXPathBoundSchema - Removed the constructors of
SchematronResourcePurewith aboolean bLenientparameter. Use the version without it and callsetLenient(boolean)instead - Honoring the
@subjectattribute in the Pure implementation. See #133 - thx @ericlop
v7.1.3 - 2023-12-06
- Updated to Saxon 11.6
- Added a new parameter
ignoreWarningsto the Maven pluginvalidategoal. See #159 - thx @IacopoArduini-gmail
v7.1.2 - 2023-07-31
- Updated to ph-commons 11.1
v7.1.1 - 2023-07-03
- Updated to Saxon 11.5 - reverted back from Saxon 12.x as the default branch
-
DefaultSVRLErrorLevelDeterminatornow also deals withcautionas a warning level - Improved logging and code documentation
v7.1.0 - 2023-02-21
- Updated to Saxon HE 12.0 - there seem to be backward incompatible changes
- Updated to ANT 1.10.13
- Updated to SchXslt 1.9.5
- Fixed an error with pattern local variable resolution in "pure" implementation. See #142 - thx @bertrand-lorentz
- Added a check in "pure" implementation, that Pattern ID must follow the XML NCName convention
v7.0.1 - 2023-02-22
- Updated to ANT 1.10.13
- Updated to SchXslt 1.9.5
- Fixed an error with pattern local variable resolution in "pure" implementation. See #142 - thx @bertrand-lorentz
- Added a check in "pure" implementation, that Pattern ID must follow the XML NCName convention
v7.0.0 - 2023-01-08
- Using Java 11 as the baseline
- Updated to ph-commons 11
- Using JAXB 4.0 as the baseline
- The creation of SVRL metadata was disabled in the SchXslt version (using parameter
schxslt.compile.metadatawith valuefalse) - Removed deprecated methods
v6.3.4 - 2022-11-17
- Updated to SchXslt 1.9.4
- Updated to ph-commons 10.2.2
- Fixed an error in the SVRL location - no XPath compliant paths are created. See also https://github.com/phax/ph-commons/issues/31
v6.3.3 - 2022-08-17
- Updated to Saxon 11.4 (which updates XMLResolver to 4.4 which updates to Apache Http Client 5.x)
- Extended
ISchematronXSLTBasedResourceAPI to enable/disable the SVRL validation
v6.3.2 - 2022-07-06
- Updated the RelaxNG components to version
20220510 - Updated to SchXslt 1.9.1
- The Maven "Schematron to XSLT" plugin has the parameter "stopOnError" (boolean)
v6.3.1 - 2022-05-05
- Updated to Saxon 11.3
- Updated to SchXslt 1.8.7
- Updated the RelaxNG components to version
20181222
v6.3.0 - 2022-03-08
- Updated to Saxon 11.2
- Updated to SchXslt 1.8.6
v6.2.8 - 2021-12-29
- Updated to SchXslt 1.8.5
- Deprecated
SchematronHelper.applySchematronin favour of the native methods - The Maven plugin prints a progress report, if the execution takes longer than 5 seconds. This can be enabled/disabled with the new parameter
showProgress. - The
diagnostic-referenceelements in the Pure implementation now copy the rich attributes. See #126 - thanks @costas80
v6.2.7 - 2021-12-09
- Fixed an error in the ISO Schematron, that caused a message to be emitted if a
iso:name[@path]exists that does not had a@selectattribute. - Avoid double evaluation of Schematron when using the XSLT based approach with disabled caching
v6.2.6 - 2021-11-24
- Extended
SchematronResourceSCHAPI. See #122 - thanks @cshjsc - Made an improvement in the ISO Schematron XSLT on attribute handling. See #123 - thanks @Falcon2677
v6.2.5 - 2021-11-22
- Updated to ph-commons 10.1.5
- Fixed quite some SonarCloud issues - nothing critical
- Fixed the automatic resource ID of in-memory resources. See #118 - thanks @olavivaino and @qligier
- Added new factory method overloads for class
SchematronResourceSchXslt_XSLT2
v6.2.4 - 2021-11-02
- Updated to ANT 1.10.12
- Added a new unchecked exception class
SchematronInterruptedExceptionthat is thrown in case the current Thread gets interrupted during the compilation of XSLTs/Schematrons. See #119 - thanks @Michiel-s
v6.2.3 - 2021-10-14
- Updated to SchXslt 1.8.4
- Added some factory methods in the
PS*classes
v6.2.2 - 2021-09-27
- Updated to Saxon-HE 10.6
- Updated to SchXslt 1.8.2
- Added the JAXB dependencies to the ANT task and the Maven plugin
- Added a new parameter
xsltHeaderto thesch2xsltMaven plugin goal, to add a comment to the generated XSLTs - Added a new parameter
schHeaderto thepreprocessingMaven plugin goal, to add a comment to the generated SCHs
v6.2.1 - 2021-08-01
- Updated to SchXslt 1.7.4
- Updated the Maven plugin configuration on validation -
xmlIncludes,xmlExcludes,xmlErrorIncludesandxmlErrorExcludesare now of typeString[]compared toString[]before. No need to changepom.xmlconfigurations afaik.
v6.2.0 - 2021-05-02
- Updated to ph-commons 10.1
- Updated to Saxon-HE 10.5
- Updated to SchXslt 1.7.1
v6.1.0 - 2021-03-22
- Updated to ph-commons 10
- Extended API to have SchematronResource
fromClassPathoverloads withClassLoaderparameter - Made
SVRLHelper.getBeautifiedLocationmore flexible - The update to ph-commons 10 also fixed #110 - thanks @monapadu
v6.0.3 - 2021-01-28
- Updated to SchXslt 1.6.2
- Changed the internal XSLT caching lock management, so that the cache can be filled in parallel
v6.0.2 - 2021-01-06
- Updated the svrl.xsd to match the requirements of
diagnostic-referenceof ISO Schematron (see #85) - thanks @nkutsche - Language tag of a diagnostic is preserved in SVRL output (see #82) - thanks @dmj
v6.0.1 - 2020-12-04
- Made the "id" attribute accessible in
AbstractSVRLMessage(see #103) - thanks @mangeg
v6.0.0 - 2020-11-24
- Using the new Maven group ID
com.helger.schematron(the group ID of the Maven plugin stays untouched:com.helger.maven) - Created a new submodule
ph-schematron-apithat contains the shared implementation parts - Created a new submodule
ph-schematron-purethat contains the pure Java implementation - Created a new submodule
ph-schematron-xsltthat contains the XSLT based implementation (https://github.com/Schematron/schematron) - Created a new submodule
ph-schematron-schxsltthat contains the SchXslt based implementation (https://github.com/schxslt/schxslt) - Dropped the submodule
ph-schematron- pick one ofph-schematron-xsltorph-schematron-pureinstead - Started a Wiki at https://github.com/phax/ph-schematron/wiki
- Extended the SVRL XSD to also work if foreign elements are allowed see #111 (thanks @flowrider3000) and #101 (thanks @Michiel-s)
- The default processing engine for the Schematron validation changed from
puretoschematron - Added new class
SchematronXSLTValidatorSuccessfulReportOnlyinph-schematron-xslt - The pure implementation now also registers handles for the query bindings
xpath3andxslt3 - Added SchXslt 1.5.2 as a new way to create SVRL (the engine ID is 'schxslt-xslt2')
- The ANT task and the Maven plugin also support the SchXslt engine
v5.6.5 - 2020-11-19
- Updated to Saxon-HE 10.3
- Added
SchematronResourceXSLTCache.clearCache()andSchematronResourceSCHCache.clearCache()(see #109) - thanks @SnowMakerDemo
v5.6.4 - 2020-10-13
- Updated to ANT 1.10.9
- The Maven plugin now also complains on "successful reports" (see #108) - thanks @lueck
v5.6.3 - 2020-09-28
v5.6.2 - 2020-09-17
- Updated to Jakarta JAXB 2.3.3
v5.6.1 - 2020-08-30
- Updated to ANT 1.10.8
- Updated to Saxon-HE 10.2
v5.6.0 - 2020-03-29
- Updated to ph-commons 9.4.0
- Updated to Saxon-HE 10.0
- Changed the internal error handler to use
IErrorand therefore also improve the error handling quality
v5.5.0 - 2020-03-08
- Updated to Saxon-HE 9.9.1-7
- Improved XPath configuration for the pure Schematron implementation (see PR #98) - thanks @aanno
- See new interface
IXPathConfigand builder classXPathConfigBuilder
- See new interface
v5.4.1 - 2020-03-08
- Updated to Saxon-HE 9.9.1-6
- Added a "lenient" setting to the pure Schematron implementation to allow reading Schematrons with an old namespace URI (see PR #97) - thanks @aanno
- Added the "lenient" flag to the Maven plugin for validating documents
v5.4.0 - 2019-11-29
- Changed the package of the generated SVRL classes from
org.oclc.purl.dsdl.svrltocom.helger.schematron.svrl.jaxbto avoid incompatibilities with other Schematron solutions (incompatible change) - Removed
ph-sch2xslt-maven-pluginwhich was deprecated long time ago. Useph-schematron-maven-plugininstead.
v5.3.0 - 2019-11-22
- Updated to ANT 1.10.7
- Updated to Saxon-HE 9.9.1-5
- The default include handler of the pure version, now allows to include non-Schematron XMLs
- The Maven plugin
preprocessMojo now emits the XML declaration as well - Added support for the Schematron query bindings
xpathandxpath2(issue #80) - Extended API of
SCHTransformerCustomizerfor forcing result caching (issue #87), added new parameters in Maven plugin and ANT task for this setting (forceCacheResult) - Renamed method
IPSValidationHandler.onRuletoonFiredRule(incompatible change) - Added methods
IPSValidationHandler.onRuleStartandandfor chaining
v5.2.0 - 2019-06-13
- Fixed a ClassLoader issues for ANT task (issue #78)
- Updated the SVRL XSD with the ISO Schematron 2016 changes (incompatible change)
v5.1.1 - 2019-06-12
- Fixed regression in ANT task (see issue #71)
v5.1.0 - 2019-06-11
- Updated to ANT 1.10.6
- Updated to Saxon-HE 9.9.1-3
- Fixed created Schematron XSDs (issue #76)
- Improved logging results in ANT task (issue #71)
- Added new ANT task parameters
failOnValidationError,failOnValidationWarnandfailOnValidationInfothat all default tofalse(issue #50) - Removed deprecated methods
- SCH and XSLT based compilers now correctly pass the
URIResolverto the created XSLT - important for include resolution (issue #77) - The default include resolver was improved for file based SCH and XSLT validation
v5.0.10 - 2019-05-07
- Improved handling of XML elements from other namespaces (issue #51)
- The Maven preprocess goal now uses the
<ns>elements from the Schematron as XML namespace context - The ANT task is now build against 1.10.x but is source compatible with ANT 1.9.x
- Added Java 12 support for Maven plugins
v5.0.9 - 2019-04-25
- Updated to ant 1.9.14
- Updated to Saxon-HE 9.9.1-1
- The Maven plugin
ph-sch2xslt-maven-pluginis now deprecated and will be removed in the next major version. The functionality was moved "as-is" to theph-schematron-maven-plugin - The Maven plugin
ph-schematron-maven-plugingot a new goalpreprocessto create preprocessed Schematrons (issue #75)
v5.0.8 - 2018-11-26
- Fixed an initialization error in the SCH to XSLT maven plugin in JDK 11
v5.0.7 - 2018-11-22
- Updated to ph-commons 9.2.0
- Updated to Saxon-HE 9.9.0-1
v5.0.6 - 2018-09-09
- The Ant task has the possibility to provide custom parameters to XSLT and SCH validations (issue #62)
- Instances of
SchematronResourceSCHnow have a default URI resolver to resolve references relative to the source Schematron - Requires ph-commons 9.1.5
-
SVRLHelpercan now handlenullinputs
v5.0.5 - 2018-08-13
- Updated to Saxon-HE 9.8.0-14
- Added support to disable "fail fast" mode in ph-schematron-maven-plugin (see issue #69)
- Fixed custom error handling for
reportwhen usingrole(see issue #66 again)
v5.0.4 - 2018-05-14
- Really fixed OSGI ServiceProvider configuration
- Updated to Saxon-HE 9.8.0-12
v5.0.3 - 2018-05-09
- Fixed OSGI ServiceProvider configuration
v5.0.2 - 2018-04-12
- Added new interface
ISchematronXSLTBasedResourceas a common base class for XSLT based validations - Improved the
DefaultSVRLErrorLevelDeterminatorimplementation to be more flexible and cater for more error levels - Updated to Saxon-HE 9.8.0-11
- The Maven plugins now require Maven 3.0
- Added new parameter
parametersto theph-sch2xslt-maven-plugin - Finally the
roleattribute is copied to a failed assertion when using the pure implementation - The Ant task has the possibility to provide values for
roleandflagthat are interpreted as error (issue #66)
v5.0.1 - 2018-02-01
- Moved
getBeautifiedLocationto classSVRLHelperand made it public - Updated to Saxon-HE 9.8.0-7
- Requires ph-commons 9.0.1
v5.0.0 - 2018-01-02
- Updated to ph-commons 9.0.0
- Added new ANT task for preprocessing Schematron files only
- Improved support for
base-uri()XPath function when using the pure implementation (issue #47) - Fixed issue with
roleattribute in SVRL when using pure implementation (issue #54) - Updated to Saxon-HE 9.8.0-6 - therefore no XLST v1 scripts can be used anymore - this only works up to 9.7.x!
- Added ANT task property
failOnError(issue #57)
v4.3.4 - 2017-07-27
- Added new class
SchematronDebugthat centrally manages the debug flags for logging etc.
v4.3.3 - 2017-07-27
- Reverted to Saxon-HE 9.7.0_18 because of incompatibilities in production
v4.3.2 - 2017-07-25
- Updated to Saxon-HE 9.8.0-3
- Changed all XSLT scripts to use and create only XSLT 2.0 (because Saxon 9.8.x does not support XSLT 1.0 anymore)
- Updated to ph-commons 8.6.6
v4.3.1 - 2017-05-29
- Updated to ph-commons 8.6.5
- Fixed too verbose logging of created XSLT
- Removed some old deprecated methods
v4.3.0 - 2017-05-15
- Updated to Saxon-HE 9.7.0-18
- Fixed an error with nested SVRL directories in Maven plugin (issue #37)
- Added possibility to use "negative" tests in Maven plugin (issue #38)
- Added ANT plugin to validate Schematron resources (issue #39, issue #40)
- Using the EntityResolver also for the XML files to be validated (not just the Schematron)
- Added a default
EntityResolverand a defaultURIResolverthat tries to resolve includes relative to the base Schematron.
v4.2.2 - 2017-02-22
- Updated to Saxon-HE 9.7.0-15
- Fixed usage of
<let>in<extend>-based rules for the pure implementation (issue #36)
v4.2.1 - 2017-01-20
- Added WrappedCollectingPSErrorHandler
v4.2.0 - 2017-01-09
- Binds to ph-commons 8.6.0
- Updated to Saxon-HE 9.7.0-14
- Added a new Schematron validation Maven plugin
v4.1.1 - 2016-11-03
- Added possibility to use XML EntityResolver (issue #30)
- Updated to Saxon-HE 9.7.0-10
v4.1.0 - 2016-09-09
- Binding to ph-commons 8.5.x
v4.0.2 - 2016-07-22
v4.0.1 - 2016-07-05
- better integration of sch2xslt Maven plugin into m2e - thanks to @baerrach
v4.0.0 - 2016-06-15
- updated to JDK8
- updated to Saxon-HE 9.7
v3.0.1 - 2015-10-14
- keep diagnostics in Pure version; resource resolving emits to error handler
v3.0.0 - 2015-07-29
- because of update to ph-commons 6.0.0; extended XSLT based API
v2.9.2 - 2015-03-12
- because of update to ph-commons 5.6.0
v2.9.1 - 2015-02-03
- fixes a classloader issue added in 2.9.0
v2.9.0 - 2015-01-30
- introduced new APIs in several places
- updated to Saxon-HE 9.6
v2.8.4 - 2014-10-30
v2.8.3 - 2014-09-16
- An easy way to use XQuery functions (like funcx library) as custom XPath functions was added
v2.8.2 - 2014-09-02
v2.8.1 - 2014-08-29
v2.8.0 - 2014-08-28