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.