Project

Profile

Help

Bug #3932

closed

accumulator-before not working correctly with streaming and xsl:result-document in Saxon 9.9. EE

Added by Martin Honnen about 6 years ago. Updated about 6 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Streaming
Sprint/Milestone:
-
Start date:
2018-10-02
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
9.8, 9.9
Fix Committed on Branch:
9.8, 9.9
Fixed in Maintenance Release:
Platforms:

Description

When trying to use streaming and xsl:result-document with an accumulator to capture the attribute value of a preceding sibling element I get wrong results for the accumulator value returned by accumulator-before() where that call is used inside of an xsl:result-document. This happens with Saxon 9.9.0.1 EE, it seems Saxon 9.8 EE gets it right.

Example XSLT 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" exclude-result-prefixes="#all" expand-text="yes"
	version="3.0">
	
	<xsl:param name="STREAMABLE" static="yes" as="xs:boolean" select="true()"/>
	
	<xsl:mode _streamable="{$STREAMABLE}" use-accumulators="#all"/>
	
	<xsl:accumulator name="last-id" as="xs:string?" initial-value="()" _streamable="{$STREAMABLE}">
		<xsl:accumulator-rule match="item" phase="end" select="string(@id)"/>
	</xsl:accumulator>
	
	<xsl:output method="html" indent="yes" version="5.0"/>
	
	<xsl:template match="/">
		<html>
			<head>
				<title>Testing accumulator with streaming and result-document threading</title>
			</head>
			<body>
				<h1>Testing accumulator with streaming and result-document threading</h1>
				<section>
					<h2>Results</h2>
					<xsl:apply-templates/>
				</section>
			</body>
		</html>
	</xsl:template>
	
	<xsl:template match="items">
		<xsl:result-document href="item-result.html">
			<html>
				<head>
					<title>Items</title>
				</head>
				<body>
					<ul>
						<xsl:apply-templates select="item"/>
					</ul>
				</body>
			</html>
		</xsl:result-document>
	</xsl:template>
	
	<xsl:template match="item">
		<li>Item {@id}, position: {position()}, attribute pos: {@pos},
			accumulator-before('last-id'): {accumulator-before('last-id')}</li>
		
		<xsl:result-document href="item_{@id}.txt" method="text">Item {@id}, accumulator-before('last-id'): {accumulator-before('last-id')}</xsl:result-document>
	</xsl:template>
	
</xsl:stylesheet>

Sample XML is

<?xml version="1.0" encoding="UTF-8"?>
<items>
   <item id="i1" pos="1">
      <data>data 1</data>
   </item>
   <item id="i2" pos="2">
      <data>data 2</data>
   </item>
   <item id="i3" pos="3">
      <data>data 3</data>
   </item>
   <item id="i4" pos="4">
      <data>data 4</data>
   </item>
   <item id="i5" pos="5">
      <data>data 5</data>
   </item>
</items>

Now the item-results.html has the right accumulator values with

     <ul>
        <li>Item i1, position: 1, attribute pos: 1,
                               accumulator-before('last-id'): </li>
        <li>Item i2, position: 2, attribute pos: 2,
                               accumulator-before('last-id'): i1</li>
        <li>Item i3, position: 3, attribute pos: 3,
                               accumulator-before('last-id'): i2</li>
        <li>Item i4, position: 4, attribute pos: 4,
                               accumulator-before('last-id'): i3</li>
        <li>Item i5, position: 5, attribute pos: 5,
                               accumulator-before('last-id'): i4</li>
     </ul>

However those test files created with xsl:result-document href="item_{@id}.txt" method="text" look like this (for instance when outputting them with type item_i*.txt in a PowerShell console):

Item i1, accumulator-before('last-id'):
Item i2, accumulator-before('last-id'): i2
Item i3, accumulator-before('last-id'): i3
Item i4, accumulator-before('last-id'): i4
Item i5, accumulator-before('last-id'): i5

while with Saxon 9.8 EE I get the intented result:

Item i1, accumulator-before('last-id'):
Item i2, accumulator-before('last-id'): i1
Item i3, accumulator-before('last-id'): i2
Item i4, accumulator-before('last-id'): i3
Item i5, accumulator-before('last-id'): i4

Using --allow-multithreading:off for 9.9 also gives the intented results.


Files

input5.xml (370 Bytes) input5.xml Martin Honnen, 2018-10-02 07:41
acc-test-result-doc-text3.xsl (1.56 KB) acc-test-result-doc-text3.xsl Martin Honnen, 2018-10-02 07:41
Actions #1

Updated by Michael Kay about 6 years ago

  • Status changed from New to In Progress

I have added test case accumulator-075, with variant -075s for the streaming case.

Currently it is producing correct results for both 9.8 and 9.9.

It also produces correct results if I disable the patch for bug #3627.

But the report says the problem goes away if asynchronous processing is disabled, so there could be a multi-threading issue here that needs further investigation. I may try running it on 9.9 as issued without the various xsl:result-document patches that have been applied in the last few days.

Actions #2

Updated by Michael Kay about 6 years ago

The test case (in the form of accumulator-075s) is producing correct results when run with the test suite driver, but incorrect results when run from the command line.

Actions #3

Updated by Michael Kay about 6 years ago

This one is going to be tough. When xsl:result-document operates asynchronously relative to the thread that is reading the streamed input, it is necessary to retain the accumulator values associated with the context item until the asynchronous thread has finished with them. We are currently making no attempt to do this. The current accumulator value is simply held as a variable in the AccumulatorWatch (there is also a stack of values for ancestor nodes); there is no attempt to associate it directly with the FleetingElementNode (which IS retained until the asynchronous result-document thread has finished with it, because it's held in a ManualIterator in the thread's local snapshot of the dynamic context.)

Having said this, a design in which the predescent and postdescent values of the accumulator (actually, each applicable accumulator) are held directly in the FleetingNode would be in some ways much cleaner.

Actions #4

Updated by Michael Kay about 6 years ago

Note that when xsl:result-document is consuming, it's executed synchronously. The unusual thing about this case is that result-document isn't consuming, but is executed with a streamed node as the context node. Because this case is likely to be quite unusual, the obvious answer seems to be to execute the instruction synchronously in this case.

Actions #5

Updated by Michael Kay about 6 years ago

  • Status changed from In Progress to Resolved
  • Assignee set to Michael Kay
  • Applies to branch 9.8 added
  • Fix Committed on Branch 9.8, 9.9 added

Changed EnterpriseConfiguration.processResultDocument() to add getContextItem() instance of FleetingNode to the list of conditions that cause xsl:result-document to be processed synchronously.

Patch committed for 9.8 and 9.9.

Actions #6

Updated by O'Neil Delpratt about 6 years ago

  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 9.8.0.15 added

Bug fix applied in the Saxon 9.8.0.15 maintenance release. Leave open to the Saxon 9.9 maintenance release.

Actions #7

Updated by O'Neil Delpratt about 6 years ago

  • Status changed from Resolved to Closed
  • Fixed in Maintenance Release 9.9.0.2 added

Bug fix applied in the Saxon 9.9.0.2 maintenance release.

Please register to edit this issue

Also available in: Atom PDF