# XT

## Version 19991105

Copyright (c) 1998, 1999 James Clark

See the file copying.txt for copying permission.

XT is an implementation in Java of XSL Transformations. This version of XT implements the PR-xslt-19991008 version of XSLT. Stylesheets written for earlier versions of the XSLT WD must be converted before they can be used with this version of XT.

This should be considered a beta release.

## Changes from Previous Releases

### Changes in this release

This release of XT adds support for the following:

- an `xt:node-set` extension function that converts a result tree fragment to a node-set
- an `xt:intersection` extension function that returns the intersection of two node-sets
- an `xt:difference` extension function that returns the difference of two node-sets
- a simple, purely DOM API

### Changes in version 19991102

This release of XT adds support for the following:

- `doctype-system`, `doctype-public`, `omit-xml-declaration` and `standalone` attributes on `xsl:output`
- the `preceding` axis
- `xsl:message`
- DOM Level 1

## Usage

To use XT, you need:

- the XT distribution
- an XML parser in Java that supports SAX, such as XP; you should choose a SAX parser that provides `Locator` information, otherwise you won't get any line numbers in error messages

Put `xt.jar` in your `CLASSPATH`, together with whatever is needed for your XML parser, and `sax.jar` if that isn't included with your XML parser. Then use the command:

    java -Dcom.jclark.xsl.sax.parser=your-sax-driver com.jclark.xsl.sax.Driver source stylesheet result name=value...

The `name=value` arguments are optional and specify parameter names and values; they can occur in any order with respect to the other arguments. They will be ignored unless the stylesheet contains a corresponding top-level `xsl:param` element. The value of the parameter will be of type string.

To find a SAX parser, XT first uses the value of the system property `com.jclark.xsl.sax.parser`; if this is not set it uses the value of the system property `org.xml.sax.parser`; if this is not set it uses the class `com.jclark.xml.sax.CommentDriver` (This subclasses the normal XP SAX driver to provide support for comments; it is present only in XP version 0.5 or later; if you have an earlier version of XP use `-Dcom.jclark.xsl.sax.parser=com.jclark.xml.sax.Driver` instead.)

Alternatively under Windows you can use XT packaged as a Win32 executable. This includes XP and SAX. To use this, you will need to have the Microsoft Java VM installed (this is included with IE). Run this with the command:

    xt source stylesheet result name=value...

## Servlet Usage

XT can be used as a servlet. This requires a servlet engine that implements at least version 2.1 of the Java Servlet API. The servlet class is `com.jclark.xsl.sax.XSLServlet`. The servlet requires an init parameter `stylesheet`; the value is the path of the stylesheet in a form suitable to be passed to `ServletContext.getResource`. The translated path gives the XML document to be transformed. An extension of `.xml` will be automatically added to the translated path if necessary. (Some browsers assume that a URL ending in `.xml` is an XML document.) Parameters from the query part of the URL are passed in as parameters to the stylesheet. The stylesheet is cached on initialization.

## XT API

The public interface to XT is `com.jclark.xsl.sax.XSLProcessor` which is implemented by `com.jclark.xsl.sax.XSLProcessorImpl`. This interface is based on SAX.

There is also a simple API based purely on the DOM. This is `com.jclark.xsl.dom.TransformEngine`, which is implemented by `com.jclark.xsl.dom.XSLTransformEngine`. This is significantly less functional and much slower than the SAX API. The file `DOMDemo.java` in the `demo` directory is a demo of this.

It is also possible to mix SAX and the DOM, using the DOM for input and SAX for output; this requires that a class be created that extends `com.jclark.xsl.dom.XMLProcessorImpl` and implements at least the `load` method. The class `com.jclark.xsl.dom.SunXMLProcessorImpl` does this for Sun's DOM implementation (in Project X TR2). An object of the class extending `com.jclark.xsl.dom.XMLProcessorImpl` can be passed to the `setParser(XMLProcessorEx)` method of `com.jclark.xsl.sax.XSLProcessorImpl`. XT will be much slower when using the DOM than when using SAX directly, so you should not use this unless you already have a DOM tree as a result of some other processing. For testing purposes, you can use a class extending `com.jclark.xsl.dom.XMLProcessorImpl` with `com.jclark.xsl.sax.Driver` by specifying the name of the class as the value of the `com.jclark.xsl.sax.parser` system property.

## Limitations

The following features of the XSLT PR are not yet implemented:

- the element extension mechanism (the `extension-element-prefixes` and `xsl:extension-element-prefixes` attributes, the `xsl:fallback` element, and the `element-available` function)
- keys (the `xsl:key` element, and the `key()` function)
- the `xsl:decimal-format` element and the optional third argument on the `format-number()` function
- the `namespace` axis
- forwards-compatible processing
- the `xsl:exclude-result-prefixes` attribute on literal result elements (the `exclude-result-prefixes` attribute on `xsl:stylesheet` is implemented)

There are also some known bugs, notably:

- Many errors that the XSLT specification requires to be reported are silently ignored.
- Comments and processing instructions occurring in the DTD are not excluded from the data model.
- The `node()` node-test does not work in match patterns (it does work in expressions).
- The `document()` function does not pay attention to the HTTP `content-type` header.
- The `xsl:import` element does not conform to the requirement that when `xsl:include` is used to include a stylesheet, any `xsl:import` elements in the included document are moved up in the including document to after any existing `xsl:import` elements in the including document.
- The HTML output method may get confused if you embed namespace-qualfied XML elements with the HTML.

Apart from missing features and bugs, the implementation is in need of improvement in several areas, including:

- The implementation of the `xsl:number` element is slow.
- The `xml` output method ignores the `encoding` and `cdata-section-elements` attributes on `xsl:output`.
- Error reporting is often not as helpful as it might be.
- No error recovery is attempted after an error is reported.
- the `document()` function does not support fragment identifiers in URIs for any media types

Not much effort has yet been devoted to optimizing performance.

## Extension Functions

A call to a function `ns:foo` where `ns` is bound to a namespace of the form `http://www.jclark.com/xt/java/className` is treated as a call of the static method `foo` of the class with fully-qualified name `className`. Hyphens in method names are removed with the character following the hyphen being upper-cased. Overloading based on number of parameters is supported; overloading based on parameter types is not. A non-static method is treated like a static method with the `this` object as an additional first argument. A constructor is treated like a static method named `new`. Extension functions can return objects of arbitrary types which can then be passed as arguments to other extension functions or stored in variables.

For example, the following

    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:date="http://www.jclark.com/xt/java/java.util.Date">

    <xsl:template match="/">
      <html>
        <xsl:if test="function-available('date:to-string') and function-available('date:new')">
          <p><xsl:value-of select="date:to-string(date:new())"/></p>
        </xsl:if>
      </html>
    </xsl:template>

    </xsl:stylesheet>

will print out the current date.

Types are mapped between XSLT and Java as follows:

XSLT type | Java type
--- | ---
string | `java.lang.String`
number | `double`
boolean | `boolean`
node-set | `com.jclark.xsl.om.NodeIterator`
result tree fragment | `com.jclark.xsl.sax.ResultTreeFragment`

On return from an extension function, an object of type `com.jclark.xsl.om.Node` is also allowed and will be treated as a node-set; also any numeric type is allowed and will be converted to a number.

The `demo` directory has an examples.

## Multiple Output Documents

XT supports an extension element `xt:document` for creating output documents in addition to the main output document. The prefix `xt` must be bound to the namespace URI `http://www.jclark.com/xt`.

XT does not yet properly implement the element extension mechanism, and will recognize the namespace URI `http://www.jclark.com/xt` as an extension namespace regardless of whether it has been declared using an `extension-element-prefixes` or `xsl:extension-element-prefixes`. You should not rely on this and should declare the namespace `http://www.jclark.com/xt` as an extension namespace in accordance with the XSLT WD. For example,

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:xt="http://www.jclark.com/xt"
                    extension-element-prefixes="xt">
    ...
    </xsl:stylesheet>

The `xt:document` element has a required `href` attribute, which must be a relative URL. The value of the `href` attribute is interpreted as an attribute value template. The content of the `xt:document` element is a template for the result tree to be stored in the location specified by the `href` attribute. The base URL for resolving the `href` relative URL is the URL of the parent output document: either the URL of the main output document or the URL in which the parent `xt:document` element was stored. Thus, the same relative URL specifed by the `href` attribute can be used in the parent document to reference the document created by the `xt:document` element.

The `xt:document` element can also have all the same attributes as the `xsl:output` element. These attributes are merged with attributes specified on top-level `xsl:output` elements to determine the output method for this document. The attributes on the `xt:document` element take precedence over the attributes specified on top-level `xsl:output` elements.

For example,

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:xt="http://www.jclark.com/xt"
                    extension-element-prefixes="xt">

    <xsl:variable name="file">out</xsl:variable>

    <xsl:template match="/">
      <xt:document method="xml" href="{$file}.xml">
         <xsl:call-template name="out"/>
      </xt:document>
      <xt:document method="html" href="{$file}.html">
         <xsl:call-template name="out"/>
      </xt:document>
      <xt:document method="text" href="{$file}.txt">
         <xsl:call-template name="out"/>
      </xt:document>
    </xsl:template>

    <xsl:template name="out">
      <html>
       <head><title>Title</title></head>
       <body>
       <p>Line 1<br/>Line 2</p>
       </body>
      </html>
    </xsl:template>

    </xsl:stylesheet>

The `demo` directory has a couple more examples.

## Non-XML output

XT supports an additional output method of `xt:nxml` where the prefix `xt` is bound to the namespace URI `http://www.jclark.com/xt`. This produces non-XML output from a result document that conforms to the following DTD:

    <!ELEMENT nxml (escape*, (control|data)*)>
    <!ELEMENT escape (#PCDATA|char)*>
    <!ATTLIST escape char CDATA #REQUIRED>
    <!ELEMENT control (#PCDATA|char|data|control)*>
    <!ELEMENT data (#PCDATA|data|control)*>
    <!ELEMENT char EMPTY>
    <!ATTLIST char number NMTOKEN #REQUIRED>

The `data` element contains data. Within a `data` element control characters get escaped. The `escape` element specifies how a particular control character gets escaped.

The `control` element contains control information. Within a `control` element, all characters are output directly without escaping.

The `char` element allows the output of a character that is not allowed by XML (such as control-L).

For example, the following stylesheet

    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xt:nxml" xmlns:xt="http://www.jclark.com/xt"/>
    <xsl:template match="/">
    <nxml>
    <escape char="\">\\</escape>
    <data>&amp;&lt;&gt;\</data>
    <control>&amp;&lt;&gt;\</control>
    </nxml>
    </xsl:template>
    </xsl:stylesheet>

will output

    &<>\\&<>\

The `encoding` attribute on `xsl:output` applies to the `xt:nxml` output method.

A result method can also have the form `java:class` where `java` is bound to the namespace URI `http://www.jclark.com/xt/java` and `class` is the name of a Java class that implements the `com.jclark.xsl.sax.OutputDocumentHandler` interface (which extends `org.xml.sax.DocumentHandler`). For example,

    <xsl:output method="xtj:com.jclark.xsl.sax.NXMLOutputHandler"
                xmlns:xtj="http://www.jclark.com/xt/java"/>

is equivalent to

    <xsl:output method="xt:nxml" xmlns:xt="http://www.jclark.com/xt"/>

## Built-in Extension Functions

XT provides the following built-in extension functions. The namespace URI for these is `http://www.jclark.com/xt`.

`xt:node-set`
  Converts a result tree fragment to the equivalent node-set. The argument must be a node-set or a result tree fragment; the result will be a node-set. See the `sort-uniq` example in the `demo` directory.
`xt:intersection`
  Returns the intersection of two node-sets.
`xt:difference`
  Returns the difference of two node-sets (the nodes in the first node-set that are not in the second node-set).

## Reporting Bugs

Please report bugs to me. When reporting bugs please be sure to include both a complete stylesheet and complete source document that illustrate the bug. Create a zip file containing all the necessary files, and attach the zip file to your email.