Converting XML Schemas to Schematron (#12): Some better diagnostics

by Rick Jelliffe

One simplification I have made in the XSLT code presented so far is that except for datatypes I have elided the issue of diagnostics. Yet the ability to provide better diagnostics is one of the value propositions for Schematron. So lets quickly add in some diagnostics!

In Schematron schemas, a distinction is made between assertions, which are positive natural language statements about what should be found in a schema (and if possible why!) and diagnostics which provide information about errors for users. So the schema might say "Element X should be followed by element Y" and the diagnostics might say "Element X was followed by element Z". The user gets both pieces of information.

But in a well-written schema, the assertions can pretty much be printed off without theirXPath paraphernalia as bullet points and read as software requirements or human-usable documentation. See Autogenerating standards from Schematron schemas for an XSLT script that does this.

So here is our basic diagnostics section. These are each linked to from the appropriate assertions using the diagnostics attribute to reference the diagnostic element's ID..

<sch:diagnostic id="d1">This element was found:
"<sch:value-of select="*/name()"/>".</sch:diagnostic>

<sch:diagnostic id="typo-element">This element was found:
"<sch:name/>" in "<sch:value-of select="parent::*/name()"/>".</sch:diagnostic>

<sch:diagnostic id="typo-attribute">This attribute was found:
"<sch:name/>" on "<sch:value-of select="parent::*/name()"/>".</sch:diagnostic>

<sch:diagnostic id="expected-element">This element was found:
"<sch:name/>" in "<sch:value-of select="parent::*/name()"/>".</sch:diagnostic>

<sch:diagnostic id="expected-attribute">This attribute was found:
"<sch:name/>" on "<sch:value-of select="parent::*/name()"/>".</sch:diagnostic>

<sch:diagnostic id="unexpected-immediate-follower">This element was found:
"<sch:value-of select="following-sibling::*[1]/name()"/>".</sch:diagnostic>

<xsl:comment>Generating Diagnostics for xs:all/xs:elements
<xsl:for-each select="xs:element[.//xs:all]//xs:all/xs:element">
<xsl:variable name="ancestor-element" select="ancestor::xs:element/@name"/>
<xsl:variable name="element-name" select="if (@name) then @name else @ref"/>
<sch:diagnostic id="{concat('d2-',$ancestor-element,'-',$element-name)}">
<sch:value-of select="count($element-name)"/>
"<xsl:value-of select="$element-name"/>" elements were found</sch:diagnostic>

<!-- generate diagnostic for each standard datatypes -->
<xsl:call-template name="generate-standard-datatypes-diagnostics"/>

This is the last in this round of articles on the XSLT to Schematron converter about schema generation, probably. Thanks to JSTOR and Allette Systems for sponsoring its development. I hope to be transferring the to SourceForge under GPL in February, though I want to divide the main code out into nice separate files first, for maintainability. I am very interested in finding anyone interested in taking over or contributing to the project&,dash;I have a backlog of Schematron matters to attend to!