Secondary output
The term secondary output refers to values produced using the xsl:result-document instruction. As with the principal output, applications can control both the destination of secondary output, and its format.
When running from the command line, secondary outputs are always serialized,
using the serialization parameters supplied on the xsl:result-document
instruction itself, or in the xsl:output
declaration referenced in its
format
attribute. Serialization parameters supplied on the command line
(for example !indent=yes
) only take effect if the
xsl:result-document
chooses to use the default output format.
By default, secondary outputs are written to a file whose name is established
by resolving the relative URI given in the @href
attribute of xsl:result-document
against the base output URI of the transformation. The
base output URI defaults to the destination of the principal output.
The destination and format of secondary outputs can be influenced using the API:
The JAXP interface was designed for XSLT 1.0 and it has never been updated to handle secondary results. Applications that produce multiple results should therefore use s9api.
-
Various Java interfaces, such as the s9api Xslt30Transformer, have a method
transformer.setResultDocumentHandler(uri -> processor.newSerializer(....));setResultDocumentHandler()
which accepts a JavaFunction<URI, Destination>
, that is, a function that accepts an absolute URI and returns a Destination for the output. For example, you might write:When writing to the secondary result document is complete, Saxon will call the method
Destination.close()
, whose effect depends on the kind of destination. For example, in the case of a Serializer, theclose()
method will close any input stream that Saxon created, but not one that the user created, unless the methodSerializer.setCloseOnCompletion()
is called to request this.You can also call the method
Destination.onClose()
to supply an application-specific action to be performed when the destination is closed. For example, if the URI is amailto:
URI, you might want to attach the serialized result to an email message and send it to a nominated recipient.The older OutputURIResolver mechanism is retained for backwards compatibility. This is limited by the fact that it returns a JAXP
Result
object, which doesn't allow, for example, for returning a "raw" result in which the XSLT results are not wrapped in a document node. -
Various C# interfaces, such as the Saxon.Api Xslt30Transformer, have a property
transformer.ResultDocumentHandler = (href, base) => processor.NewSerializer(....);ResultDocumentHandler
whose value is a delegate that accepts a relative URI and base URI, and returns an IDestination for the output. For example, you might write:You can set the property
Destination.OnClose
to supply an application-specific action to be performed when the destination is closed. For example, if the URI is amailto:
URI, you might want to attach the serialized result to an email message and send it to a nominated recipient. -
In the SaxonC interface, the
XsltExecutable
has a methodsetCaptureResultDocuments()
(set_capture_result_documents()
in Python) which accepts two boolean flags: the first argument is a flag where the value true enables the capturing of secondary result documents in a map (std::map< std::string, XdmValue * >
in C++); the second argument is used to specify that the results should be captured as raw values. After executing the transformation, call thegetResultDocuments()
method (get_result_documents()
in Python) to return the map. The string in the map is the document URI. The default is to send secondary documents to file storage.In PHP the
getResultDocuments()
method returns the map as aXdmMap
.In Python the
get_result_documents()
method returns a Pythondict
(i.e.dict [str, PyXdmValue]
).For example in Python you could do the following:
xslt_excutable.set_capture_result_documents(True) result = xslt_executable.call_template_returning_value(template_name='main', base_output_uri=base_output_uri) result_documents = xslt_executable.get_result_documents()
In the case of an xsl:result-document
instruction
with no href
attribute, the output is sent to the principal output destination,
which must not then be used for anything else. The main reason for this is to allow
serialization options to be set dynamically.
Because xsl:result-document
is an instruction that by its nature has
side-effects, which runs against the grain of XSLT's pure functional language philosophy,
the XSLT specification defines a number of rules constraining what the instruction can do.
Notably (a) you can't write more than one output to the same URI, and (b) you can't write to
a URI that the transformation also reads from. Using a ResultDocumentHandler,
it's very easy to circumvent these rules (for example by using URIs containing an arbitrary
query part, and having the result handler drop the query part), but the consequences
might be unpredictable behaviour
if instructions in the stylesheet are executed in an unexpected order.
Saxon-EE evaluates the xsl:result-document
instruction asynchronously,
unless multi-threading is explicitly disabled. This means that the transformation might be
building several output files in parallel. This will cause problems if the stylesheet
uses extension functions that have side-effects.