Bug #5042
closedxslt3 fails to identify that function with type declaration as="element()" returns an empty sequence
100%
Description
I have a function with a return type declaration as="element()"
but a body, that, after a code change and the use of xsl:where-populated
, might return the empty sequence.
In this case Saxon Java or Saxon-JS when running a compiled stylesheet from Saxon Java EE give the error "XTTE0780".
However, when I run the stylesheet directly through xslt3
, i.e. use the XX compiler, the error is not noticed and the stylesheet incuding the function call returning an empty sequence is executed.
Example function:
<xsl:function name="mf:wrap-if-populated" as="element()" visibility="public">
<xsl:param name="items" as="item()*"/>
<xsl:param name="wrapper-name" as="xs:QName"/>
<xsl:where-populated>
<xsl:element name="{$wrapper-name}" namespace="{namespace-uri-from-QName($wrapper-name)}">
<xsl:apply-templates select="$items"/>
</xsl:element>
</xsl:where-populated>
</xsl:function>
Full test case
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:function name="mf:wrap-if-populated" as="element()" visibility="public">
<xsl:param name="items" as="item()*"/>
<xsl:param name="wrapper-name" as="xs:QName"/>
<xsl:where-populated>
<xsl:element name="{$wrapper-name}" namespace="{namespace-uri-from-QName($wrapper-name)}">
<xsl:apply-templates select="$items"/>
</xsl:element>
</xsl:where-populated>
</xsl:function>
<xsl:template match="list[@type = 'ordered']">
<xsl:sequence select="mf:wrap-if-populated(item, QName('', 'ol'))"/>
</xsl:template>
<xsl:template match="list">
<xsl:sequence select="mf:wrap-if-populated(item, QName('', 'ul'))"/>
</xsl:template>
<xsl:template match="list/item">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
<xsl:template match="root">
<html>
<head>
<title>Example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="/" name="xsl:initial-template">
<xsl:next-match/>
<xsl:comment xmlns:saxon="http://saxon.sf.net/">Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
</xsl:template>
</xsl:stylesheet>
Sample input:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<list>
<item>a</item>
<item>b</item>
<item>c</item>
</list>
<list type="ordered"></list>
</root>
Output of xslt3
when running the SEF compiled by Saxon Java EE 10.5:
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
<title>Example</title>
</head>
<body>
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>Transformation failure: Error XTTE0780 at sheet2.xsl#13
Required cardinality of result of call to function mf:wrap-if-populated#2 is exactly one; supplied value is empty
Error XTTE0780 at sheet2.xsl#13
Required cardinality of result of call to function mf:wrap-if-populated#2 is exactly one; supplied value is empty
Output when running the XSLT file through xslt3
:
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
<title>Example</title>
</head>
<body>
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
</body>
</html>
<!--Run with Saxon-JS 2.2 Node.js-->
Updated by Michael Kay over 2 years ago
- Status changed from New to In Progress
Looking at the SEF file, the XX compiler hasn't generated a type checking instruction (by contrast, it does so if we change the function return type to as="element(xxx)"
). The probably means that it has wrongly inferred the type of the xsl:where-populated
instruction (so it thinks no type check is necessary).
Updated by Michael Kay over 2 years ago
I think the offending code is probably at conditionals.xsl line 202:
<xsl:template match="ex:condCont | ex:onEmpty | ex:onNonEmpty" mode="process-xpath">
<xsl:variable name="source" as="element()">
<xsl:apply-templates select="*" mode="#current"/>
</xsl:variable>
<xsl:copy>
<xsl:sequence select="@*, $source/@sType, $source"/>
</xsl:copy>
</xsl:template>
This is copying the attribute $source/@sType
, implying that the inferred static type of the condCont
(=wherePopulated
) instruction is the same as the inferred type of its operand.
By contrast SaxonJ has
protected int computeCardinality() {
return super.computeCardinality() | StaticProperty.ALLOWS_ZERO;
}
Updated by Michael Kay over 2 years ago
- Status changed from In Progress to Resolved
- Assignee set to Michael Kay
- Fix Committed on JS Branch Trunk added
Updated by Debbie Lockett over 2 years ago
- Fix Committed on JS Branch 2 added
- Fix Committed on JS Branch deleted (
Trunk)
Updated by Debbie Lockett over 2 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in JS Release set to SaxonJS 2.4
Bug fix applied in the SaxonJS 2.4 maintenance release.
Please register to edit this issue
Also available in: Atom PDF Tracking page