Schmit: SCHema In Transformation
By Kohsuke Kawaguchi

Table of Contents

  1. Introduction
  2. Getting Started
  3. XML Schema
  4. Reference
  5. Contact
  6. Former-project-proposal

Introduction

Schmit is an XSLT extension that allows you to access schema annotation information from within the stylesheet. This functionality can be used to write more generic stylesheet that isn't tied to any particular XML vocabulary. The current release works for Apache Xalan.

Getting Started

To use Schmit, you first prepare a schema that validates the input of the transformation. For example, if you are converting a DocBook to XHTML, you need a schema for DocBook. Schmit supports
RELAX NG and W3C XML Schema.

Assume you have the following schema:


<?xml version="1.0"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
         xmlns:a="test">
  <start>
    <element name="root">
      <element name="child" a:note="1st">
        <empty/>
      </element>
      <element name="child" a:note="2nd">
        <empty/>
      </element>
    </element>
  </start>
</grammar>
</grammar>

Note that this schema contains attributes from namespace "test". Schmit treats all the non-RELAX NG namespaces in a grammar as "annotations". For XML Schema, elements and attributes inside <xs:annotation> are considered as "annotations".

Inside your stylesheet, you first declare Schmit as an XSLT extension:


<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
	xmlns:sc="xalan://com.sun.msv.schmit.XalanExtension"
	extension-element-prefixes="sc">

As usual, you can use any prefix instead of "sc". But in this document, we assume that the prefix "sc" is used for the extension declaration.

Next, you need to tell the processor to apply the above schema to the input. This will be done by using the sc:useSchema extension element. This can be done at the very beginning of the stylesheet:


<xsl:template match="/">
  <sc:useSchema href="myschema.rng" />
  ...
</xsl:template>

The href attribute points to the location of the schema. When this instruction is executed, the schema is loaded.

Once you load a schema, you can use another extension function sc:annotation to obtain the annotation.


<xsl:template match="/">
  <result>
    <sc:useSchema href="myschema.rng" />
    <xsl:for-each select="root/child">
      <note>
        <xsl:value-of select="sc:annotation(.)/@a:note" />
      </note>
    </xsl:for-each>
  </result>
</xsl:template>

The sc:annotation function takes a node set, and returns a node set that contains all the annotation elemetns/attributes attached to it. In the above example, we are retriving the value of the a:note attribute attached to each child element.

If an input looks like:


<?xml version="1.0"?>
<root>
  <child/>
  <child/>
</root>

Then the result will look like:


<?xml version="1.0"?>
<result>
	<note>1st</note>
	<note>2nd</note>
</result>

The use of sc:annotation is not limited to xsl:value-of; it can be used anywhere where you can write XPath functions. For example, you can write a template matching rule like this:


<xsl:template match="*[sc:annotation(.)/@a:visible]">

which will match any element whose definition have a:visible attribute, or you can write:


<xsl:copy-of select="sc:annotation(.)/a:htmldoc/*" />

which copies HTML documentation of the current element (assuming that you've written one inside schema) into the current location.

XML Schema

When you choose W3C XML Schemas as your schema language, you need to use the sc:annotation like this:


<xsl:copy-of select="sc:annotation(.)/xs:appinfo/foo:myAnnotation" />

In other words, you can assume that this method returns xs:annotation element itself --- therefore you need to be prepared to see elements like xs:appinfo or xs:documentation before you get to your own annotation.

Reference

Schmit has one extension element and one extension function. This section defines the syntax of those extensions.

useSchema extension element


<sc:useSchema href="[attribute value template]" />

Loads a schema from the specified location and annotate the current input document (the document that includes the context node) with it.

The href attribute takes an attribute value template, meaning that you can write things like this:


<sc:useSchema href="foo.rng" />
<sc:useSchema href="${myVariable}" />

annotation extension function


sc:annotation()
sc:annotation([node-set])

Looks up the annotation attached to the specified nodes, and returns them as a node set. sc:annotation() is equivalent of sc:annotation(.).

Contact

If you have any comment or suggestion to this technology, please feel free to drop a note to Kohsuke Kawaguchi.

Former Project Proposal

The former project proposal can be found here.