- From: <bugzilla@jessica.w3.org>
- Date: Tue, 07 Feb 2017 11:52:48 +0000
- To: public-qt-comments@w3.org
https://www.w3.org/Bugs/Public/show_bug.cgi?id=30060 Bug ID: 30060 Summary: [XSLT30]xsl:iterate example "Collecting Multiple Values in a Single Pass" not working Product: XPath / XQuery / XSLT Version: Member-only Editors Drafts Hardware: PC OS: Windows NT Status: NEW Severity: editorial Priority: P2 Component: XSLT 3.0 Assignee: mike@saxonica.com Reporter: martin.honnen@gmx.de QA Contact: public-qt-comments@w3.org Target Milestone: --- Today I tried to run the example "Collecting Multiple Values in a Single Pass" in https://www.w3.org/XML/Group/qtspecs/specifications/xslt-30/html/#iterate, it has the source code <xsl:source-document streamable="yes" href="employees.xml"> <xsl:iterate select="employees/employee"> <xsl:param name="highest" as="element(employee)*"/> <xsl:param name="lowest" as="element(employee)*"/> <xsl:on-completion> <highest-paid-employees> <xsl:value-of select="$highest/name"/> </highest-paid-employees> <lowest-paid-employees> <xsl:value-of select="$lowest/name"/> </lowest-paid-employees> </xsl:on-completion> <xsl:variable name="is-new-highest" as="xs:boolean" select="empty($highest[@salary ge current()/@salary])"/> <xsl:variable name="is-equal-highest" as="xs:boolean" select="exists($highest[@salary eq current()/@salary])"/> <xsl:variable name="is-new-lowest" as="xs:boolean" select="empty($lowest[@salary le current()/@salary])"/> <xsl:variable name="is-equal-lowest" as="xs:boolean" select="exists($lowest[@salary eq current()/@salary])"/> <xsl:variable name="new-highest-set" as="element(employee)*" select="if ($is-new-highest) then . else if ($is-equal-highest) then ($highest, .) else $highest"/> <xsl:variable name="new-lowest-set" as="element(employee)*" select="if ($is-new-lowest) then . else if ($is-equal-lowest) then ($lowest, .) else $lowest"/> <xsl:next-iteration> <xsl:with-param name="highest" select="$new-highest-set"/> <xsl:with-param name="lowest" select="$new-lowest-set"/> </xsl:next-iteration> </xsl:iterate> </xsl:source-document> Reading it I wondered whether it is possible to pass on streamed nodes on as parameters and furthermore whether it would be possible to use "." at several places in the body of the xsl:iterate. So I constructed a sample input document <employees> <employee salary="3000"> <name>Employee a</name> </employee> <employee salary="1000"> <name>Employee b</name> </employee> <employee salary="3000"> <name>Employee c</name> </employee> <employee salary="2000"> <name>Employee d</name> </employee> </employees> and a complete stylesheet with <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math" version="3.0"> <xsl:template name="main"> <xsl:source-document streamable="yes" href="test2017020702.xml"> <xsl:iterate select="employees/employee"> <xsl:param name="highest" as="element(employee)*"/> <xsl:param name="lowest" as="element(employee)*"/> <xsl:on-completion> <highest-paid-employees> <xsl:value-of select="$highest/name"/> </highest-paid-employees> <lowest-paid-employees> <xsl:value-of select="$lowest/name"/> </lowest-paid-employees> </xsl:on-completion> <xsl:variable name="is-new-highest" as="xs:boolean" select="empty($highest[@salary ge current()/@salary])"/> <xsl:variable name="is-equal-highest" as="xs:boolean" select="exists($highest[@salary eq current()/@salary])"/> <xsl:variable name="is-new-lowest" as="xs:boolean" select="empty($lowest[@salary le current()/@salary])"/> <xsl:variable name="is-equal-lowest" as="xs:boolean" select="exists($lowest[@salary eq current()/@salary])"/> <xsl:variable name="new-highest-set" as="element(employee)*" select=" if ($is-new-highest) then . else if ($is-equal-highest) then ($highest, .) else $highest"/> <xsl:variable name="new-lowest-set" as="element(employee)*" select=" if ($is-new-lowest) then . else if ($is-equal-lowest) then ($lowest, .) else $lowest"/> <xsl:next-iteration> <xsl:with-param name="highest" select="$new-highest-set"/> <xsl:with-param name="lowest" select="$new-lowest-set"/> </xsl:next-iteration> </xsl:iterate> </xsl:source-document> </xsl:template> </xsl:stylesheet> however when I try to run that with Saxon-EE 9.7.0.14J it refuses to run it, telling me Static error on line 8 column 67 of test2017020702.xsl: XTSE3430: The body of the xsl:stream instruction is not streamable * Operand if($is-new-highest) then ... else ... of let $new-highest-set := ... selects streamed nodes in a context that allows arbitrary navigation (line 36) I looked into the test cases of the test suite whether it has some input/xslt sample similar to that spec example but I couldn't find anything. So I tried fixing the example based on what I have learned in the past trying to get code working as streamable with Saxon 9.7 and I had to make sure I construct a copy-of() first of the context node in a variable and use that copy then in all occasions: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math" version="3.0"> <xsl:output indent="yes"/> <xsl:template name="main"> <xsl:source-document streamable="yes" href="test2017020702.xml"> <xsl:iterate select="employees/employee"> <xsl:param name="highest" as="element(employee)*"/> <xsl:param name="lowest" as="element(employee)*"/> <xsl:on-completion> <highest-paid-employees> <xsl:value-of select="$highest/name" separator=","/> </highest-paid-employees> <lowest-paid-employees> <xsl:value-of select="$lowest/name" separator=","/> </lowest-paid-employees> </xsl:on-completion> <xsl:variable name="copy" select="copy-of()"/> <xsl:variable name="is-new-highest" as="xs:boolean" select="empty($highest[@salary ge $copy/@salary])"/> <xsl:variable name="is-equal-highest" as="xs:boolean" select="exists($highest[@salary eq $copy/@salary])"/> <xsl:variable name="is-new-lowest" as="xs:boolean" select="empty($lowest[@salary le $copy/@salary])"/> <xsl:variable name="is-equal-lowest" as="xs:boolean" select="exists($lowest[@salary eq $copy/@salary])"/> <xsl:variable name="new-highest-set" as="element(employee)*" select=" if ($is-new-highest) then $copy else if ($is-equal-highest) then ($highest, $copy) else $highest"/> <xsl:variable name="new-lowest-set" as="element(employee)*" select=" if ($is-new-lowest) then $copy else if ($is-equal-lowest) then ($lowest, $copy) else $lowest"/> <xsl:next-iteration> <xsl:with-param name="highest" select="$new-highest-set"/> <xsl:with-param name="lowest" select="$new-lowest-set"/> </xsl:next-iteration> </xsl:iterate> </xsl:source-document> </xsl:template> </xsl:stylesheet> I am not sure that rewrite is the intended implementation of that example but I think the example in the spec should be fixed to work with an implementation like Saxon. -- You are receiving this mail because: You are the QA Contact for the bug.
Received on Tuesday, 7 February 2017 11:52:57 UTC