David Maus

A container element for abstract Schematron rules

I found the following usage patterns in the recently published version of the Lightweight Information Describing Objects schema (LIDO) and Antenna House's focheck utility.

In both cases the abstract rules are referenced in a rule attribute of a sch:extends element.

This use of abstract rules is at odds with the Schematron specification. Section 5.4.13 specifies an abstract rule as a list of assertions that will be invoked by rules belonging to the same pattern. Meaning, you can only sch:extend an abstract rule if it is defined in the same pattern. To some degree this makes sense. The sch:pattern element provides scope to the contained rules such that patterns are independent of each other.

Technically you can work around this limitation using sch:extends with a href attribute. This attribute is mutual exclusive with the rule attribute and was introduced with the 2016 release of the Schematron specification. It ought to reference a Schematron element in an external declaration whose content should be inserted in place of the sch:extends element.

But this feels wrong.

First, the semantics of sch:extends with href is defined by what the processor should do — insert the contents in place of the extends element — rather than by what we want to express.

Second, it forces you to externalize parts of your schema for the only reason to make them available.

Third, the way href works forces you to create one file per abstract rule, or to rely on the Schematron implementation to resolve a fragment identifier to a rule in the external file.

E.g. the rule

<rule context="fo:*/@border-bottom-color">  <extends rule="color-transparent"/></rule>

needs to be rewritten as

<rule context="fo:*/@border-bottom-color">  <extends href="abstract.sch#color-transparent"/></rule>

and the Schematron processor needs to resolve the fragment #color-transparent to the corresponding rule.

Note that sch:extends is only allowed as child of a sch:rule. Thus, its sole purpose is to reuse constraints from a different pattern.

I think adding the href attribute to sch:extends is the wrong solution for reuse across patterns.

Instead, I propose a new top-level sch:rules element that contains only abstract rules. The abstract rules defined in this element are globally available and can be used in a rule attribute of a sch:extends element.

This proposed element requires the following changes to the text of the 2020 specification: