[xsl] Why is pattern item/bar/text()[accumulator-before('collect-foo') eq $search] not motionless?

Subject: [xsl] Why is pattern item/bar/text()[accumulator-before('collect-foo') eq $search] not motionless?
From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 3 Jan 2016 12:16:07 -0000
I am using streaming with an accumulator with Saxon 9.7 EE, I have a global variable

<xsl:param name="search" as="xs:string" select="'searched foo'"/>

and an accumulator

<xsl:accumulator name="collect-foo" as="xs:string?" initial-value="()" streamable="yes">
<xsl:accumulator-rule match="item/foo/text()">
<xsl:sequence select="string()"/>
</xsl:accumulator-rule>
</xsl:accumulator>


and I would like to write a pattern using that accumulator value and compare it to the global variable, as in

<xsl:template match="item/bar/text()[accumulator-before('collect-foo') eq $search]">
<xsl:value-of select="$replace"/>
</xsl:template>


but Saxon complains

XTSE3430: Template rule is declared streamable but it does not satisfy the streamability rules.
* The match pattern is not motionless


When I rewrite the template to have the check inside, as in

<xsl:template match="item/bar/text()">
<xsl:value-of select="if (accumulator-before('collect-foo') eq $search) then $replace else ."/>
</xsl:template>


all works fine.

http://www.w3.org/TR/xslt-30/#streamability-fn-accumulator-before with "If the argument to accumulator-before is motionless, the function call is grounded and motionless." sounds as if the call to `accumulator-before` with a string literal as the argument should be fine.

For completeness, the full stylesheet is


<?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:param name="search" as="xs:string" select="'searched foo'"/>
<xsl:param name="replace" as="xs:string" select="'new bar value'"/>

<xsl:mode streamable="yes" on-no-match="shallow-copy"/>
<xsl:global-context-item use-accumulators="collect-foo"/>

<xsl:accumulator name="collect-foo" as="xs:string?" initial-value="()" streamable="yes">
<xsl:accumulator-rule match="item/foo/text()">
<xsl:sequence select="string()"/>
</xsl:accumulator-rule>
</xsl:accumulator>


<xsl:template match="item/bar/text()[accumulator-before('collect-foo') eq $search]">
<xsl:value-of select="$replace"/>
</xsl:template>


</xsl:stylesheet>

a sample input document is

<root>
  <item-list>
    <item>
      <foo>foo 1</foo>
      <bar>bar 1</bar>
    </item>
    <item>
      <foo>searched foo</foo>
      <bar>bar 2</bar>
    </item>
    <item>
      <foo>foo 3</foo>
      <bar>bar 3</bar>
    </item>
    <item>
      <foo>searched foo</foo>
      <bar>bar 4</bar>
    </item>
  </item-list>
</root>

Current Thread