[xsl] Question on streaming accumulator solely selecting attribute in select expression of accumulator-rule

Subject: [xsl] Question on streaming accumulator solely selecting attribute in select expression of accumulator-rule
From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 2 Jan 2016 11:57:48 -0000
I am trying to learn more about streamed processing in XSLT 3.0, currently about streamed accumulators. I have a sample stylesheet which in the `select` attribute of an `xsl:accumulator` rule only selects the `@type` attribute of the matched `product` element, but the expression does so several times:

<?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:map="http://www.w3.org/2005/xpath-functions/map";
  exclude-result-prefixes="xs map"
  version="3.0">

<xsl:mode streamable="yes"/>
<xsl:global-context-item use-accumulators="type-count"/>

<xsl:output method="text"/>

<xsl:accumulator name="type-count" as="map(xs:string, xs:integer)" initial-value="map{}" streamable="yes">
<xsl:accumulator-rule match="product">
<xsl:sequence select="if (map:contains($value, @type))
then map:put($value, string(@type), $value(@type) + 1)
else map:put($value, string(@type), 1)"/>
</xsl:accumulator-rule>
</xsl:accumulator>


<xsl:template match="/">
<xsl:for-each select="*/*">
<xsl:message select="node-name(.)"/>
</xsl:for-each>
<xsl:value-of select="serialize(accumulator-after('type-count'), map{ 'method' : 'adaptive'})"/>
</xsl:template>


</xsl:stylesheet>

Saxon 9.7 EE does not compile the stylesheet, indicating

Error at xsl:accumulator-rule on line 15 column 41 of test2016010206.xsl:
XTSE3430: The xsl:accumulator-rule/@select expression for a streaming accumulator must be
motionless. Operand [@type, ...] of apply(...) selects streamed nodes in a context that
allows arbitrary navigation (line 18)


Why is the access to an attribute with `string(@type)` not motionless?

When I fix the stylesheet with a `let` expression, as in

<?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:map="http://www.w3.org/2005/xpath-functions/map";
  exclude-result-prefixes="xs map"
  version="3.0">

<xsl:mode streamable="yes"/>
<xsl:global-context-item use-accumulators="type-count"/>

<xsl:output method="text"/>

<xsl:accumulator name="type-count" as="map(xs:string, xs:integer)" initial-value="map{}" streamable="yes">
<xsl:accumulator-rule match="product">
<xsl:sequence select="let $type := string(@type)
return if (map:contains($value, $type))
then map:put($value, $type, $value($type) + 1)
else map:put($value, $type, 1)"/>
</xsl:accumulator-rule>
</xsl:accumulator>


<xsl:template match="/">
<xsl:for-each select="*/*">
<xsl:message select="node-name(.)"/>
</xsl:for-each>
<xsl:value-of select="serialize(accumulator-after('type-count'), map{ 'method' : 'adaptive'})"/>
</xsl:template>


</xsl:stylesheet>

the code compiles and runs fine. But I wonder why the multiple use of the same attribute causes an error, I thought during streaming of an element its attributes are always accessible.

Current Thread