ODD topics – Defining schematron constraints in ODD

Like any XML language, the TEI can be parsed with Schematron. Moreover, ODD supports natively the specification of Schematron rules,  and the TEI specification itself (for instance here: https://github.com/TEIC/TEI/blob/dev/P5/Source/Specs/att.datable.w3c.xml ) contains embedded schematron rules.

NB: This post doesn’t aim to explain how the Schematron language works. To learn more about Schematron, see W. Piez and D. Lapeyre, Introduction to Schematron, Mulberry Technologies, Inc, Nov. 2008. However, to minimally understand the following, you should know that Schematron, an ISO specification, is an XML language, based on the extensive use of XPath, that makes assertions or reports on the presence or absence of specific patterns in XML documents.

Schematron rules can be used to provide warnings without causing validation errors (i.e. “non-fatal errors”), or to add more qualitative rules to specific elements. For instance, one may want to set a character number limit for the content of a specific tag, or check the value of an attribute by means of a regular expression.

ODD makes it convenient to specify such rules at the same level of the element specification, in an element <constraintSpec>, possibly present in <attDef>, <classSpec>, <elementSpec>, or <schemaSpec> (see the TEI guidelines for more details). Inside <constraintSpec>, the <constraint> element contains assertions in the Schematron language, as shown in the following example:

<elementSpec ident="TEI" mode="change">
   <constraintSpec ident="xmlid" scheme="schematron" type="SSK">
      <constraint>
         <sch:rule context="tei:TEI">
            <sch:let name="fileName" value="tokenize(document-uri(/), '/')[last()]"/>
            <sch:assert test="string(@xml:id)=substring-before($fileName, '.xml')" role="error">
The xml:id of the TEI element should be equal to the name of the file,
without the file extension. Currently the value of xml:id is "<sch:value-of select="@xml:id"/>" 
whilst the file name is "<sch:value-of select="$fileName"/>"</sch:assert>
         </sch:rule>
      </constraint>
   </constraintSpec>
</elementSpec>

Two important caveats (thanks to Syd Bauman’s XPath and Schematron for TEI Customization, https://www.wwp.northeastern.edu/outreach/seminars/_current/presentations/schematron/schematron_odd.xml):

  1. the element <sch:rule> is not mandatory. When missing (i.e., just bare sch:assert and sch:report elements), the context of the Schematron rule is the element or attribute that is being defined (<elementSpec> or <attDef>).
  2. In <constraintSpec>, you need to specify the tei: prefix for TEI elements (see example below).

When a RELAX NG schema is generated from the ODD, the schematron rule will be embedded in the schema:

<define name="tei_TEI">
   <element name="TEI">
   ... 
      <pattern xmlns="http://purl.oclc.org/dsdl/schematron"
               id="myTEI-TEI-xmlid-constraint-rule-10">
         <sch:rule xmlns="http://www.tei-c.org/ns/1.0"
                   xmlns:sch="http://purl.oclc.org/dsdl/schematron"
                   context="tei:TEI">
            <sch:let name="fileName" value="tokenize(document-uri(/), '/')[last()]"/>
            <sch:assert test="string(@xml:id) = substring-before($fileName, '.xml')" role="error">
The xml:id of the TEI element should be equal to the name of the file, 
without the file extension. Currently the value of xml:id is "<sch:value-of select="@xml:id"/>" 
whilst the file name is "<sch:value-of select="$fileName"/>"</sch:assert>
         </sch:rule>
      </pattern>
   ...
   </element>
</define>

This embedded Schematron rule is checked in addition to the RELAX NG when performing file validation, as shown in the following images:

See the full ODD example under:https://github.com/laurentromary/ODDtopics/blob/master/ODD%20examples/schematronODD.xml


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.