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.
In order to run Joost you need additionally
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-sheet
s 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
).
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>
Supported stx elements (and their attributes)
in the namespace http://stx.sourceforge.net/2002/ns
in
alphabetical order
terminate
attribute behaves as in XSLT.
logger
and level
attributes can be
used to produce log messages that will be send to a special Log
object. The name of this object must be specified in the
logger
attribute. The level
attribute
must be one of the values trace
, debug
,
info
, warn
, error
, or
fatal
. Joost will use the Commons Logging
framework if it can be found on the classpath. Otherwise the
attributes logger
and level
will simply
be ignored, i.e. the stx:message
instruction behaves
as if these attributes weren't present. Since Commons Logging is
just a wrapper for other logging facilities, Joost doesn't
provide any mechanisms to configure the underlying logger.
append = "yes"|"no"
is a Joost
specific extension. If set to yes
then the result stream
will be appended to a probably existing file (specified by the
href
attribute). Joost won't produce an XML
declaration in this case, regardless if there is already a file to
append to or not. Note that the resulting document can't be
well-formed XML since it doesn't have a single root element. If
append
is set to no
(the default) it will
replace the old file.
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
java.util.List
object to
a sequence, see Invoking Java methods in
the Extensions section below.
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.
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:
-doe
parameter
setOutputProperty
or
setOutputProperties
in the
Transformer
class.
{http://joost.sf.net/extension}support-disable-output-escaping
(which is support-disable-output-escaping
in the
Joost extension namespace).
yes
or no
.
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" />
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:
prefix
: the namespace prefix that defines the functions
of this script. The namespace must be in scope for the
script
element. The invocation of script functions
requires the use of this prefix.
language
: the language identifier, that is used by BSF
to find the proper scripting engine.
url
(optional): the URL of an external script
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.
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:
A static method can be invoked directly.
The local name of the function must match the name of a public
static method in this class. The names match if they contain
the same characters, excluding hyphens and forcing any character
that follows a hyphen to upper-case. For example the STXPath
function call prefix:to-string()
matches the Java
method toString();
but if you prefer, the function
call can also be written as prefix:toString()
.
The number of the arguments supplied to the function call must match exactly the number of the parameters of the Java method. If there are more than one candidate, Joost attempts to find the one that is the best fit to the types of the supplied arguments (see Conversion rules below). Joost will report an error if no matching method at all can be found, or if several methods may be used but none is preferable to the others.
Example:
<stx:value-of select="math:sqrt($arg)"
xmlns:math="java:java.lang.Math"/>
A constructor is invoked by using a function
named prefix:new
. If there are several constructors,
then again Joost tries to find the one that is the best
fit, according to the types of the supplied arguments. The result
of invoking new()
is an STXPath value of type Java
Object; the only things that can be done with a Java Object are
to assign it to a variable, to pass it to an extension function,
and to convert it to a string
, number
,
or boolean
, using the rules given below.
An instance-level method is invoked by supplying an extra first argument of type Java Object which is the object on which the method is to be invoked. Matching of method names is done as for static methods.
Example:
<stx:value-of select="date:to-string(date:new())"
xmlns:date="java:java.util.Date" />
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.Object
s (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.
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
http://www.ietf.org/rfc/rfc2616.txt#POST
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).
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.
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.
Have fun!
ob / 2009-10-17