Bug #3242
closedStatic type checking error with document-node()
100%
Description
I'm getting a static type checking error when testing on whether a variable of type item() is an element() or document-node() in the same expression. The error can be avoid if I do the tests in separate expressions. I've attached some toy stylesheets that demonstrate the error that have been distilled out of a more complex meta-xsl generated stylesheet.
The error I'm getting is:
Static error at char 1 in xsl:copy-of/@select on line 19 column 62 of bug.instance-of-document-node.xsl:
XPTY0004: Required item type of value of variable $ns-cleaned is node(); supplied value has item type xs:string
The relevant portion from the bug stylesheet is:
@
<xsl:when test="(. instance of element()) or (. instance of document-node())">
<xsl:variable name="ns-cleaned" as="item()*">
<xsl:copy-of select="." copy-namespaces="no"/>
</xsl:variable>
<xsl:sequence select="serialize($ns-cleaned)"/>
</xsl:when>
@
If that "or" is split into two different "whens" as in the workaround stylesheet no error is generated.
This problem only seems to be present in Saxon 9.7, I did not get any errors from 9.5. or 9.6.
Files
Updated by Nick Nunes over 7 years ago
- File workaround.instance-of-document-node.xsl workaround.instance-of-document-node.xsl added
- File bug.instance-of-document-node.xsl bug.instance-of-document-node.xsl added
Yes, my apologies.
Updated by Michael Kay over 7 years ago
It seems there's an incorrect type inference for xsl:copy-of in this situation, it thinks it will return a node but in this case it will return a string.
In more detail, the situation is quite complicated. There are two phases of type-checking; the second phase is done with more context information and can refine the types inferred in the first phase. The first phase incorrectly infers a type of node() for the result of the copy-of instruction, and hence for the variable $ns-cleaned.
In the second phase, if the xsl:when condition is a simple one like (. instance of element()), then it is statically evaluated to false() because it is known by this stage that $atype is a string. Because it is statically false, no further checking of this branch of the conditional takes place, and the previous incorrect inference therefore has no adverse effects.
But the more complex condition (. instance of element() or . instance of document-node()) isn't being statically evaluated to false() (this is a missed optimization opportunity rather than a bug per se), and so further checking of the conditional branch takes place. This time "," is known to be a string, so the result of xsl:copy-of is known to be a string, but the required type of the variable is still thought to be node(), and the conflict is reported in the error message.
Three actions emerge:
(a) fix the type inferencing for xsl:copy-of
(b) precompute the result of "And" and "Or" expressions more aggressively if one or both arguments are statically known.
(c) the type inferencing for xsl:copy-of is unnecessarily complicated because a flag "isSchemaAware" is set to true; if this flag had been false, the type inferencing would simply assume that the result type is the same as the operand type. It seems this flag is always true, even in Saxon-HE. We should try to set it correctly. However, this is probably a risky change, so I won't do this on the 9.7 branch.
Updated by Michael Kay over 7 years ago
- Category set to XSLT conformance
- Status changed from New to Resolved
- Assignee set to Michael Kay
- Priority changed from Low to Normal
- Applies to branch 9.7, trunk added
- Fix Committed on Branch 9.7, trunk added
I fixed (a) on the 9.7 and 9.8 branches, (b) and (c) on the 9.8 branch only.
Updated by O'Neil Delpratt over 7 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in Maintenance Release 9.7.0.19 added
Bug fix applied in the 9.7.0.19 maintenance release.
Please register to edit this issue