Caching compiled stylesheets in memory
The JAXP interface represents a compiled stylesheet as a Templates
object. The
object contains the entire stylesheet; all modules must be compiled as a single unit. JAXP
was designed before packages were added to the XSLT 3.0 language. The
Templates
object is thread-safe, so once created it can be used by many
transformations running separately in parallel. To use the Templates
object to
run a transformation of a particular source document, a Transformer
object is
created. The Transformer
is not thread-safe; its transform()
method must not be called while a transformation is active. The Transformer
can be serially reused, but with Saxon there is no benefit in doing so; better garbage
collection generally occurs if a new Transformer
is created for each
transformation.
The s9api interface (Java) and Saxon.Api (C#) have a similar design: a compiled stylesheet is
represented by an XsltExecutable
object, and the instantiation of a stylesheet performing a single transformation by an
XsltTransformer
or Xslt30Transformer
object. These APIs
also add a third class to the design, namely the XsltCompiler
, which holds compile-time
options such as the base URI of the stylesheet, values of static parameters, and
compile-time options such as whether to defer compilation of template rules until they are used, how to resolve references to
modules (xsl:include
/xsl:import
), what schema definitions to use,
and where to report compile-time errors. The XsltCompiler
is also thread-safe,
though the options in force should not be changed while the compiler is in use, and you may
need to think carefully about how to capture compilation errors if several compilations
are active at the same time. Different
XsltCompiler
instances with different option settings can run concurrently
with each other.
In the SaxonC API (for C++, PHP and Python), a compiled stylesheet is also
represented by an XsltExecutable
object, but the API design differs to Java
and C#. Methods to perform of a single transformation are provided directly on the
XsltExecutable
. A stylesheet is compiled to an XsltExecutable
using methods on the Xslt30Processor
object:
compileFromString()
, compileFromFile()
and
compileFromXdmNode()
in C++; compileFromString()
,
compileFromFile()
and compileFromValue()
in PHP; and
compile_stylesheet()
in Python. The Xslt30Processor
holds
compile-time options such as the output base URI for the stylesheet, values of static
parameters, etc. Compile-time errors are thrown as exceptions in C++, PHP and Python.
XSLT 3.0 packages have been supported since Saxon 9.6. A package may consist of a single module,
or of a number of modules connected using xsl:include
/xsl:import
;
a package is compiled as a unit, and may have references to other packages (via
xsl:use-package)
that are compiled independently. To allow independent
compilation, there is much stronger control over the interfaces that a package exposes to
the outside world, and over the ability of declarations in one package to override another.
For example, if a function is declared to return an integer, then when compiling a call to
that function, the compiler can be confident that any overriding declaration of the
function will still return an integer result.
In the s9api interface (Java), a package is represented by an XsltPackage object. The
XsltCompiler
has a method compilePackage
which returns an
XsltPackage
if successful. The package may be made available for use by
other packages being compiled, in the same or in a different XsltCompiler
, by
the XsltCompiler
's importPackage
method. When an
xsl:use-package
declaration is found while compiling one package, the
compiler searches for a matching package among those that have been imported by the
XsltCompiler
in this way. It is possible to import several different
versions of the same package, and the package-version
attribute of
xsl:use-package
determines which of them is loaded.
In the Saxon.Api interface (C#), a package is represented by an XsltPackage object. The
XsltCompiler
has a method CompilePackage
which returns an
XsltPackage
if successful. The package may be made available for use by
other packages being compiled, in the same or in a different XsltCompiler
, by
the XsltCompiler
's ImportPackage
method. When an
xsl:use-package
declaration is found while compiling one package, the
compiler searches for a matching package among those that have been imported by the
XsltCompiler
in this way. It is possible to import several different
versions of the same package, and the package-version
attribute of
xsl:use-package
determines which of them is loaded.
The XsltPackage
object, once created, is immutable and thread-safe. It is tied
to a Saxon Processor
, but it can be imported by multiple
XsltCompiler
instances. If a common library package is used by many
different stylesheets, it makes sense to define it as a reusable package, since this avoids
the cost of compiling the code repeatedly, and avoids the need to keep multiple copies in
memory.
There is no object corresponding to XsltPackage
in the SaxonC API. But
a package can be exported as an stylesheet export file (SEF) which can then we imported again (see
also Using packages). The
Xslt30Processor
has methods compileFromStringAndSave
,
compileFromFileAndSave
and compileFromXdmNodeAndSave
which exports the
xsl:package
to file store if successful. From 12.4, the package may be made available for use by
other packages being compiled, in the same or in a different Xslt30Processor
, by
the Xslt30Processor
's importPackage
method which takes the SEF file name as argument. When an
xsl:use-package
declaration is found while compiling one package, the
compiler searches for a matching package among those that have been imported by the
Xslt30Processor
in this way. It is possible to import several different
versions of the same package, and the package-version
attribute of
xsl:use-package
determines which of them is loaded.