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 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

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:

*)
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.

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

stx:analyze-text (select)
stx:match ({regex}, {flags}?)
stx:no-match

stx:assign (name, select)

stx:attribute ({name}, {namespace}?, select)

stx:buffer (name)

stx:call-procedure (name, group?)

stx:cdata

stx:choose
stx:when (test)
stx:otherwise

stx:comment (select?)

stx:copy (attributes?)

stx:doctype ({name}, {public-id}?, {system-id}?)

stx:end-element ({name}, {namespace}?)

stx:element (name, namespace?)

stx:for-each-item (name, select)

stx:group (name?, pass-through?, strip-space?,
recognize-cdata?)

stx:if (test)
stx:else

stx:include (href)

stx:message (select?, {terminate}?, logger?, level?) –
(prints its content to standard error output or uses the
specified logger with the given level)
The terminate attribute behaves as in XSLT.
The 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.

stx:namespace-alias (sheet-prefix, result-prefix) –
(uses the sheet-prefix in the result)

stx:result-document (href, output-method?, output-encoding?, append?)
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.

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:

The property key is the string
{http://joost.sf.net/extension}support-disable-output-escaping
(which is support-disable-output-escaping in the
Joost extension namespace).

The property value may be either
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.

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.

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.

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):

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.

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).

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.