home *** CD-ROM | disk | FTP | other *** search
- <?xml version="1.0"?>
- <!-- Beta Skeleton Module for the Schematron 1.5 XML Schema Language.
- http://www.ascc.net/xml/schematron/
-
- Copyright (c) 2000,2001 Rick Jelliffe and Academia Sinica Computing Center, Taiwan
-
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from
- the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not claim
- that you wrote the original software. If you use this software in a product,
- an acknowledgment in the product documentation would be appreciated but is
- not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
-
- 3. This notice may not be removed or altered from any source distribution.
- -->
- <!--
- Version: 2001-06-12
- * same skeleton now supports namespace or no namespace
- * parameters to handlers updated for all 1.5 attributes
- * diagnostic hints supported: command-line option diagnose=yes|no
- * phases supported: command-line option phase=#ALL|...
- * abstract rules
- * compile-time error messages
- * 1.6 feature: @match on sch:key
-
- Contributors: Rick Jelliffe (original), Oliver Becker (architecture),
- Miloslav Nic (diagnostic, phase, options), Ludwig Svenonius (abstract)
- Uche Ogbuji (misc. bug fixes), Jim Ancona (SAXON workaround),
- Eddie Robertsson (misc. bug fixes)
-
- XSLT versions tested and working as-is:
- * MS XML 3
- * Oracle
- * SAXON + Instant Saxon
- * XT n.b. key() not available, will die
-
- XSLT version reliably reported working
- * FourThought's Python implementation
-
- XSLT versions tested and requires small workaround from you
- * Sablotron does not support import, so merge meta-stylesheets by hand
- * Xalan for Java 2.0 outputs wrong namespace URI, so alter by hand or script
- * Xalan for C 1.0 has problem with key, so edit by hand. Find "KEY" below
-
- If you create your own meta-stylesheet to override this one, it is a
- good idea to have both in the same directory and to run the stylesheet
- from that directory, as many XSLT implementations have ideosyncratic
- handling of URLs: keep it simple.
-
- -->
- <xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias"
- xmlns:sch="http://www.ascc.net/xml/schematron"
- >
- <!-- Note that this namespace is not version specific.
- This program implements schematron 1.5 with some 1.6 extensions -->
- <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
- <!-- Category: top-level-element -->
- <xsl:output method="xml" omit-xml-declaration="no" standalone="yes" indent="yes"/>
- <xsl:param name="block"></xsl:param><!-- reserved -->
- <xsl:param name="phase">
- <xsl:choose>
- <xsl:when test="//sch:schema/@defaultPhase">
- <xsl:value-of select="//sch:schema/@defaultPhase"/>
- </xsl:when>
- <xsl:otherwise>#ALL</xsl:otherwise>
- </xsl:choose>
- </xsl:param>
- <xsl:param name="hiddenKey"> key </xsl:param><!-- workaround for Xalan4J 2.0 -->
-
- <!-- SCHEMA -->
- <xsl:template match="sch:schema | schema">
- <axsl:stylesheet version="1.0">
- <xsl:for-each select="sch:ns | ns">
- <xsl:attribute name="{concat(@prefix,':dummy-for-xmlns')}" namespace="{@uri}"/>
- </xsl:for-each>
-
- <xsl:if test="count(sch:title/* | title/* )">
- <xsl:message>
- <xsl:text>Warning: </xsl:text>
- <xsl:value-of select="name(.)"/>
- <xsl:text> must not contain any child elements</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:call-template name="process-prolog"/>
- <!-- utility routine for implementations -->
- <axsl:template match="*|@*" mode="schematron-get-full-path">
-
- <axsl:apply-templates select="parent::*" mode="schematron-get-full-path"/>
- <axsl:text>/</axsl:text>
- <axsl:if test="count(. | ../@*) = count(../@*)">@</axsl:if>
- <axsl:value-of select="name()"/>
- <axsl:text>[</axsl:text>
- <axsl:value-of select="1+count(preceding-sibling::*[name()=name(current())])"/>
- <axsl:text>]</axsl:text>
- </axsl:template>
-
- <xsl:apply-templates mode="do-keys"
- select="sch:pattern/sch:rule/sch:key | pattern/rule/key | sch:key | key "/>
-
-
- <axsl:template match="/">
- <xsl:call-template name="process-root">
- <xsl:with-param name="fpi" select="@fpi"/>
- <xsl:with-param xmlns:sch="http://www.ascc.net/xml/schematron"
- name="title" select="./sch:title | title"/>
- <xsl:with-param name="id" select="@id"/>
- <xsl:with-param name="icon" select="@icon"/>
- <xsl:with-param name="lang" select="@xml:lang"/>
- <xsl:with-param name="version" select="@version" />
- <xsl:with-param name="schemaVersion" select="@schemaVersion" />
- <xsl:with-param name="contents">
- <xsl:apply-templates mode="do-all-patterns"/>
- </xsl:with-param>
- </xsl:call-template>
- </axsl:template>
-
- <xsl:apply-templates/>
- <axsl:template match="text()" priority="-1">
- <!-- strip characters -->
- </axsl:template>
- </axsl:stylesheet>
- </xsl:template>
-
- <!-- ACTIVE -->
- <xsl:template match="sch:active | active">
- <xsl:if test="not(@pattern)">
- <xsl:message>Markup Error: no pattern attribute in <active></xsl:message>
- </xsl:if>
- <xsl:if test="//sch:rule[@id= current()/@pattern]">
- <xsl:message>Reference Error: the pattern "<xsl:value-of select="@pattern"/>" has been activated but is not declared</xsl:message>
- </xsl:if>
- </xsl:template>
-
- <!-- ASSERT and REPORT -->
- <xsl:template match="sch:assert | assert">
- <xsl:if test="not(@test)">
- <xsl:message>Markup Error: no test attribute in <assert></xsl:message>
- </xsl:if>
- <axsl:choose>
- <axsl:when test="{@test}"/>
- <axsl:otherwise>
- <xsl:call-template name="process-assert">
- <xsl:with-param name="role" select="@role"/>
- <xsl:with-param name="id" select="@id"/>
- <xsl:with-param name="test" select="normalize-space(@test)" />
- <xsl:with-param name="icon" select="@icon"/>
- <xsl:with-param name="subject" select="@subject"/>
- <xsl:with-param name="diagnostics" select="@diagnostics"/>
- </xsl:call-template>
- </axsl:otherwise>
- </axsl:choose>
- </xsl:template>
- <xsl:template match="sch:report | report">
- <xsl:if test="not(@test)">
- <xsl:message>Markup Error: no test attribute in <report></xsl:message>
- </xsl:if>
- <axsl:if test="{@test}">
- <xsl:call-template name="process-report">
- <xsl:with-param name="role" select="@role"/>
- <xsl:with-param name="test" select="normalize-space(@test)" />
- <xsl:with-param name="icon" select="@icon"/>
- <xsl:with-param name="id" select="@id"/>
- <xsl:with-param name="subject" select="@subject"/>
- <xsl:with-param name="diagnostics" select="@diagnostics"/>
- </xsl:call-template>
- </axsl:if>
- </xsl:template>
-
-
- <!-- DIAGNOSTIC -->
- <xsl:template match="sch:diagnostic | diagnostic"
- ><xsl:if test="not(@id)"
- ><xsl:message>Markup Error: no id attribute in <diagnostic></xsl:message
- ></xsl:if><xsl:call-template name="process-diagnostic">
- <xsl:with-param name="id" select="@id" />
- </xsl:call-template>
- </xsl:template>
-
- <!-- DIAGNOSTICS -->
- <xsl:template match="sch:diagnostics | diagnostics"/>
-
- <!-- DIR -->
- <xsl:template match="sch:dir | dir" mode="text"
- ><xsl:call-template name="process-dir">
- <xsl:with-param name="value" select="@value"/>
- </xsl:call-template>
- </xsl:template>
-
- <!-- EMPH -->
- <xsl:template match="sch:emph | emph" mode="text"
- ><xsl:call-template name="process-emph"/>
- </xsl:template>
-
- <!-- EXTENDS -->
- <xsl:template match="sch:extends | extends">
- <xsl:if test="not(@rule)"
- ><xsl:message>Markup Error: no rule attribute in <extends></xsl:message
- ></xsl:if>
- <xsl:if test="not(//sch:rule[@abstract='true'][@id= current()/@rule] )
- and not(//rule[@abstract='true'][@id= current()/@rule])">
- <xsl:message>Reference Error: the abstract rule "<xsl:value-of select="@rule"/>" has been referenced but is not declared</xsl:message>
- </xsl:if>
- <xsl:call-template name="IamEmpty" />
-
- <xsl:if test="//sch:rule[@id=current()/@rule]">
- <xsl:apply-templates select="//sch:rule[@id=current()/@rule]"
- mode="extends"/>
- </xsl:if>
-
- </xsl:template>
-
- <!-- KEY -->
- <!-- do we need something to test uniqueness too? -->
- <!-- NOTE: if you get complaint about "key" here (e.g. Xalan4C 1.0) replace
- "key" with "$hiddenKey" -->
- <xsl:template match="sch:key | key " mode="do-keys" >
- <xsl:if test="not(@name)">
- <xsl:message>Markup Error: no name attribute in <key></xsl:message>
- </xsl:if>
- <xsl:if test="not(@match) and not(../sch:rule)">
- <xsl:message>Markup Error: no match attribute on <key> outside <rule></xsl:message>
- </xsl:if>
- <xsl:if test="not(@path)">
- <xsl:message>Markup Error: no path attribute in <key></xsl:message>
- </xsl:if>
- <xsl:call-template name="IamEmpty" />
-
- <xsl:choose>
- <xsl:when test="@match">
- <axsl:key match="{@match}" name="{@name}" use="{@path}"/>
- </xsl:when>
- <xsl:otherwise>
- <axsl:key name="{@name}" match="{parent::sch:rule/@context}" use="{@path}"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
- <xsl:template match="sch:key | key" /><!-- swallow -->
-
- <!-- NAME -->
- <xsl:template match="sch:name | name" mode="text">
- <axsl:text xml:space="preserve"> </axsl:text>
- <xsl:if test="@path"
- ><xsl:call-template name="process-name">
- <xsl:with-param name="name" select="concat('name(',@path,')')"/>
- <!-- SAXON needs that instead of select="'name({@path})'" -->
- </xsl:call-template>
- </xsl:if>
- <xsl:if test="not(@path)"
- ><xsl:call-template name="process-name">
- <xsl:with-param name="name" select="'name(.)'"/>
- </xsl:call-template>
- </xsl:if>
- <xsl:call-template name="IamEmpty" />
- <axsl:text xml:space="preserve"> </axsl:text>
- </xsl:template>
-
- <!-- NS -->
- <xsl:template match="sch:ns | ns" mode="do-all-patterns" >
- <xsl:if test="not(@uri)">
- <xsl:message>Markup Error: no uri attribute in <ns></xsl:message>
- </xsl:if>
- <xsl:if test="not(@prefix)">
- <xsl:message>Markup Error: no prefix attribute in <ns></xsl:message>
- </xsl:if>
- <xsl:call-template name="IamEmpty" />
- <xsl:call-template name="process-ns" >
- <xsl:with-param name="prefix" select="@prefix"/>
- <xsl:with-param name="uri" select="@uri"/>
- </xsl:call-template>
- </xsl:template>
- <xsl:template match="sch:ns | ns" /><!-- swallow -->
-
- <!-- P -->
- <xsl:template match="sch:schema/sch:p | schema/p" mode="do-schema-p" >
- <xsl:call-template name="process-p">
- <xsl:with-param name="class" select="@class"/>
- <xsl:with-param name="icon" select="@icon"/>
- <xsl:with-param name="id" select="@id"/>
- <xsl:with-param name="lang" select="@xml:lang"/>
- </xsl:call-template>
- </xsl:template>
- <xsl:template match="sch:pattern/sch:p | pattern/p" mode="do-pattern-p" >
- <xsl:call-template name="process-p">
- <xsl:with-param name="class" select="@class"/>
- <xsl:with-param name="icon" select="@icon"/>
- <xsl:with-param name="id" select="@id"/>
- <xsl:with-param name="lang" select="@xml:lang"/>
- </xsl:call-template>
- </xsl:template>
- <xsl:template match="sch:phase/sch:p" /><!-- We don't use these -->
- <xsl:template match="sch:p | p" />
-
- <!-- PATTERN -->
- <xsl:template match="sch:pattern | pattern" mode="do-all-patterns">
- <xsl:if test="($phase = '#ALL')
- or (../sch:phase[@id= ($phase)]/sch:active[@pattern= current()/@id])
- or (../phase[@id= ($phase)]/active[@id= current()/@id])">
- <xsl:call-template name="process-pattern">
- <xsl:with-param name="name" select="@name"/>
- <xsl:with-param name="id" select="@id"/>
- <xsl:with-param name="see" select="@see"/>
- <xsl:with-param name="fpi" select="@fpi"/>
- <xsl:with-param name="icon" select="@icon"/>
- </xsl:call-template>
- <axsl:apply-templates select="/" mode="M{count(preceding-sibling::*)}"/>
- </xsl:if>
- </xsl:template>
-
- <xsl:template match="sch:pattern | pattern">
- <xsl:if test="($phase = '#ALL')
- or (../sch:phase[@id= ($phase)]/sch:active[@pattern= current()/@id])
- or (../phase[@id= ($phase)]/active[@id= current()/@id])">
- <xsl:apply-templates/>
- <axsl:template match="text()" priority="-1" mode="M{count(preceding-sibling::*)}">
- <!-- strip characters -->
- </axsl:template>
- </xsl:if>
- </xsl:template>
-
- <!-- PHASE -->
- <xsl:template match="sch:phase | phase" >
- <xsl:if test="not(@id)">
- <xsl:message>Markup Error: no id attribute in <phase></xsl:message>
- </xsl:if>
- </xsl:template>
-
- <!-- RULE -->
- <xsl:template match="sch:rule[not(@abstract='true')] | rule[not(@abstract='true')]">
- <xsl:if test="not(@context)">
- <xsl:message>Markup Error: no context attribute in <rule></xsl:message>
- </xsl:if>
- <axsl:template match="{@context}" priority="{4000 - count(preceding-sibling::*)}" mode="M{count(../preceding-sibling::*)}">
- <xsl:call-template name="process-rule">
- <xsl:with-param name="id" select="@id"/>
- <xsl:with-param name="context" select="@context"/>
- <xsl:with-param name="role" select="@role"/>
- </xsl:call-template>
- <xsl:apply-templates/>
- <axsl:apply-templates mode="M{count(../preceding-sibling::*)}"/>
- </axsl:template>
- </xsl:template>
-
-
- <!-- ABSTRACT RULE -->
- <xsl:template match="sch:rule[@abstract='true'] | rule[@abstract='true']" >
- <xsl:if test=" not(@id)">
- <xsl:message>Markup Error: no id attribute on abstract <rule></xsl:message>
- </xsl:if>
- <xsl:if test="@context">
- <xsl:message>Markup Error: (2) context attribute on abstract <rule></xsl:message>
- </xsl:if>
- </xsl:template>
-
- <xsl:template match="sch:rule[@abstract='true'] | rule[@abstract='true']"
- mode="extends" >
- <xsl:if test="@context">
- <xsl:message>Markup Error: context attribute on abstract <rule></xsl:message>
- </xsl:if>
- <xsl:apply-templates/>
- </xsl:template>
-
- <!-- SPAN -->
- <xsl:template match="sch:span | span" mode="text">
- <xsl:call-template name="process-span"
- ><xsl:with-param name="class" select="@class"/>
- </xsl:call-template>
- </xsl:template>
-
- <!-- TITLE -->
- <!-- swallow -->
- <xsl:template match="sch:title | title" />
-
- <!-- VALUE-OF -->
- <xsl:template match="sch:value-of | value-of" mode="text" >
- <xsl:if test="not(@select)">
- <xsl:message>Markup Error: no select attribute in <value-of></xsl:message>
- </xsl:if>
- <xsl:call-template name="IamEmpty" />
- <axsl:text xml:space="preserve"> </axsl:text>
- <xsl:choose>
- <xsl:when test="@select"
- ><xsl:call-template name="process-value-of">
- <xsl:with-param name="select" select="@select"/>
- <!-- will saxon have problem with this too?? -->
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise >
- <xsl:call-template name="process-value-of"
- ><xsl:with-param name="select" select="'.'"/>
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
- <axsl:text xml:space="preserve"> </axsl:text>
- </xsl:template>
-
- <!-- ============================================================== -->
- <!-- Text -->
- <xsl:template match="text()" priority="-1" mode="do-keys">
- <!-- strip characters -->
- </xsl:template>
- <xsl:template match="text()" priority="-1" mode="do-all-patterns">
- <!-- strip characters -->
- </xsl:template>
- <xsl:template match="text()" priority="-1" mode="do-schema-p">
- <!-- strip characters -->
- </xsl:template>
- <xsl:template match="text()" priority="-1" mode="do-pattern-p">
- <!-- strip characters -->
- </xsl:template>
- <xsl:template match="text()" priority="-1">
- <!-- strip characters -->
- </xsl:template>
- <xsl:template match="text()" mode="text">
- <xsl:value-of select="normalize-space(.)"/>
- </xsl:template>
-
- <xsl:template match="text()" mode="inline-text">
- <xsl:value-of select="."/>
- </xsl:template>
-
- <!-- ============================================================== -->
- <!-- utility templates -->
- <xsl:template name="IamEmpty">
- <xsl:if test="count( * )">
- <xsl:message>
- <xsl:text>Warning: </xsl:text>
- <xsl:value-of select="name(.)"/>
- <xsl:text> must not contain any child elements</xsl:text>
- </xsl:message>
- </xsl:if>
- </xsl:template>
-
- <xsl:template name="diagnosticsSplit">
- <!-- Process at the current point the first of the <diagnostic> elements
- referred to parameter str, and then recurse -->
- <xsl:param name="str"/>
- <xsl:variable name="start">
- <xsl:choose>
- <xsl:when test="contains($str,' ')">
- <xsl:value-of select="substring-before($str,' ')"/>
- </xsl:when>
- <xsl:otherwise><xsl:value-of select="$str"/></xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
-
- <xsl:variable name="end">
- <xsl:if test="contains($str,' ')">
- <xsl:value-of select="substring-after($str,' ')"/>
- </xsl:if>
- </xsl:variable>
-
- <xsl:if test="not(string-length(normalize-space($start)) = 0)
- and not(//sch:diagnostic[@id = ($start)]) and not(//diagnostic[@id = ($start)])">
- <xsl:message>Reference error: A diagnostic "<xsl:value-of select="string($start)"/>" has been referenced but is not declared</xsl:message>
- </xsl:if>
-
- <xsl:if test="string-length(normalize-space($start)) > 0">
- <xsl:apply-templates
- select="//sch:diagnostic[@id = ($start) ] | //diagnostic[@id= ($start) ]"/>
- </xsl:if>
-
- <xsl:if test="not($end='')">
- <xsl:call-template name="diagnosticsSplit">
- <xsl:with-param name="str" select="$end"/>
- </xsl:call-template>
- </xsl:if>
- </xsl:template>
-
-
- <!-- ============================================================== -->
-
- <xsl:template match="*">
- <xsl:message>
- <xsl:text>Warning: unrecognized element </xsl:text>
- <xsl:value-of select="name(.)"/>
- </xsl:message>
- </xsl:template>
- <xsl:template match="*" mode="text">
- <xsl:message>
- <xsl:text>Warning: unrecognized element </xsl:text>
- <xsl:value-of select="name(.)"/>
- </xsl:message>
- </xsl:template>
- <!-- ============================================================== -->
- <!-- Default named templates -->
- <!-- These are the actions that are performed unless overridden -->
- <xsl:template name="process-prolog"/>
- <!-- no params -->
- <xsl:template name="process-root">
- <xsl:param name="contents"/>
- <!-- unused params: fpi, title, id, icon, lang, version, schemaVersion -->
- <xsl:copy-of select="$contents"/>
- </xsl:template>
- <xsl:template name="process-assert">
- <xsl:param name="role"/>
- <xsl:param name="test"/>
- <!-- unused parameters: id, icon, diagnostics, subject -->
- <xsl:call-template name="process-message">
- <xsl:with-param name="pattern" select="$test"/>
- <xsl:with-param name="role" select="$role"/>
- </xsl:call-template>
- </xsl:template>
- <xsl:template name="process-report">
- <xsl:param name="role"/>
- <xsl:param name="test"/>
- <!-- unused parameters: id, icon, diagnostics, subject -->
- <xsl:call-template name="process-message">
- <xsl:with-param name="pattern" select="$test"/>
- <xsl:with-param name="role" select="$role"/>
- </xsl:call-template>
- </xsl:template>
- <xsl:template name="process-diagnostic">
- <!-- params: id -->
- <xsl:apply-templates mode="text"/>
- </xsl:template>
- <xsl:template name="process-dir"
- ><xsl:apply-templates mode="inline-text"/></xsl:template>
- <xsl:template name="process-emph"
- ><xsl:apply-templates mode="inline-text"/></xsl:template>
- <xsl:template name="process-name">
- <xsl:param name="name"
- /><axsl:value-of select="{$name}"/></xsl:template>
- <xsl:template name="process-ns" />
- <!-- unused params: prefix, uri -->
- <!-- note that this is independent of the use of sch:ns by sch:schema -->
- <xsl:template name="process-p"/>
- <!-- unused params: class, id, icon, lang -->
- <xsl:template name="process-pattern"/>
- <!-- unused params: name, id, see, fpi, icon -->
- <xsl:template name="process-rule"/>
- <!-- unused params: id, context, role -->
- <xsl:template name="process-span"
- ><xsl:apply-templates mode="inline-test"/></xsl:template>
- <xsl:template name="process-value-of">
- <xsl:param name="select"
- /><axsl:value-of select="{$select}"/></xsl:template>
- <!-- default output action: the simplest customization is to just override this -->
- <xsl:template name="process-message">
- <!-- params: pattern, role -->
- <xsl:apply-templates mode="text"/>
- </xsl:template>
- </xsl:stylesheet>
-
-