Chapter 8. Abstract patterns and includes..

Table of Contents

Includes

The patterns we have seen so far have been concrete, insofar as each pattern has been explicit. For readers with a programming background, the abstract pattern is a way of re-using patterns with minor changes made through parameters, just as methods are modified for re-use through parameter values. The standard defines abstract rules as named lists of assertions without a context. That is the key. The context is specified when the abstract rule is used.

As of 2007-01-26T09:08:05.0Z, no XSLT stylesheet is available to pre-process these. The principle is to transform these abstract patterns into concrete ones, effectively expanding the macros to produce a Schematron file. The standard has examples of this class of pattern in ¶5.4.9

A minor diversion into patterns is called for now. The schema for Schematron has a complex definition for pattern which is shown below in a pseudo DTD syntax. There are basically three options for the children of the pattern element. The first is used when defining an abstract pattern. A pattern is defined as abstract when it has the abstract attribute with a value of true. If the abstract attribute has a value of true, then it must also have an id attribute. The id value is the label used as the target of a pattern which is said to be an instance of an abstract pattern. This is a pattern which makes use of the abstract pattern, it could be said to 'fill in the values' or instantiate the pattern.

To repeat that. An abstract pattern contains rules which use parameters. Call this the pattern definition. An abstract pattern instance provides values for the parameters (using the param attribute) and might be said to create an instance of the pattern. The third set of children for a pattern are the ones which we have already met, which are not discussed here. Now for the syntax groups, Example 8.1, “pattern syntax”. The syntax used is as per a DTD, ? means optional, * means zero or more.

Example 8.1. pattern syntax


element pattern
  Rich attributes (icon, see, xml:lang xml:space - decorations)
Foreign elements (in other namespaces)
Inclusion  (include external Schematron files here)

group 1 (define an abstract pattern)                1
 Attributes:  abstract='true' , id , title? 
 child elements: p* , let* , rule*


group 2 (create an instance of an abstract pattern)  2
 Attributes:  abstract='false'? , id? , title?  is-a
 child elements: p* , param*


group 3 (use for non-abstract patterns, as seen previously)  3
 Attributes:  abstract='false'? , id? , title? 
 child elements: p* , let* , rule*

1

Grammar for defining an abstract pattern. The id attribute identifies it.

2

Grammar for using an abstract pattern. The is-a attribute refers to the abstract pattern it instantiates.

3

Standard grammar for non abstract patterns


If you look at 2, ¶5.4.9, there is an example of an abstract pattern definition and use. A modified version is shown below, with comments.

Example 8.2. An abstract pattern example


<!-- Abstract pattern definition -->
<iso:pattern  abstract='true' id='table'>  1
 <iso:rule context='$table'>               2
   <iso:assert test='$row'><iso:name/> element should contain rows</iso:assert>
 </iso:rule>

 <iso:rule context='$row'>                 3
   <iso:assert test='$entry'><iso:name/> element should contain entries</iso:assert>
 </iso:rule>
</iso:pattern>


<!-- instantiate the pattern for an html table  -->
<iso:pattern is-a='table' id='html-table'>  4
  <iso:param name='table' value='table'/>
  <iso:param name='row'   value='tr'/>      5
  <iso:param name='entry' value='td|th'/>
</iso:pattern>

<!-- And re-use it for a CALS table, same structure, different elements  -->
<iso:pattern is-a='table' id='CALS-table'>  6
  <iso:param name='table' value='table'/>
  <iso:param name='row'   value='.//row'/>  7
  <iso:param name='entry' value='cell'/>
</iso:pattern>

1

The abstract pattern, with id table

2

A rule for context X (variable table)

3

A rule for context Y (variable row)

4 6

Make use of the pattern, providing values for the 'variables' by the parameters

5

E.g. the row variable is instantiated by the html tr context

7

Here the row variable is instantiated by the CALS row, called row, in a different position to the HTML row!


Perhaps you can see the use of the grammar shown in Example 8.1, “pattern syntax”, group 1 and 2.

When these abstract patterns are resolved, the parameters will provide values for the abstract patterns, the rules will become 'concrete', taking those values, to provide something like Example 8.3, “The instantiated pattern for the CALS table usage” for the CALS table usage.

Example 8.3. The instantiated pattern for the CALS table usage

  
<iso:pattern   id='table'>  
 <iso:rule context='table'>               
   <iso:assert test='row'><iso:name/> element should contain rows</iso:assert>
 </iso:rule>

 <iso:rule context='../row'>                 
   <iso:assert test='cell'><iso:name/> element should contain entries</iso:assert>
 </iso:rule>
</iso:pattern>


Of course this is only produced as part of the processing of your Schematron file, it is shown here as it would appear if you chose to write it out the long way. The utility of the abstract pattern is that it enables pattern re-use.

A stylesheet is provided, see Chapter 11, ISO implementation Stylesheets, which transforms abstract patterns into concrete ones.

One final comment on abstract patterns, for the context attribute on a rule element. It may take more than one variable, so the abstract pattern may have a rule which looks like Example 8.4, “Multiple variables in a context”

Example 8.4. Multiple variables in a context


  <iso:pattern  abstract='true' id='table'>  
 <iso:rule context='$table[@class=$type]'>               
   <iso:assert test='$row'><iso:name/> element should contain rows</iso:assert>
 </iso:rule>

</iso:pattern>


Here two variables are used in the rule context. Again this hints at the possibilities for abstract patterns. It seems that your imagination is likely to be the limit!

Includes

The syntax for an included file is


  <iso:include href='filename.sch'/>

This element can appear anywhere within the schema element, replacing patterns, rules etc. The only validity constraint is that the resulting Schematron file must be valid to the Schematron schema. The include file itself must be valid XML, valid to the part of the schema that it will instantiate. It must also have a single root, i.e. such an included file cannot contain two rules (which would equate to two roots!)

Processing an include requires that it is the first step in the chain of steps needed to process a Schematron file. This is because the included content may itself contain abstract patterns which require processing. See Chapter 11, ISO implementation Stylesheets for an example stylesheet.

An example is shown in Example 8.5, “A simple include example” below, which is a simple example whereby a single rule is in an external file and included into the main Schematron file.

Example 8.5. A simple include example


  <?xml version="1.0" encoding="iso-8859-1"?>
<!-- The main Schematron file -->

<iso:schema    xmlns="http://purl.oclc.org/dsdl/schematron" 
	       xmlns:iso="http://purl.oclc.org/dsdl/schematron" 
	       xmlns:sch="http://www.ascc.net/xml/schematron"
	       queryBinding='xslt2'
	       schemaVersion="ISO19757-3">
  <iso:title>Test ISO schematron file. Introduction mode </iso:title>
  <!-- Not used in first run -->
  <iso:ns prefix="dp" uri="http://www.dpawson.co.uk/ns#" />

<iso:pattern id="doc.checks">
  <iso:title>checking an XXX document</iso:title>
  <iso:rule context="doc">
    <iso:report 
test="chapter">Report date.<iso:value-of select="current-dateTime()"/></iso:report>
  </iso:rule>
</iso:pattern>

  <iso:pattern id="chapter.checks">
    <iso:title>Basic Chapter checks</iso:title>
    <iso:p>All chapter level checks. </iso:p>

 <iso:include href='input.incl'/>                        1              

  </iso:pattern>
</iso:schema>


<!-- The included file input.incl-->


<?xml version="1.0" encoding="iso-8859-1"?>
   <iso:rule context="chapter"
   xmlns:iso="http://purl.oclc.org/dsdl/schematron"          2   
   >                        3     
      <iso:assert test="title">Chapter should have  a title</iso:assert>
      <iso:report test="count(para)"><iso:value-of select="count(para)"/> paragraphs</iso:report>
      <iso:assert test="count(para) >= 1">A chapter must have one or more paragraphs</iso:assert>
      <iso:assert test="*[1][self::title]">Title must be first child of chapter</iso:assert>
      <iso:assert test="@id">All chapters must have an ID attribute</iso:assert>
    </iso:rule>

1

The include statement, where the included text will be brought in

2

Since the elements are namespaced, the namespace prefix must be declared

3

The XML which will be included to form a valid Schematron file


The mechanics are simple, it is the classic software engineering include pattern. The referenced text is inserted into the referring file at the point of inclusion. The time at which this is done is implementation dependent, though the stylesheet which implements the abstract patterns provides the ideal time for processing inclusions. See Chapter 11, ISO implementation Stylesheets for an example stylesheet which processes inclusions.

Warning

Note that an include file can itself contain include files. The possibility exists of infinite recursion. You need to manage this.

Legal Notice