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 a 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 generate bytecode, 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.
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.