Joost

Contents

This page contains information about the world's first prototypic Java implementation of the Streaming Transformations for XML (STX) language. It is intended as a reference implementation which demonstrates the functionality of STX. Joost is developed and maintained by Oliver Becker.

The latest version 0.9.1 was created on 2009-09-26 and may be downloaded here.

Joost is released under the Mozilla Public License 1.1. Have a look at the project page for further information. Any questions concerning Joost may be asked on the joost-help mailing list.

Getting started

In order to run Joost you need additionally

As a standalone application

Run Joost with
java net.sf.joost.Main [opts] xml-source stx-sheet [pars] {stx-sheet [pars]}
or simply
java -jar joost.jar [opts] xml-source stx-sheet [pars] {stx-sheet [pars]}

The dash character "-" for the xml-source parameter denotes the standard input. The specification of multiple stx-sheets creates a transformation chain. Global parameters for each STX transformation sheet may be specified by adding command line arguments (pars) of the form parameter=value (on Windows enclosed in additional quotes: "parameter=value") directly after each stx-sheet. value is interpreted as a string, not as an expression.

The list of possible options includes

    -help   print a help message
-version print the version information and exit
-o <filename> write the result to the file <filename>
-m <classname> use a <classname> object for stx:message output (unless the stx:message element has a logger attribute and logging is available, see below)
this class must implement the interface net.sf.joost.emitter.StxEmitter
-nodecl don't include an XML declaration in the result
-noext prevent calls on Java extension functions and script functions
-doe enable disable-output-encoding support, see below
-time print timing information on standard error output
-pdf pass the result to FOP for PDF generation (requires -o), see below

If Commons Logging is available, Joost will log possible runtime errors and messages produced with stx:message/@logger using the appropriate logger objects. You can check whether logging is available or not by running Joost with the -help or -version command line options.

Joost is able to pass its output to FOP for producing PDF output from a stream of XSLFO SAX events. To use this function you have to add fop.jar, batik.jar and avalon.jar (FOP 0.20.5 comes with avalon-framework-cvs-20020806.jar) to your classpath. It is not possible to change FOP's verbosity on the command line at the moment (Joost sets it to warn).

As a library

Joost implements the TrAX interfaces from JAXP 1.1. In order to create a Joost transformer you have to set the Java property javax.xml.transform.TransformerFactory to the value net.sf.joost.trax.TransformerFactoryImpl. Alternatively it is possible to create an TransformerFactoryImpl instance simply by calling its constructor.

Maven projects can use the current joost.jar by adding the following dependency into the pom.xml:

<dependency>
  <groupId>net.sf.joost</groupId>
  <artifactId>joost</artifactId>
  <version>0.9.1</version>
</dependency>

*) Joost [pronounced yohst] meant once Joost is Oli's Original Streaming Transformer and was inspired by the given name a good fiend's little son. The work on this tool started in 2002. It is not related to joost.com which appeared at the end of 2006.

Features

Supported stx elements (and their attributes) in the namespace http://stx.sourceforge.net/2002/ns in alphabetical order

Built-in extension elements
A built-in extension element must be used with a fully-qualified name and the prefix bound to the namespace http://joost.sf.net/extension


Supported STXPath functions in alphabetical order

Built-in extension functions
A built-in extension function must be used with a fully-qualified name and the prefix bound to the namespace http://joost.sf.net/extension

Limitations

Extensions

HTML output

Joost provides an experimental HTML 4.01 output method that can be invoked by specifying joost:html in the output-method attribute. The prefix joost must be bound to Joost's extension namespace http://joost.sf.net/extension. CDATA boundaries will not be printed in HTML. This means for HTML output the disable-output-escaping feature of XSLT may be simulated by using the stx:cdata instruction.


Disable output escaping

Though both STX and Joost don't have a feature for disabling output escaping in the language (unlike XSLT 1.0), it may happen that an XSLT process invoked via a filter (filter-method) produces output using the disable-output-escaping attribute. As specified by the JAXP API, this information is passed via corresponding processing instructions, see PI_DISABLE_OUTPUT_ESCAPING and PI_ENABLE_OUTPUT_ESCAPING in the API documentation of the Result interface. By default, Joost will copy these processing instructions to the output without special treatment, i.e. normal output escaping will be applied.

However, Joost provides two ways to enable the handling of disable-output-escaping related processing instructions in the XML and HTML serializer, i.e. output escaping can be switched off and on accordingly:

Joost cannot distinguish between "technical" processing instructions that stem from an disable-output-escaping attribute in an XSLT transformation and "real" processing instructions that have been produced via an stx:processing-instruction instruction. Therefore it is possible to imitate XSLT's disable-output-escaping via

  <stx:processing-instruction name="javax.xml.transform.disable-output-escaping" />
  ... some text that should be printed without output escaping
  <stx:processing-instruction name="javax.xml.transform.enable-output-escaping" />
      

Scripting

This release of Joost introduces experimental support for scripting languages. It uses the bean scripting framework BSF (see above) as a bridge to concrete scripting engines.

The new element joost:script defines a script. The prefix (in this case joost) must be bound to Joost's extension namespace http://joost.sf.net/extension. The element joost:script must be a child of stx:transform or stx:group and allows only text contents. It has the following attributes:

Example that uses Javascript (Rhino):

<stx:transform xmlns:stx="http://stx.sourceforge.net/2002/ns" 
               xmlns:joost="http://joost.sf.net/extension"
               xmlns:js="urn:javascript"
               version="1.0">

  <joost:script prefix="js" language="javascript">
  <![CDATA[
    function fac(n) {
      var res = 1;
      while (n > 1) {
        res = res * n;
        n--;
      }
      return res;
    }
  ]]>
  </joost:script>

  <stx:template match="/">
    <stx:value-of select="concat('5! = ', js:fac(5))" />
  </stx:template>

</stx:transform>

This "transformation" will output
5! = 120

Note: global script variables will be initialized only once at the moment. This is important for re-used transformation sheets via JAXP Templates objects.


Invoking Java methods

Joost allows the use of extension functions written in Java. An extension function is invoked using the notation prefix:localname(params?). The prefix must be bound to a namespace indicating the Java class to which the function belongs. This namespace must use the URN notation "java:" followed by the full-qualified class name, for example "java:java.util.Random". The referenced class must be found in the current classpath.

The rules for invoking Java extension functions are similar to those used by Saxon or Xalan:

It is recommended not to invoke an extension function having side-effects within the predicates of a match pattern, because the order of these function calls and whether such a function will be used at all is undefined (implementation dependent).
(For example in match="a[ex:foo()]//b[ex:bar()]/c[ex:baz()]")

Conversion rules
Depending on the type of the argument values supplied to the function call, Joost tries to find a method that has parameters of the following types (Java types with a higher conversion preference appear first in the list; if one parameter is of a primitve type and the argument in the function call is a non-empty sequence, only the first item will be considered):

supplied STXPath type required Java type
empty sequence java.util.List, java.lang.Object (or a derived type, i.e. a reference type)
boolean boolean, byte, short, int, long, char, java.lang.String, float, double, java.util.List, java.lang.Object
number double, float, long, int, short, byte, java.lang.String, char, boolean, java.util.List, java.lang.Object
node, string java.lang.String, char, double, float, int, long, short, byte, boolean, java.util.List, java.lang.Object
wrapped Java Object same type, base type, java.lang.Object, java.util.List, java.lang.String

If the target type is java.lang.Object then a conversion according to the following table will be performed. If the target type is java.util.List then a java.util.ArrayList will be constructed containing a list of java.lang.Objects (see table) for each of the items. An empty sequence will be represented as an empty list (not as a list with a null member).

supplied STXPath type target type java.lang.Object
empty sequence null
boolean java.lang.Boolean containing the boolean value
number java.lang.Double containing the number
string java.lang.String
node java.lang.String containing the node value
wrapped Java Object the object itself

The result of a function call will be converted as follows:

return type STXPath type / value
void empty sequence
java.lang.String, char string
boolean boolean
double, float, byte, short, int, long number
anything else, i.e. any reference type, including the value null wrapped Java Object

A wrapped Java Object may be converted to another data type as follows.

required type conversion rule
node not possible
string null will be converted to the empty string, any other object will be converted by invoking its toString() method
boolean null will be converted to false, any other object will be converted via a string conversion and then applying the STXPath function boolean()
number via a string conversion and then applying the STXPath function number()

A wrapped Java Object of type java.lang.Object[] or java.util.List may be converted to a sequence using the Joost extension function sequence. If the supplied parameter is neither an array nor a java.util.List object, this function returns its parameter.


Using external SAX2 filters

Joost implements the usage of external SAX2 filters as described in the STX specification section 5.18. Joost uses the TrAX API to instantiate an XSLT transformer object. The actual XSLT implementation (i.e. the javax.xml.transform.TransformerFactory) to be used may be controlled by setting the property net.sf.joost.trax.TrAXConstants.KEY_XSLT_FACTORY, either as a system property or using TransformerFactory.setAttribute.

Besides the XSLT (http://www.w3.org/1999/XSL/Transform) and STX (http://stx.sourceforge.net/2002/ns) filter methods, Joost provides built-in implementations for the following two additional values of the filter-method attribute:

http://xml.org/sax
Provides a SAX parser. All character data will be fed into the parser, all other events will be ignored. The events generated by the parser constitute the result of this filter.
http://www.ietf.org/rfc/rfc2616.txt#POST
Sends the filter input data per HTTP-POST request to the URL specified in the required target parameter (i.e. <stx:param name="target" ... >). The data of the HTTP response are the result of this filter. The HTTP-POST filter can be used to access web services from STX.

A custom filter implementation must support the javax.xml.transform.sax.TransformerHandler interface. Such a filter can be invoked by implementing a net.sf.joost.TransformerHandlerResolver object which returns the filter object for a requested filter URI. This resolver must be registered using the property net.sf.joost.trax.TrAXConstants.KEY_TH_RESOLVER in the TransformerFactory.setAttribute method, or by invoking setTransformerHandlerResolver on a net.sf.joost.stx.Processor object. There is an example implementation of a filter and an appropriate resolver in the src-samples directory (shipped with the source release only).


OutputURIResolver

Joost provides the interface OutputURIResolver that acts as the counterpart to the JAXP URIResolver. With the help of this interface the user can define what kind of result document should be created for a stx:result-document instruction. If an OutputURIResolver has been defined then Joost invokes its resolve method every time it encounters the instruction stx:result-document. The resolver may return a Result instance or null if the default implementation should be used.

An OutputURIResolver must be registered using the property http://joost.sf.net/attributes/output-uri-resolver in the TransformerFactory.setAttribute method, or by invoking setOutputURIResolver on a net.sf.joost.stx.Processor object.

Examples

The current release contains an example directory with a set of selected STX examples. In addition you may browse Joost's CVS test directory as well as the examples directory from the STX CVS tree.

Resources

Contributors


Get Joost STX processor at SourceForge.net. Fast, secure and Free Open Source software downloads Have fun!

ob / 2009-10-17