[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

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


Subject: Re: [xsl] Question on streaming accumulator solely selecting attribute in select expression of accumulator-rule
From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 2 Jan 2016 13:12:06 -0000

I think the problem is that the analysis of the dynamic function call
$value(@type) isn't smart enough. I haven't yet established whether this a
problem with the streamability rules in the spec or a problem with the Saxon
implementation. But if you replace this with map:get($value, @type) then it
works.

Michael Kay
Saxonica


> On 2 Jan 2016, at 11:58, Martin Honnen martin.honnen@xxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
>
> 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
Keywords