Internal error when calling saxon:transform() with stylesheet without primary output
For the moment, we chain multiple transformations together by using the standard transform() function without any problems (see the simplified example 1 in attached zip). In order to reduce memory consumption, we like to replace this function by the saxon:transform() extension function allowing the secondary result output to be serialized directly to filestore. When the styleheet has no primary output, we get the following error (see example 2):
java.lang.RuntimeException: Internal error evaluating function shared:transform-with-saxon at line 162 in module file:/D:/Data/MyProjects/upp/upm-publish-processing/src/test/saxon-transform/xsl/shared-functions.xslt at net.sf.saxon.expr.instruct.UserFunction.call(UserFunction.java:612)...
Putting a dummy element in the primary result tree, solves the problem.
#1 Updated by Michael Kay over 1 year ago
saxon:transform() is pretty ancient and rather reflects the old XSLT 1.0 processing model where there is always one source document. Have you considered using the standard XSLT 3.0 fn:transform() function instead, which is much more flexible?
Of course we should fix any crash.
One word of caution about chaining transformations in this way: because you're invoking one transformation before the other has finished, it can be heavy on memory use (the internal state of the first transformation, including the source document tree, is there for the duration of the second, even if it is never going to be used again). Piping the results of one transformation to another using SAX-like events, e.g. at the s9api level using one XsltTransformer as the destination of another, is potentially more efficient.
#2 Updated by Johan Gheys over 1 year ago
We use the standard XSLT 3.0 fn:transform () function already as much as possible (see example 1), but this function has no parameter to directly write secondary result documents to the filestore. Such documents are accumulated in memory together with the primary output document, after which writing can only begin. This means a considerable memory consumption, especially when it concerns a large number of documents with a large volume. In these specific cases we hope to be able to use the saxon:transform () function so that the secondary output can be serialized directly to the filestore.
#3 Updated by Michael Kay over 1 year ago
Thanks, that's useful feedback.
The specification of result document handling in fn:transform() was a significant challenge because the WG didn't want to define some half-baked side-effect mechanism; delegating the disposal of secondary result documents to a user-written function was a way of basically offloading the problem onto implementors, who presumably already have their own workarounds for handling calls to external functions with side effects.
#5 Updated by Johan Gheys over 1 year ago
Small additional question: when using the standard XSLT 3.0 fn:transform() function with the additional option source-location provided by Saxon, we notice a different behavior compared to the stylesheet-location option. The stylesheet-location option seems to use the standard URIResolver; the source-location option not. The documentation doesn't mention any different behavior. What are the rules to correctly use the source-location option?
#6 Updated by Michael Kay over 1 year ago
Sorry for the delay in progressing this.
There were various paths in which the implementation of the call() method was returning null rather than an EmptySequence, which is incorrect. The documentation also needs to be updated to indicate that saxon:transform() can return an empty sequence if the stylesheet generates no principal output.
#7 Updated by Michael Kay over 1 year ago
- Category set to Saxon extensions
- Status changed from New to In Progress
- Assignee set to Michael Kay
- Applies to branch 9.9, trunk added
- Fix Committed on Branch 9.9, trunk added
Code patched on 9.9 and trunk: TransformFn.call() returns ZeroOrOne rather than NodeInfo, and returns empty sequence instead of null when there is no result. Function signature updated to make the result optional. Documentation updated on trunk only.
#8 Updated by Michael Kay over 1 year ago
- Status changed from In Progress to Resolved
As regards fn:transform and source-location, yes, I think we should be using the URIResolver. A more significant omission is that we don't seem to be setting the base URI for resolving a relative source-location, which means it's going to resolve against the current directory rather than the static base URI. I have fixed both these issues.
Please register to edit this issue