Bug #2681

System properties: early evaluation

Added by Michael Kay over 4 years ago. Updated about 3 years ago.

XSLT export
Start date:
Due date:
% Done:


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


The argument to the XSLT system-property() function is generally written as a string literal, and Saxon will generally evaluate the function during stylesheet compilation, which allows optimization based on the result (for example, code within the test "if (system-property('xsl:vendor') eq 'Microsoft')..." will be eliminated at compile time).

This strategy is wrong in cases where the stylesheet is exported, and is then executed in a different environment. A stylesheet that is being exported is necessarily compiled under Saxon-EE, where system properties such as xsl:is-schema-aware and xsl:supports-higher-order-functions will take the value "yes"; but the exported stylesheet may be evaluated in an environment where schema-awareness and higher-order-functions are not supported. Evaluation in these cases should therefore be deferred until run-time.

Note that there's nothing much we can do about calls that appear within static expressions, e.g. use-when. These are necessarily evaluated at compile time.


#1 Updated by Michael Kay over 4 years ago

The same problem applies to function-available() and element-available() - we don't really know what will be available until the code is imported into the execution environment.

#2 Updated by Michael Kay over 4 years ago

Note that given the current API, we don't actually know while compiling a stylesheet (package), that it is going to be exported.

#3 Updated by Michael Kay over 4 years ago

On the saxon-dev branch I have made some changes so system-property avoids early evaluation of certain properties, like is-schema-aware. But I'm not sure this is the final solution. I think that when we're compiling a stylesheet for export, we need to be told something about the target execution environment. For example, we want static errors if there are calls on fn:sort() and the target environment is one that doesn't support higher-order functions; similarly, use of system-property() and function-available() within static expressions should give a result that reflects the capabilities of the target environment.

#4 Updated by Michael Kay over 4 years ago

I think the right way forward for this is probably to introduce some kind of setting on the XsltCompiler that says what the target platform is. So if you're under EE, you might be compiling for execution under HE, perhaps in future for execution in a Javascript environment, and we should require the user the opportunity to say that (or perhaps to explicitly say that the target platform is not known / generic). Functions like system-property and function-available will then be evaluated with respect to the target platform if known, or evaluation will be deferred to run-time if the target platform is unknown.

#5 Updated by Michael Kay over 4 years ago

I have implemented this as follows:

(a) an option -target is available on the Transform command line. The value is the target edition for executing the stylesheet, e.g. EE, PE, HE, JS.

(b) the same option is available in s9api as XsltCompiler.setTargetEdition(), or if required as an option on the CompilerInfo.

(c) the option affects the results of system-property(), element-available(), and function-available() when executed at compile time (either in ordinary code, or in a use-when expression). For example, if the target edition is HE, then element-available('xsl:merge') returns false.

(d) the option also affects the contents of the export file. Currently this is only true for target:JS, which is mandatory if the stylesheet is to be executed under Saxon-JS. The option causes some constructs, for example item type tests, to be compiled into fragments of Javascript code which are included in the export file.

There is scope for further use of this option in future, either (a) for early diagnostics if the stylesheet uses constructs that are not available on the target platform, or (b) for generating code in a different way, e.g. fallback code for streaming.

#6 Updated by Michael Kay over 4 years ago

  • Status changed from New to Resolved
  • Applies to branch 9.8 added
  • Fix Committed on Branch 9.7, 9.8 added

Changes committed to the 9.7 and 9.8 branches as described above. Note, the changes on the 9.8 branch are not fully operational because other code needed for target:JS is not yet present on this branch.

#7 Updated by O'Neil Delpratt over 4 years ago

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

Bug fix applied in the Saxon maintenance release.

#8 Updated by O'Neil Delpratt over 4 years ago

  • Sprint/Milestone set to

#9 Updated by O'Neil Delpratt about 3 years ago

  • Applies to branch trunk added
  • Applies to branch deleted (9.8)

#10 Updated by O'Neil Delpratt about 3 years ago

  • Fix Committed on Branch trunk added
  • Fix Committed on Branch deleted (9.8)

Please register to edit this issue

Also available in: Atom PDF