All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.s9api.XsltCompiler Maven / Gradle / Ivy

There is a newer version: 12.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2018-2022 Saxonica Limited
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.s9api;

import net.sf.saxon.Configuration;
import net.sf.saxon.PreparedStylesheet;
import net.sf.saxon.expr.parser.OptimizerOptions;
import net.sf.saxon.lib.ErrorReporter;
import net.sf.saxon.lib.ResourceResolver;
import net.sf.saxon.lib.ResourceResolverWrappingURIResolver;
import net.sf.saxon.lib.StringCollator;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.om.NodeSource;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.style.*;
import net.sf.saxon.trace.XSLTTraceCodeInjector;
import net.sf.saxon.trans.CompilerInfo;
import net.sf.saxon.trans.UncheckedXPathException;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.trans.XmlProcessingAbort;
import net.sf.saxon.trans.packages.IPackageLoader;
import net.sf.saxon.trans.packages.PackageDetails;
import net.sf.saxon.trans.packages.PackageLibrary;
import net.sf.saxon.trans.packages.VersionedPackageName;
import net.sf.saxon.transpile.CSharpModifiers;
import net.sf.saxon.transpile.CSharpReplaceBody;
import net.sf.saxon.tree.linked.DocumentImpl;
import net.sf.saxon.tree.linked.ElementImpl;

import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * An XsltCompiler object allows XSLT 2.0 and XSLT 3.0 stylesheets to be compiled. The compiler holds information that
 * represents the static context for the compilation.
 * 

To construct an {@code XsltCompiler}, use the factory method {@link Processor#newXsltCompiler} on the Processor object.

*

An {@code XsltCompiler} may be used repeatedly to compile multiple queries. Any changes made to the * {@code XsltCompiler} (that is, to the static context) do not affect queries that have already been compiled. * An XsltCompiler may in principle be used concurrently in multiple threads, but in practice this * is best avoided because all instances will share the same ErrorListener and it may therefore be * difficult to establish which error messages are associated with each compilation.

*

If JIT compilation is enabled (this is the default for Saxon-EE), then static errors in template * rules might be detected not during execution of the compile() method, but rather * when the relevant code is first executed. In this situation the compile() method will * not throw an exception, but the errors will still (eventually) be notified to the ErrorListener * associated with the compiler.

*

To avoid problems with error reporting, it is recommended that: *

    *
  • When code is under development and static errors are therefore likely, a new * {@code XsltCompiler} should be created for each compilation (and JIT should preferably * be disabled, so that all static errors are detected.)
  • *
  • When production code is being loaded, and errors are therefore unlikely, * it is safe to use the same {@code XsltCompiler} for all compilations, and to * enable JIT for maximum performance.
  • *
* * @since 9.0 */ @CSharpModifiers(code = {"internal"}) public class XsltCompiler { private final Processor processor; private final Configuration config; private final CompilerInfo compilerInfo; /** * Protected constructor. The public way to create an XsltCompiler is by using the factory method * {@link Processor#newXsltCompiler} . * * @param processor the Saxon processor */ protected XsltCompiler(Processor processor) { this.processor = processor; this.config = processor.getUnderlyingConfiguration(); compilerInfo = new CompilerInfo(config.getDefaultXsltCompilerInfo()); compilerInfo.setGenerateByteCode(config.isGenerateByteCode(HostLanguage.XSLT)); compilerInfo.setTargetEdition(config.getEditionCode()); compilerInfo.setJustInTimeCompilation(config.isJITEnabled()); } /** * Get the Processor from which this XsltCompiler was constructed * * @return the Processor to which this XsltCompiler belongs * @since 9.3 */ public Processor getProcessor() { return processor; } /** * Set the URIResolver to be used during stylesheet compilation. This interface is * retained for backwards compatibility reasons. The supplied URIResolver * is wrapped in a ResourceResolver. The ResourceResolver * interface is preferred because more information is made available; most obviously, * the absolute URI formed by combining the base URI and relative URI. * * @param resolver the URIResolver to be used during stylesheet compilation. * @deprecated since 11.1. Use {@link #setResourceResolver} */ public void setURIResolver(URIResolver resolver) { compilerInfo.setResourceResolver( new ResourceResolverWrappingURIResolver(resolver)); } /** * Set the ResourceResolver to be used during stylesheet compilation. * The ResourceResolver is used for dereferencing * an absolute URI (after URI resolution) to return a {@link javax.xml.transform.Source} representing the * location where a stylesheet module can be found. *

This ResourceResolver is used to dereference the URIs appearing in xsl:import, * xsl:include, and xsl:import-schema declarations. It is not used * for resolving the URI supplied for the main stylesheet module (as supplied to the * {@link #compile(javax.xml.transform.Source)} or {@link #compilePackage(javax.xml.transform.Source)} methods. * It is not used at run-time for resolving requests to the document() or similar functions. * (Instead, such functions use the run-time ResourceResolver passed to the {@link XsltTransformer} * or {@link Xslt30Transformer}).

* * @param resolver the ResourceResolver to be used during stylesheet compilation. */ public void setResourceResolver(ResourceResolver resolver) { compilerInfo.setResourceResolver(resolver); } /** * Set the value of a stylesheet parameter. Static (compile-time) parameters must be provided using * this method on the XsltCompiler object, prior to stylesheet compilation. Non-static parameters * may also be provided using this method if their values will not vary from one transformation * to another. * * @param name the qualified name identifying the parameter, as declared in a global <xsl:param> * element in the stylesheet * @param value the value of the parameter * @throws SaxonApiUncheckedException if the value is lazily evaluated, and evaluation fails */ public void setParameter(QName name, XdmValue value) { try { compilerInfo.setParameter(name.getStructuredQName(), ((Sequence) value.getUnderlyingValue()).materialize()); } catch (UncheckedXPathException e) { throw new SaxonApiUncheckedException(e); } } /** * Clear the values of all stylesheet parameters previously set using {@link #setParameter(QName, XdmValue)}. * This resets the parameters to their initial ("undeclared") state */ public void clearParameters() { compilerInfo.clearParameters(); } /** * Get the URIResolver to be used during stylesheet compilation. * * @return the URIResolver used during stylesheet compilation. Returns null if no user-supplied * URIResolver has been set. * @deprecated since 11.1 - use a ResourceResolver instead */ public URIResolver getURIResolver() { ResourceResolver rr = compilerInfo.getResourceResolver(); if (rr instanceof ResourceResolverWrappingURIResolver) { return ((ResourceResolverWrappingURIResolver)rr).getWrappedURIResolver(); } else { return null; } } /** * Get the ResourceResolver to be used during stylesheet compilation. * * @return the ResourceResolver used during stylesheet compilation. Returns null if no user-supplied * ResourceResolver has been set. */ public ResourceResolver getResourceResolver() { return compilerInfo.getResourceResolver(); } /** * Set the ErrorListener to be used during this compilation episode * * @param listener The error listener to be used. This is notified of all errors detected during the * compilation. * *

In earlier releases, contrary to the documentation, the supplied * {@code ErrorListener} was also notified of run-time errors, unless a different * {@code ErrorListener} was supplied at run-time. This is no longer the case from * Saxon 10.0

* @deprecated since 10.0. Use {@link #setErrorReporter(ErrorReporter)} */ @Deprecated public void setErrorListener(ErrorListener listener) { compilerInfo.setErrorListener(listener); } /** * Get the ErrorListener being used during this compilation episode * * @return listener The error listener in use. This is notified of all errors detected during the * compilation. Returns null if no user-supplied ErrorListener has been set. * @deprecated since 10.0. Use {@link #getErrorReporter()} */ @Deprecated public ErrorListener getErrorListener() { return compilerInfo.getErrorListener(); } /** * Supply a (typically empty) {@code List} which will be populated with information about any static errors * encountered during the transformation. *

Calling this method overwrites the effect of any previous call on {@link #setErrorListener(ErrorListener)} * as well as previous calls on {@code setErrorList}.

* * @param errorList a List (typically empty) to which information will be appended about * static errors found during the compilation. Each such error is represented by a * {@link XmlProcessingError} object. * @since 9.9. */ public void setErrorList(List errorList) { //noinspection Convert2MethodRef compilerInfo.setErrorReporter(err -> errorList.add(err)); } /** * Supply a callback which will be notified of all static errors and warnings * encountered during a compilation carried out using this {@code XsltCompiler}. *

Calling this method overwrites the effect of any previous call on {@link #setErrorListener(ErrorListener)} * or {@code setErrorList}.

*

Note that if multiple compilations are carried out concurrently in different threads using * the same {@code XsltCompiler}, then the {@link ErrorReporter} must be thread-safe; messages from different * compilations will be interleaved, and there is no obvious way of determining which message originated * from which compilation. In practice, it is only sensible to do this in an environment * where the stylesheets being compiled are known to be error-free.

* * @param reporter a Consumer which will be notified of all Static errors and warnings * encountered during a compilation episode. * @since 10.0 */ public void setErrorReporter(ErrorReporter reporter) { compilerInfo.setErrorReporter(reporter); } /** * Get the recipient of error information previously registered using {@link #setErrorReporter(ErrorReporter)}. * * @return the consumer previously registered explicitly using {@link #setErrorReporter(ErrorReporter)}, * or implicitly using {@link #setErrorListener(ErrorListener)} or {@link #setErrorList(List)}. * If no error reporter has been registered, the result may be null, or may return * a system supplied error reporter. * @since 10.0 */ public ErrorReporter getErrorReporter() { return compilerInfo.getErrorReporter(); } /** * Say that the stylesheet must be compiled to be schema-aware, even if it contains no * xsl:import-schema declarations. Normally a stylesheet is treated as schema-aware * only if it contains one or more xsl:import-schema declarations. If it is not schema-aware, * then all input documents must be untyped, and validation of temporary trees is disallowed * (though validation of the final result tree is permitted). Setting the argument to true * means that schema-aware code will be compiled regardless. * * @param schemaAware If true, the stylesheet will be compiled with schema-awareness * enabled even if it contains no xsl:import-schema declarations. If false, the stylesheet * is treated as schema-aware only if it contains one or more xsl:import-schema declarations. * @since 9.2 */ public void setSchemaAware(boolean schemaAware) { compilerInfo.setSchemaAware(schemaAware); } /** * Ask whether schema-awareness has been requested by means of a call on * {@link #setSchemaAware} * * @return true if schema-awareness has been requested * @since 9.2 */ public boolean isSchemaAware() { return compilerInfo.isSchemaAware(); } /** * Ask whether any package produced by this compiler can be deployed to a different location, with a different base URI * * @return if true then static-base-uri() represents the deployed location of the package, * rather than its compile time location * @since 9.8 */ public boolean isRelocatable() { return compilerInfo.isRelocatable(); } /** * Say whether any package produced by this compiler can be deployed to a different location, with a different base URI * * @param relocatable if true then static-base-uri() represents the deployed location of the package, * rather than its compile time location * @since 9.8 * */ public void setRelocatable(boolean relocatable) { compilerInfo.setRelocatable(relocatable); } /** * Set the target edition under which the stylesheet will be executed. * * @param edition the Saxon edition for the run-time environment. One of "EE", "PE", "HE", or "JS". * @since 9.7.0.5. Experimental and subject to change. */ public void setTargetEdition(String edition) { if (!("EE".equals(edition) || "PE".equals(edition) || "HE".equals(edition) || "JS".equals(edition))) { throw new IllegalArgumentException("Unknown Saxon edition " + edition); } compilerInfo.setTargetEdition(edition); } /** * Get the target edition under which the stylesheet will be executed. * * @return the Saxon edition for the run-time environment. One of "EE", "PE", "HE", or "JS". * @since 9.7.0.5. Experimental and subject to change. */ public String getTargetEdition() { return compilerInfo.getTargetEdition(); } /** * Declare the default collation * * @param uri the absolute URI of the default collation. Either this URI must have been bound to a collation * using the method {@link Configuration#registerCollation(String, StringCollator)}, or it must be a * collation that is recognized implicitly, such as a UCA collation * @throws IllegalStateException if the collation URI is not a recognized collation * @since 9.5 */ public void declareDefaultCollation(String uri) { StringCollator c; try { c = getProcessor().getUnderlyingConfiguration().getCollation(uri); } catch (XPathException e) { c = null; } if (c == null) { throw new IllegalStateException("Unknown collation " + uri); } compilerInfo.setDefaultCollation(uri); } /** * Get the default collation * * @return the URI of the default collation if one has been set, or the URI of the codepoint collation otherwise * @since 9.7.0.2 */ public String getDefaultCollation() { return compilerInfo.getDefaultCollation(); } /** * Set the XSLT (and XPath) language level to be supported by the processor. Set the value to "4.0" * to enable support for experimental features defined in the XSLT 4.0 proposal (which is likely to change * before it stabilizes). * * @param version the language level to be supported. The values "3.0" and "4.0" are recognized * @throws IllegalArgumentException if the value is not equal to 3.0 or 4.0 * @since 9.3. From 11.0, accepts the values "3.0" and "4.0" */ public void setXsltLanguageVersion(String version) { switch (version) { case "3.0": compilerInfo.setXsltVersion(30); break; case "4.0": compilerInfo.setXsltVersion(40); break; default: throw new IllegalArgumentException("Language version must be 3.0|4.0"); } } /** * Get the XSLT (and XPath) language level supported by the processor. * * @return the language level supported. In Saxon 11 this returns either "3.0" or "4.0". * @since 9.3 */ public String getXsltLanguageVersion() { return compilerInfo.getXsltVersion() == 40 ? "4.0" : "3.0"; } /** * Ask whether assertions (xsl:assert instructions) should be enabled. By default * they are disabled. If assertions are enabled at compile time, then by * default they will also be enabled at run time; but they can be * disabled at run time by specific request * * @return true if assertions are enabled at compile time * @since 9.7 */ public boolean isAssertionsEnabled() { return compilerInfo.isAssertionsEnabled(); } /** * Say whether assertions (xsl:assert instructions) should be enabled. By default * they are disabled. If assertions are enabled at compile time, then by * default they will also be enabled at run time; but they can be * disabled at run time by specific request * * @param enabled true if assertions are enabled at compile time * @since 9.7 */ public void setAssertionsEnabled(boolean enabled) { compilerInfo.setAssertionsEnabled(enabled); } /** * Request fast compilation. Fast compilation will generally be achieved at the expense of run-time performance * and quality of diagnostics. Fast compilation is a good trade-off if (a) the stylesheet is known to be correct, * and (b) once compiled, it is only executed once against a document of modest size. *

Fast compilation may result in static errors going unreported, especially if they occur in code * that is never executed.

*

The current implementation is equivalent to switching off all optimizations other than just-in-time * compilation of template rules. Setting this option, however, indicates an intent rather than a mechanism, * and the implementation details may change in future to reflect the intent.

* * @param fast set to true to request fast compilation; set to false to revert to the optimization options * defined in the Configuration. * @since 9.9 */ public void setFastCompilation(boolean fast) { if (fast) { // The only optimizer option that speeds up compilation is JIT. compilerInfo.setOptimizerOptions(new OptimizerOptions(OptimizerOptions.JIT)); } else { compilerInfo.setOptimizerOptions(getProcessor().getUnderlyingConfiguration().getOptimizerOptions()); } } /** * Ask if fast compilation has been enabled. * * @return true if fast compilation has been enabled (technically, this returns true if the only * optimizer option that has been enabled is JIT compilation of template rules). * @since 9.9 */ public boolean isFastCompilation() { return compilerInfo.getOptimizerOptions().getOptions() == OptimizerOptions.JIT; } /** * Set whether trace hooks are to be included in the compiled code. To use tracing, it is necessary * both to compile the code with trace hooks included, and to supply a TraceListener at run-time * *

Setting tracing to true suppresses those optimizations that cause major reorganisation of the code, * such as function inlining and loop-lifting. These optimizations can be reinstated, but this will tend * to make trace output harder to interpret.

* * @param option true if trace code is to be compiled in, false otherwise * @since 9.3 */ public void setCompileWithTracing(boolean option) { if (option) { compilerInfo.setCodeInjector(new XSLTTraceCodeInjector()); compilerInfo.setOptimizerOptions(compilerInfo.getOptimizerOptions().except( new OptimizerOptions(OptimizerOptions.COMMON_SUBEXPRESSIONS | OptimizerOptions.CONSTANT_FOLDING | OptimizerOptions.INLINE_FUNCTIONS | OptimizerOptions.INLINE_VARIABLES | OptimizerOptions.LOOP_LIFTING | OptimizerOptions.EXTRACT_GLOBALS) ) ); } else { compilerInfo.setCodeInjector(null); } } /** * Ask whether trace hooks are included in the compiled code. * * @return true if trace hooks are included, false if not. * @since 9.3 */ public boolean isCompileWithTracing() { return compilerInfo.isCompileWithTracing(); } /** * Set whether bytecode should be generated for the compiled stylesheet. This option * is available only with Saxon-EE. The default depends on the setting in the configuration * at the time the XsltCompiler is instantiated, and by default is true for Saxon-EE. * * @param option true if bytecode is to be generated, false otherwise * @since 9.6 */ public void setGenerateByteCode(boolean option) { compilerInfo.setGenerateByteCode(option); } /** * Ask whether bytecode is to be generated in the compiled code. * * @return true if bytecode is to be generated, false if not. * @since 9.6 */ public boolean isGenerateByteCode() { return compilerInfo.isGenerateByteCode(); } /** * Import a compiled XQuery library. This makes pre-compiled XQuery library modules available * to the saxon:import-query declaration. * @param queryCompiler An XQueryCompiler that has been used to compile a library of XQuery functions * (by using one of the overloaded methods named compileLibrary). */ public void importXQueryEnvironment(XQueryCompiler queryCompiler) { compilerInfo.setXQueryLibraries(queryCompiler.getUnderlyingStaticContext().getCompiledLibraries()); } /** * Get the stylesheet associated * via the xml-stylesheet processing instruction (see * http://www.w3.org/TR/xml-stylesheet/) with the document * document specified in the source parameter, and that match * the given criteria. If there are several suitable xml-stylesheet * processing instructions, then the returned Source will identify * a synthesized stylesheet module that imports all the referenced * stylesheet module. *

The returned Source will have an absolute URI, created by resolving * any relative URI against the base URI of the supplied source document, * and redirected if necessary by using the URIResolver associated with this * XsltCompiler.

* * @param source The XML source document. Note that if the source document * is available as an instance of {@link XdmNode}, a corresponding Source * can be obtained using the method {@link net.sf.saxon.s9api.XdmNode#asSource()}. * If the source is a StreamSource or SAXSource, it will be read only as far as the * xml-stylesheet processing instruction (but the Source will be consumed and must not * be re-used). * @param media The media attribute to be matched. May be null, in which * case the prefered templates will be used (i.e. alternate = no). * Note that Saxon does not implement the complex CSS3-based syntax for * media queries. By default, the media value is simply ignored. An algorithm for * comparing the requested media with the declared media can be defined using * the method {@link Configuration#setMediaQueryEvaluator(Comparator)}. * @param title The value of the title attribute to match. May be null. * @param charset The value of the charset attribute to match. May be null. * @return A Source object suitable for passing to {@link #compile(javax.xml.transform.Source)}. * @throws SaxonApiException if any problems occur, including the case where no matching * xml-stylesheet processing instruction is found. * @since 9.6 */ @CSharpReplaceBody(code="throw new NotImplementedException();") public Source getAssociatedStylesheet(Source source, String media, String title, String charset) throws SaxonApiException { try { return StylesheetModule.getAssociatedStylesheet(config, compilerInfo.getResourceResolver(), source, media, title, charset); } catch (XPathException e) { throw new SaxonApiException(e); } } /** * Compile a library package. *

The source argument identifies an XML file containing an <xsl:package> element. Any packages * on which this package depends must have been made available to the XsltCompiler * by importing them using {@link #importPackage}.

* * * @param source identifies an XML document holding the the XSLT package to be compiled * @return the XsltPackage that results from the compilation. Note that this package * is not automatically imported to this XsltCompiler; if the package is required * for use in subsequent compilations then it must be explicitly imported. * @throws SaxonApiException if the source cannot be read or if static errors are found during the * compilation. Any such errors will have been notified to the registered ErrorListener * if there is one, or reported on the System.err output stream otherwise. * @since 9.6 * @see #compile(Source) - especially the notes regarding error handling and just-in-time compilation. */ public XsltPackage compilePackage(Source source) throws SaxonApiException { try { Compilation compilation = null; if (source instanceof NodeSource && ((NodeSource)source).getNode() instanceof DocumentImpl) { ElementImpl elem = ((DocumentImpl) ((NodeSource) source).getNode()).getDocumentElement(); if (elem instanceof StyleElement) { compilation = ((StyleElement)elem).getCompilation(); } } if (compilation == null) { compilation = new Compilation(config, new CompilerInfo(compilerInfo)); } compilation.setLibraryPackage(true); XsltPackage pack = new XsltPackage(this, compilation.compilePackage(source).getStylesheetPackage()); int errors = compilation.getErrorCount(); if (errors > 0) { String count = errors == 1 ? "one error" : errors + " errors"; throw new SaxonApiException("Package compilation failed: " + count + " reported"); } return pack; } catch (UncheckedXPathException e) { throw new SaxonApiException(e.getXPathException()); } catch (XPathException | XmlProcessingAbort e) { throw new SaxonApiException(e); } } private PackageLibrary getPackageLibrary() { return compilerInfo.getPackageLibrary(); } /** * Load a compiled package from a file or from a remote location. *

The supplied URI represents the location of a resource which must have been originally * created using {@link XsltPackage#save(java.io.File)}.

*

The result of loading the package is returned as an XsltPackage object. * Note that this package is not automatically imported to this XsltCompiler; * if the package is required for use in subsequent compilations then it must be explicitly * imported.

* * @param location the location from which the package is to be loaded, as a URI * @return the compiled package loaded from the supplied file or remote location * @throws SaxonApiException if no resource can be loaded from the supplied location or if the * resource that is loaded is not a compiled package, or if the compiled package is not * consistent with this XsltCompiler (for example, if it was created using an * incompatible Saxon version). * @since 9.7 */ public XsltPackage loadLibraryPackage(URI location) throws SaxonApiException { return loadLibraryPackage(new StreamSource(location.toString())); } /** * Load a compiled package from a file or from a remote location. *

The supplied URI represents the location of a resource which must have been originally * created using {@link XsltPackage#save(java.io.File)}.

*

The result of loading the package is returned as an XsltPackage object. * Note that this package is not automatically imported to this XsltCompiler; * if the package is required for use in subsequent compilations then it must be explicitly * imported.

* * @param input the source from which the package is to be loaded, as a JAXP Source object * @return the compiled package loaded from the supplied file or remote location * @throws SaxonApiException if no resource can be loaded from the supplied location or if the * resource that is loaded is not a compiled package, or if the compiled package is not * consistent with this XsltCompiler (for example, if it was created using an * incompatible Saxon version). * @since 10.0 */ public XsltPackage loadLibraryPackage(Source input) throws SaxonApiException { try { IPackageLoader loader = processor.getUnderlyingConfiguration().makePackageLoader(); if (loader != null) { StylesheetPackage pack = loader.loadPackage(input); return new XsltPackage(this, pack); } throw new SaxonApiException("Loading library package requires Saxon PE or higher"); } catch (XPathException e) { throw new SaxonApiException(e); } } /** * Load a compiled package from a file or from a remote location, with the intent to use this as a complete * executable stylesheet, not as a library package. *

The supplied URI represents the location of a resource which must have been originally * created using {@link XsltPackage#save(java.io.File)} or some equivalent.

*

The result of loading the package is returned as an XsltExecutable object.

* * @param location the location from which the package is to be loaded, as a URI * @return the compiled package loaded from the supplied file or remote location * @throws SaxonApiException if no resource can be loaded from the supplied location or if the * resource that is loaded is not a compiled package, or if the compiled package is not * consistent with this XsltCompiler (for example, if it was created using an * incompatible Saxon version). * @since 9.7 */ public XsltExecutable loadExecutablePackage(URI location) throws SaxonApiException { return loadLibraryPackage(location).link(); } /** * Load a compiled package from a supplied source, with the intent to use this as a complete * executable stylesheet, not as a library package. *

The supplied source represents the location of a resource which must have been originally * created using {@link XsltPackage#save(java.io.File)} or some equivalent.

*

The result of loading the package is returned as an XsltExecutable object.

* * @param source the source from which the package is to be loaded * @return the compiled package loaded from the supplied file or remote location * @throws SaxonApiException if no resource can be loaded from the supplied location or if the * resource that is loaded is not a compiled package, or if the compiled package is not * consistent with this XsltCompiler (for example, if it was created using an * incompatible Saxon version). * @since 11 */ public XsltExecutable loadExecutablePackage(Source source) throws SaxonApiException { return loadLibraryPackage(source).link(); } /** * Import a library package. Calling this method makes the supplied package available for reference * in the xsl:use-package declarations of subsequent compilations performed using this * XsltCompiler. * * @param thePackage the package to be imported * @throws SaxonApiException if the imported package was created under a different {@link Processor} * @since 9.6 */ public void importPackage(XsltPackage thePackage) throws SaxonApiException { if (thePackage.getProcessor() != processor) { throw new SaxonApiException( "The imported package and the XsltCompiler must belong to the same Processor"); } compilerInfo.getPackageLibrary().addPackage(thePackage.getUnderlyingPreparedPackage()); } /** * Import a library package, changing the package name and/or version. Calling this method * makes the supplied package available for reference in the xsl:use-package * declaration of subsequent compilations performed using the XsltCompiler. The * supplied package name and version are used in place of the name and version used in the XSLT * source code. This provides a level of indirection: for example the same source package can * be compiled twice, with different settings for the static parameter values, and the two * different compiled versions can then be selected from xsl:use-package declarations. distinguishing * them by the new package name and/or version. * * @param thePackage the package to be imported * @param packageName the new package name to be used. If null, the original package name is used * unchanged * @param version the new package version number to be used. If null, the original package version * number is used unchanged * @throws SaxonApiException if the imported package was created under a different {@link Processor}, * or if the supplied version number is invalid * @since 9.8 */ public void importPackage(XsltPackage thePackage, String packageName, String version) throws SaxonApiException { try { if (thePackage.getProcessor() != processor) { throw new SaxonApiException("The imported package and the XsltCompiler must belong to the same Processor"); } PackageDetails details = new PackageDetails(); if (packageName == null) { packageName = thePackage.getName(); } if (version == null) { version = thePackage.getVersion(); } details.nameAndVersion = new VersionedPackageName(packageName, version); details.loadedPackage = thePackage.getUnderlyingPreparedPackage(); compilerInfo.getPackageLibrary().addPackage(details); } catch (XPathException e) { throw new SaxonApiException(e); } } /** * Import a named package, together with all the packages on which it depends, recursively. * The package must be identified in the package library for this {@code XsltCompiler}, which defaults * to the package library defined in the {@link Configuration}, typically set up by loading a configuration * file. * @param packageName the name of the required package. This is the name under which it is registered * in the package library, which is not necessarily the same as the name appearing * in the XSLT source code. * @param versionRange the required version of the package, or range of versions, in the format * of the package-version attribute of xsl:use-package. * @return the best matching package if there is one, or null otherwise. The name of the package * must match; if there are multiple versions, then the version chosen is based first on the * priority attached to this package/version in the library, and if the priorities are equal (or * there are no explicit priorities) then the one with highest version number is taken. * @throws SaxonApiException if an error is detected * @since 9.8 */ public XsltPackage obtainPackage(String packageName, String versionRange) throws SaxonApiException { try { PackageVersionRanges pvr = new PackageVersionRanges(versionRange); PackageDetails details = getPackageLibrary().findPackage(packageName, pvr); if (details != null) { if (details.loadedPackage != null) { return new XsltPackage(this, details.loadedPackage); } else if (details.sourceLocation != null) { XsltPackage pack = compilePackage(details.sourceLocation); details.loadedPackage = pack.getUnderlyingPreparedPackage(); return pack; } } return null; } catch (XPathException e) { throw new SaxonApiException(e); } } /** * Import a package from the configuration file (or more generally, from the packageLibrary * of this XsltCompiler) given an alias used to identify it * @param alias the alias of the package/version in the configuration file * @return the referenced package * @throws SaxonApiException the package does not exist, or if compiling the package fails */ public XsltPackage obtainPackageWithAlias(String alias) throws SaxonApiException { PackageDetails details = getPackageLibrary().findDetailsForAlias(alias); if (details == null) { throw new SaxonApiException("No package with alias " + alias + " found in package library"); } try { List packageNames = new ArrayList<>(); StylesheetPackage pack = getPackageLibrary().obtainLoadedPackage(details, packageNames); return new XsltPackage(this, pack); } catch (XPathException e) { throw new SaxonApiException(e); } } /** * Compile a stylesheet. *

Note: the term "compile" here indicates that the stylesheet is converted into an executable * form. There is no implication that this involves code generation.

*

The source argument identifies the XML document holding the principal stylesheet module. Other * modules will be located relative to this module by resolving relative URIs found in <xsl:include> * and <xsl:import> declarations against the base URI that is defined * as the {@code systemId} property of the supplied {@code Source}.

*

The following kinds of {@link javax.xml.transform.Source} are recognized:

*
    *
  • {@link javax.xml.transform.stream.StreamSource}, allowing the stylesheet to be supplied as a * URI, as a {@link java.io.File}, as an {@link java.io.InputStream}, or as a {@link java.io.Reader}
  • *
  • {@link javax.xml.transform.sax.SAXSource}, allowing the stylesheet to be supplied as a stream * of SAX events from a SAX2-compliant XML parser (or any other source of SAX events)
  • *
  • {@link javax.xml.transform.dom.DOMSource}, allowing the stylesheet to be supplied as a * DOM tree
  • *
  • Document wrappers for XOM, JDOM, DOM4J, or AXIOM trees
  • *
  • A Saxon {@link NodeInfo}, representing the root of a tree in any of the native tree formats supported * by Saxon
  • *
*

The compilation uses a snapshot of the properties of the XsltCompiler at the * time this method is invoked. This is relevant when JIT compilation is enabled (which is the default * under Saxon-EE). Under JIT compilation, templates are compiled when first executed, which will typically be after * the compile() method has returned. Subsequent changes to the properties of the XsltCompiler, * for example, setting a new ErrorListener, have no effect on the delayed compilation of * template rules at execution time.

*

If JIT compilation is enabled (this is the default for Saxon-EE), then static errors in template * rules might be detected not during execution of the compile() method, but rather * when the relevant code is first executed. In this situation the compile() method will * not throw an exception, but the errors will still (eventually) be notified to the ErrorListener * or ErrorList associated with the compiler: more specifically, the ErrorListener * or ErrorList that was associated with the XsltCompiler at the time * compile() was invoked.

* * @param source Source object representing the principal stylesheet module to be compiled. * Must not be null. If the {@code Source} wraps a resource such as a {@link java.io.Reader} * or {@link InputStream} then the resource will be consumed by the method. * @return an {@code XsltExecutable}, which represents the compiled stylesheet. The {@code XsltExecutable} * is immutable and thread-safe; it may be used to run multiple transformations, in series or concurrently. * @throws SaxonApiException if the stylesheet contains static errors or if it cannot be read. Note that * the exception that is thrown will not contain details of the actual errors found in the stylesheet. These * will instead be notified to the registered {@code ErrorListener} or {@code ErrorList}. * The default {@code ErrorListener} displays error messages on the standard error output. * */ public XsltExecutable compile(Source source) throws SaxonApiException { Objects.requireNonNull(source); try { CompilerInfo ci2 = new CompilerInfo(compilerInfo); PreparedStylesheet pss = Compilation.compileSingletonPackage(config, ci2, source); return new XsltExecutable(processor, pss); } catch (UncheckedXPathException e) { throw new SaxonApiException(e.getXPathException()); } catch (XPathException | XmlProcessingAbort e) { throw new SaxonApiException(e); } } /** * Get the underlying {@link CompilerInfo} object, which provides more detailed (but less stable) control * over some compilation options * * @return the underlying {@code CompilerInfo} object, which holds compilation-time options. The methods on * the {@code CompilerInfo} object are not guaranteed stable from release to release. */ public CompilerInfo getUnderlyingCompilerInfo() { return compilerInfo; } /** * Say whether just-in-time compilation of template rules should be used. * @param jit true if just-in-time compilation is to be enabled. With this option enabled, * static analysis of a template rule is deferred until the first time that the * template is matched. This can improve performance when many template * rules are rarely used during the course of a particular transformation; however, * it means that static errors in the stylesheet will not necessarily cause the * {@link #compile(Source)} method to throw an exception (errors in code that is * actually executed will still be notified to the registered ErrorListener * or ErrorList, but this may happen after the {@link #compile(Source)} * method returns). This option is enabled by default in Saxon-EE, and is not available * in Saxon-HE or Saxon-PE. *

Recommendation: disable this option unless you are confident that the * stylesheet you are compiling is error-free.

* @throws UnsupportedOperationException if the argument is set to true and the * configuration is not a licensed Saxon-EE configuration. */ public void setJustInTimeCompilation(boolean jit){ if (jit && !config.isLicensedFeature(Configuration.LicenseFeature.ENTERPRISE_XSLT)){ throw new UnsupportedOperationException("XSLT just-in-time compilation requires a Saxon-EE license"); } compilerInfo.setJustInTimeCompilation(jit); } /** * Ask whether just-in-time compilation of template rules should be used. * * @return true if just-in-time compilation is enabled. With this option enabled, * static analysis of a template rule is deferred until the first time that the * template is matched. This can improve performance when many template * rules are rarely used during the course of a particular transformation; however, * it means that static errors in the stylesheet may go undetected. */ public boolean isJustInTimeCompilation(){ return compilerInfo.isJustInTimeCompilation(); } /** * Get the value of the default namespace for elements and types * @return the value that was set using the method {@link #getDefaultElementNamespace()}, * if any; otherwise, the default value which is an empty string, representing "no namespace". */ public String getDefaultElementNamespace() { return compilerInfo.getDefaultElementNamespace(); } /** * Set the value of the default namespace for elements and types * * @param defaultNS the value to be used as the default namespace for elements and types. * This provides a default for the [xsl:]xpath-default-namespace * attribute in the stylesheet, and it has no effect in any part of the * stylesheet where an explicit value for [xsl:]xpath-default-namespace * is in force. The default value is a zero-length string, representing "no namespace". */ public void setDefaultElementNamespace(String defaultNS) { compilerInfo.setDefaultElementNamespace(defaultNS); } /** * Get the policy for handling of unprefixed element names in path expressions and match patterns. * @return the policy previously set using {@link #setUnprefixedElementMatchingPolicy(UnprefixedElementMatchingPolicy)}, * or its default, which is {@link UnprefixedElementMatchingPolicy#DEFAULT_NAMESPACE}. */ public UnprefixedElementMatchingPolicy getUnprefixedElementMatchingPolicy() { return compilerInfo.getUnprefixedElementMatchingPolicy(); } /** * Set the policy for handling of unprefixed element names in path expressions and match patterns. * By default, such names are expanded using the default namespace for elements and types, which * can be set either using the [xsl:]default-xpath-namespace attribute in the stylesheet, * or programmatically using the method {@link #setDefaultElementNamespace(String)}. The default policy * is {@link UnprefixedElementMatchingPolicy#DEFAULT_NAMESPACE}, * which causes such names to be expanded using the default namespace for elements and types, * which itself defaults to "no namespace", but which can be changed either using the * [xsl:]xpath-default-namespace attribute in the stylesheet, or using the * {@link #setDefaultElementNamespace(String)} method. * *

Note that any setting other than the default causes the stylesheet to behave in a way that * is not conformant with the W3C XSLT 3.0 specifications.

* *

The chosen policy affects:

*
    *
  • Any NCName used as a node-test in an axis step (production ForwardStep * or ReverseStep) in an * XPath expression within the stylesheet, other than an axis step using the attribute or * namespace axis
  • *
  • Any NCName used as a node-test in an axis step (production ForwardStepP * in a pattern within the stylesheet, other than an axis step using the attribute or namespace * axis
  • *
* *

It does not affect names appearing in other contexts (for example, names used in * {@code xsl:strip-space/@elements}), and it does not affect name tests expressed in a form * other than a simple NCName (for example tests of the form Q{}local, or * *:local, or element(local)).

* *

It does not affect XPath expressions evaluated dynamically using xsl:evaluate.

* @param unprefixedElementMatchingPolicy the policy for handling unprefixed elements. */ public void setUnprefixedElementMatchingPolicy(UnprefixedElementMatchingPolicy unprefixedElementMatchingPolicy) { compilerInfo.setUnprefixedElementMatchingPolicy(unprefixedElementMatchingPolicy); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy