Bug #3109
closedXSLT functions are exposed to xsl:evaluate but shouldn't be exposed
0%
Description
Both the latest internal draft of the XSLT 3.0 spec in https://www.w3.org/XML/Group/qtspecs/specifications/xslt-30/html/#dynamic-xpath as well as the official https://www.w3.org/TR/xslt-30/#element-evaluate say about the function signatures in the context of dynamic XPath evaluation using xsl:evaluate: "Note that this set deliberately excludes XSLT-defined functions in the standard function namespace".
However when I run tests with Saxon 9.7 EE I find that xsl:evaluate
exposes XSLT only functions like document@, @copy-of
or key
to @xsl:evaluate@.
Here is a test case that checks whether function-lookup
returns a function for certain XSLT functions:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
expand-text="true"
exclude-result-prefixes="array fn map math xs">
<xsl:param name="function-list" as="xs:string*" select="'document', 'key', 'current', 'copy-of', 'snapshot'"/>
<xsl:param name="arities" as="xs:integer*" select="1, 2, 0, 1, 1"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template name="main" match="/">
<results>
<xsl:for-each select="$function-list">
<xsl:variable name="pos" select="position()"/>
<xsl:variable name="xpath" as="xs:string">
exists(function-lookup(xs:QName('fn:{.}'), {$arities[$pos]}))
</xsl:variable>
<result function="{.}">
<xsl:evaluate xpath="$xpath"></xsl:evaluate>
</result>
</xsl:for-each>
</results>
</xsl:template>
</xsl:stylesheet>
When run with Saxon 9.7 EE (Saxon-EE 9.7.0.14J) from the command line with -it:main
it outputs
<?xml version="1.0" encoding="UTF-8"?>
<results>
<result function="document">true</result>
<result function="key">true</result>
<result function="current">true</result>
<result function="copy-of">true</result>
<result function="snapshot">true</result>
</results>
Exselt outputs
<?xml version="1.0" encoding="UTF-8"?>
<results>
<result function="document">false</result>
<result function="key">false</result>
<result function="current">false</result>
<result function="copy-of">false</result>
<result function="snapshot">false</result>
</results>
Another test case I wrote is
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
exclude-result-prefixes="array fn map math xs">
<xsl:output method="xml"/>
<xsl:template name="main" match="/">
<xsl:sequence
select="
let $f := function-lookup(xs:QName('fn:document'), 1)
return
if (exists($f)) then
$f('')
else
'not found'"/>
<xsl:variable name="path" as="xs:string">
let $f := function-lookup(xs:QName('fn:document'), 1)
return
if (exists($f)) then
$f('')
else
'not found'</xsl:variable>
<xsl:evaluate xpath="$path"/>
</xsl:template>
</xsl:stylesheet>
which tests whether document
is not only exposed but also callable, indeed Saxon calls it and returns the stylesheet while Exselt return the not found
for the @xsl:evaluate@.
Updated by Michael Kay almost 8 years ago
The spec of fn:function-lookup says:
If the arguments to fn:function-lookup identify a function that is present in the static context of the function call, the function will always return the same function that a static reference to this function would bind to. If there is no such function in the static context, then the results depend on what is present in the dynamic context, which is ·implementation-defined·.
I seem to recall there was a fair bit of discussion about situations that might lead to the dynamic context containing functions not present in the static context, but I don't recall the details - I think a number of people had different reasons for suggesting this could be useful. For Saxon, certainly, it's useful not to have to impose what would be a completely artificial restriction.
Updated by Michael Kay almost 8 years ago
Further, the XSLT 3.0 spec says of xsl:evaluate, "All other aspects of the dynamic context are the same as the dynamic context for the xsl:evaluate instruction itself", which suggests that the dynamic context must include the fn:document function. Though I'm sure that was never intended.
Updated by Michael Kay almost 8 years ago
The spec has now been clarified (see https://www.w3.org/Bugs/Public/show_bug.cgi?id=30049)
The functions available in the dynamic context of the xsl:evaluate instruction are now aligned with those in the static context (which exclude XSLT-specific function like key()) so you can no longer by-pass the restrictions in what functions are available by finding them dynamically.
If a function is available that shouldn't be, I don't think that's a serious enough bug to justify a patch for 9.7, which we now need to manage for stability rather than for conformance. But I'll try and make sure we get it right for 9.8.
Updated by Michael Kay over 7 years ago
- Status changed from New to Resolved
Saxon 9.8 is conformant with the current spec here (which permits dynamic calls to XSLT-defined functions at implementation discretion, but disallowed static calls).
Saxon 9.7 was published before the spec was clarified and will not be updated because we are now managing it for stability rather than conformance.
A test case evaluate-048 has been added.
Please register to edit this issue