Project

Profile

Help

Bug #4403

Internal error when calling saxon:transform() with stylesheet without primary output

Added by Johan Gheys 4 months ago. Updated about 1 month ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Saxon extensions
Sprint/Milestone:
Start date:
2019-12-04
Due date:
% Done:

100%

Legacy ID:
Applies to branch:
9.9, trunk
Fix Committed on Branch:
9.9, trunk
Fixed in Maintenance Release:

Description

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.

saxon-transform.zip (538 KB) Johan Gheys, 2019-12-04 10:53 saxon-transform.zip

History

#1 Updated by Michael Kay 4 months 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 4 months 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 4 months 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.

#4 Updated by Johan Gheys 4 months ago

Thank you for the clarifying background information. I understand that an additional parameter would not be a good solution. Hopefully we can still count on a well-functioning saxon:transform() function in the future.

#5 Updated by Johan Gheys 4 months 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 about 2 months 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 about 2 months 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 about 2 months 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.

#9 Updated by Johan Gheys about 2 months ago

No problem for the delay. Your support is always appreciated.

#10 Updated by O'Neil Delpratt about 1 month ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 9.9.1.7 added

Patch applied in the 9.9.1.7 maintenance release.

Please register to edit this issue

Also available in: Atom PDF