Inconsistency between normal accumulator and streaming accumulator capturing nodes
Added by Martin Honnen about 6 years ago
I was trying to use http://saxonica.com/html/documentation/extensions/attributes/capture.html and I have found an inconsistency between a normal accumulator "capturing" nodes
<xsl:accumulator name="items" as="element(item)*" initial-value="()">
<xsl:accumulator-rule phase="end" match="item" select="$value, ."/>
</xsl:accumulator>
where the use of
<xsl:template match="item">
<xsl:next-match/>
<xsl:message>item: {string(@id)}, count(accumulator-after("items")): {count(accumulator-after('items'))}, accumulator-after("items")!@id!string(): {accumulator-after("items")!@id!string()}</xsl:message>
</xsl:template>
indicates that accumulator-after("items")
includes the currently matched item
(e.g. output is
item: i2, count(accumulator-after("items")): 2, accumulator-after("items")!@id!string(): i1 i2
) and a streaming, capturing accumulator
<xsl:accumulator name="items" as="element(item)*" initial-value="()" streamable="yes">
<xsl:accumulator-rule phase="end" match="item" select="$value, ." saxon:capture="yes"/>
</xsl:accumulator>
where the accumulator-after("items")
doesn't seem to include the currently matched item
(e.g. output is alike
item: i2, count(accumulator-after("items")): 1, accumulator-after("items")!@id!string(): i1
), it only includes items preceding the currently matched one.
Tested with Saxon-EE 9.9.0.1J
.
Is that difference intentional?
The other oddity is that even without the saxon:capture
the code runs with streaming (I would have thought that the select="$value, ."
is not motionless)
Processing file:/C:/SomePath/input-3-items.xml
Streaming file:/C:/SomePath/input-3-items.xml
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
item: i1, count(accumulator-after("items")): 0, accumulator-after("items")!@id!string():
item: i2, count(accumulator-after("items")): 1, accumulator-after("items")!@id!string(): i1
item: i3, count(accumulator-after("items")): 2, accumulator-after("items")!@id!string(): i1 i2
<?xml version="1.0" encoding="UTF-8"?><items>
<item id="i1">value 1</item>
<item id="i2">value 2</item>
<item id="i3">value 3</item>
</items>
So I am confused, why can the streaming code capture a complete element node without using saxon:capture
and why is there the difference between a streaming and not streaming as to whether the currently matched node is included in the accumulator-after result?
Replies (2)
RE: Inconsistency between normal accumulator and streaming accumulator capturing nodes - Added by Michael Kay about 6 years ago
First question: why can the streaming code capture a complete element node?
(revised answer)
The specification states that the expression used to evaluate the rule must be grounded and motionless. Saxon is checking only for motionless.
The effect of using an expression that is striding and motionless (as in this test case) is that Saxon retains a reference to the streamed node in the value of the accumulator. This causes no trouble if the node is only accessed in inspection mode (e.g. counting items, or getting the node name), but it will crash if downward navigation from the node is attempted.
I'll raise a bug on this (and create a test case)
RE: Inconsistency between normal accumulator and streaming accumulator capturing nodes - Added by Michael Kay about 6 years ago
Regarding the other question, this is addressed in bug #3941, and it appears to be not related specifically to saxon:capture, but rather to be a general problem with the post-descent value of the accumulator not being available early enough during streamed processing. A search of the test cases found that the only test case that attempted to access the post-descent value of an accumulator during end-element processing was in fact (due to an oversight) not using streaming.
Please register to reply