// ISO_SVRL.xsl
//
// Implementation of Schematron Validation Report Language from ISO Schematron
// ISO/IEC 19757 Document Schema Definition Languages (DSDL)
// Part 3: Rule-based validation Schematron
// Annex D: Schematron Validation Report Language
//
// This ISO Standard is available free as a Publicly Available Specification in PDF from ISO.
// Also see www.schematron.com for drafts and other information.
//
// This implementation of SVRL is designed to run with the "Skeleton" implementation
// of Schematron which Oliver Becker devised. The skeleton code provides a
// Schematron implementation but with named templates for handling all output;
// the skeleton provides basic templates for output using this API, but client
// validators can be written to import the skeleton and override the default output
// templates as required. (In order to understand this, you must understand that
// a named template such as "process-assert" in this XSLT stylesheet overrides and
// replaces any template with the same name in the imported skeleton XSLT file.)
//
// The other important thing to understand in this code is that there are different
// versions of the Schematron skeleton. These track the development of Schematron through
// Schematron 1.5, Schematron 1.6 and now ISO Schematron. One only skeleton must be
// imported. The code has templates for the different skeletons commented out for
// convenience. ISO Schematron has a different namespace than Schematron 1.5 and 1.6;
// so the ISO Schematron skeleton has been written itself with an optional import
// statement to in turn import the Schematron 1.6 skeleton. This will allow you to
// validate with schemas from either namespace.
//
//
// History:
// 2010-07-10
// * MIT license
// 2010-04-14
// * Add command line parameter 'terminate' which will terminate on first failed
// assert and (optionally) successful report.
// 2009-03-18
// * Fix atrribute with space "see " which generates wrong name in some processors
// 2008-08-11
// * RJ Fix attribute/@select which saxon allows in XSLT 1
// 2008-08-07
// * RJ Add output-encoding attribute to specify final encoding to use
// * Alter allow-foreign functionality so that Schematron span, emph and dir elements make
// it to the output, for better formatting and because span can be used to mark up
// semantically interesting information embedded in diagnostics, which reduces the
// need to extend SVRL itself
// * Diagnostic-reference had an invalid attribute @id that duplicated @diagnostic: removed
// 2008-08-06
// * RJ Fix invalid output: svrl:diagnostic-reference is not contained in an svrl:text
// * Output comment to SVRL file giving filename if available (from command-line parameter)
// 2008-08-04
// * RJ move sch: prefix to schold: prefix to prevent confusion (we want people to
// be able to switch from old namespace to new namespace without changing the
// sch: prefix, so it is better to keep that prefix completely out of the XSLT)
// * Extra signature fixes (PH)
// 2008-08-03
// * Repair missing class parameter on process-p
// 2008-07-31
// * Update skeleton names
// 2007-04-03
// * Add option generate-fired-rule (RG)
// 2007-02-07
// * Prefer true|false for parameters. But allow yes|no on some old for compatability
// * DP Diagnostics output to svrl:text. Diagnosis put out after assertion text.
// * Removed non-SVRL elements and attributes: better handled as an extra layer that invokes this one
// * Add more formal parameters
// * Correct confusion between $schemaVersion and $queryBinding
// * Indent
// * Validate against RNC schemas for XSLT 1 and 2 (with regex tests removed)
// * Validate output with UniversalTest.sch against RNC schema for ISO SVRL
//
// 2007-02-01
// * DP. Update formal parameters of overriding named templates to handle more attributes.
// * DP. Refactor handling of rich and linkable parameters to a named template.
//
// 2007-01-22
// * DP change svrl:ns to svrl:ns-in-attribute-value
// * Change default when no queryBinding from "unknown" to "xslt"
//
// 2007-01-18:
// * Improve documentation
// * KH Add command-line options to generate paths or not
// * Use axsl:attribute rather than xsl:attribute to shut XSLT2 up
// * Add extra command-line options to pass to the iso_schematron_skeleton
//
// 2006-12-01: iso_svrl.xsl Rick Jelliffe,
// * update namespace,
// * update phase handling,
// * add flag param to process-assert and process-report & @ flag on output
//
// 2001: Conformance1-5.xsl Rick Jelliffe,
// * Created, using the skeleton code contributed by Oliver Becker
// Open Source Initiative OSI - The MIT License:Licensing
// [OSI Approved License]
//
// This source code was previously available under the zlib/libpng license.
// Attribution is polite.
//
// The MIT License
//
// Copyright (c) 2004-2010 Rick Jellife and Academia Sinica Computing Centre, Taiwan
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Ideas nabbed from schematrons by Francis N., Miloslav N. and David C.
// The command-line parameters are:
// phase NMTOKEN | "#ALL" (default) Select the phase for validation
// allow-foreign "true" | "false" (default) Pass non-Schematron elements and rich markup to the generated stylesheet
// diagnose= true | false|yes|no Add the diagnostics to the assertion test in reports (yes|no are obsolete)
// generate-paths=true|false|yes|no generate the @location attribute with XPaths (yes|no are obsolete)
// sch.exslt.imports semi-colon delimited string of filenames for some EXSLT implementations
// optimize "visit-no-attributes" Use only when the schema has no attributes as the context nodes
// generate-fired-rule "true"(default) | "false" Generate fired-rule elements
// terminate= yes | no | true | false | assert Terminate on the first failed assertion or successful report
// Note: whether any output at all is generated depends on the XSLT implementation.
xsl:stylesheet(
version="1.0",
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias",
xmlns:iso="http://purl.oclc.org/dsdl/schematron",
xmlns:schold="http://www.ascc.net/xml/schematron",
xmlns:svrl="http://purl.oclc.org/dsdl/svrl",
xmlns:xs="http://www.w3.org/2001/XMLSchema",
xmlns:xsl="http://www.w3.org/1999/XSL/Transform")
// Select the import statement and adjust the path as
// necessary for your system.
// If not XSLT2 then also remove svrl:active-pattern/@document="{document-uri()}" from process-pattern()
// <xsl:import href="iso_schematron_skeleton_for_saxon.xsl"/>
xsl:import(href="iso_schematron_skeleton_for_xslt1.xsl")
// <xsl:import href="iso_schematron_skeleton.xsl"/>
// <xsl:import href="skeleton1-5.xsl"/>
// <xsl:import href="skeleton1-6.xsl"/>
param diagnose := true
param phase :=
choose:
// Handle Schematron 1.5 and 1.6 phases
when //schold:schema/@defaultPhase:
<- //schold:schema/@defaultPhase
// Handle ISO Schematron phases
when //iso:schema/@defaultPhase:
<- //iso:schema/@defaultPhase
else:
"#ALL"
param allow-foreign := false
param generate-paths := true
param generate-fired-rule := true
param optimize
param output-encoding
// e.g. saxon file.xml file.xsl "sch.exslt.imports=.../string.xsl;.../math.xsl"
param sch.exslt.imports
// Experimental: If this file called, then must be generating svrl
svrlTest := true()
// ================================================================
template process-prolog:
axsl:output(indent="yes", method="xml", omit-xml-declaration="no", standalone="yes")
if string-length($output-encoding) > 0:
@encoding
<- $output-encoding
// Overrides skeleton.xsl
template process-root:
param title
param contents
param queryBinding := xslt1
param schemaVersion
param id
param version
// "Rich" parameters
param fpi
param icon
param lang
param see
param space
svrl:schematron-output(schemaVersion="{$schemaVersion}", title="{$title}")
if string-length( normalize-space( $phase )) > 0 and
not( normalize-space( $phase ) = '#ALL') :
axsl:attribute(name="phase")
<- $phase
if $allow-foreign = 'true':
if $allow-foreign = 'true':
call richParms:
fpi := $fpi
icon := $icon
lang := $lang
see := $see
space := $space
axsl:comment
axsl:value-of(select="$archiveDirParameter")
axsl:value-of(select="$archiveNameParameter")
axsl:value-of(select="$fileNameParameter")
axsl:value-of(select="$fileDirParameter")
apply
copy $contents
template process-assert(test, diagnostics, id, flag, role, subject, fpi, icon, lang, see, space):
// "Linkable" parameters
// "Rich" parameters
svrl:failed-assert(test="{$test}")
if string-length( $id ) > 0:
axsl:attribute(name="id")
<- $id
if string-length( $flag ) > 0:
axsl:attribute(name="flag")
<- $flag
// Process rich attributes.
call richParms:
fpi := $fpi
icon := $icon
lang := $lang
see := $see
space := $space
call linkableParms:
role := $role
subject := $subject
if $generate-paths = 'true' or $generate-paths= 'yes' :
// true/false is the new way
axsl:attribute(name="location")
axsl:apply-templates(mode="schematron-get-full-path", select=".")
svrl:text
apply
if $diagnose = 'yes' or $diagnose= 'true' :
// true/false is the new way
call diagnosticsSplit:
str := $diagnostics
if $terminate = 'yes' or $terminate = 'true' :
axsl:message(terminate="yes") = TERMINATING
if $terminate = 'assert' :
axsl:message(terminate="yes") = TERMINATING
template process-report(id, test, diagnostics, flag, role, subject, fpi, icon, lang, see, space):
// "Linkable" parameters
// "Rich" parameters
svrl:successful-report(test="{$test}")
if string-length( $id ) > 0:
axsl:attribute(name="id")
<- $id
if string-length( $flag ) > 0:
axsl:attribute(name="flag")
<- $flag
// Process rich attributes.
call richParms:
fpi := $fpi
icon := $icon
lang := $lang
see := $see
space := $space
call linkableParms:
role := $role
subject := $subject
if $generate-paths = 'yes' or $generate-paths = 'true' :
// true/false is the new way
axsl:attribute(name="location")
axsl:apply-templates(mode="schematron-get-full-path", select=".")
svrl:text
apply
if $diagnose = 'yes' or $diagnose='true' :
// true/false is the new way
call diagnosticsSplit:
str := $diagnostics
if $terminate = 'yes' or $terminate = 'true' :
axsl:message(terminate="yes") = TERMINATING
// Overrides skeleton
template process-dir(value):
choose:
when $allow-foreign = 'true':
copy .
else:
// We generate too much whitespace rather than risking concatenation
axsl:text
apply
axsl:text
template process-diagnostic(id, fpi, icon, lang, see, space):
// Rich parameters
svrl:diagnostic-reference(diagnostic="{$id}")
call richParms:
fpi := $fpi
icon := $icon
lang := $lang
see := $see
space := $space
apply
// Overrides skeleton
template process-emph(class):
choose:
when $allow-foreign = 'true':
copy .
else:
// We generate too much whitespace rather than risking concatenation
axsl:text
apply
axsl:text
template process-rule(id, context, flag, role, subject, fpi, icon, lang, see, space):
// "Linkable" parameters
// "Rich" parameters
if $generate-fired-rule = 'true':
svrl:fired-rule(context="{$context}")
// Process rich attributes.
call richParms:
fpi := $fpi
icon := $icon
lang := $lang
see := $see
space := $space
if string( $id ):
@id
<- $id
if string-length( $role ) > 0:
@role
<- $role
template process-ns(prefix, uri):
svrl:ns-prefix-in-attribute-values(prefix="{$prefix}", uri="{$uri}")
template process-p(icon, class, id, lang):
svrl:text
apply
template process-pattern(name, id, is-a, fpi, icon, lang, see, space):
// "Rich" parameters
svrl:active-pattern
if string( $id ):
axsl:attribute(name="id")
<- $id
if string( $name ):
axsl:attribute(name="name")
<- $name
call richParms:
fpi := $fpi
icon := $icon
lang := $lang
see := $see
space := $space
// ?? report that this screws up iso:title processing
apply
// ?? Seems that this apply-templates is never triggered DP
axsl:apply-templates
// Overrides skeleton
template process-message(pattern, role):
// Overrides skeleton
template process-span(class):
choose:
when $allow-foreign = 'true':
copy .
else:
// We generate too much whitespace rather than risking concatenation
axsl:text
apply
axsl:text
// ===========================================================================
// processing rich parameters.
template richParms(fpi, icon, lang, see, space):
// "Rich" parameters
// Process rich attributes.
if $allow-foreign = 'true':
if string($fpi):
axsl:attribute(name="fpi")
<- $fpi
if string($icon):
axsl:attribute(name="icon")
<- $icon
if string($see):
axsl:attribute(name="see")
<- $see
if string($space):
axsl:attribute(name="xml:space")
<- $space
if string($lang):
axsl:attribute(name="xml:lang")
<- $lang
// processing linkable parameters.
template linkableParms(role, subject):
// ISO SVRL has a role attribute to match the Schematron role attribute
if string($role ):
axsl:attribute(name="role")
<- $role
// ISO SVRL does not have a subject attribute to match the Schematron subject attribute.
// Instead, the Schematron subject attribute is folded into the location attribute