Project

Profile

Help

Bug #6626

closed

When chaining two streamable stylesheets with asDocumentDestination, an accumulator isn't copied to grounded nodes created with copy-of()

Added by Martin Honnen 15 days ago. Updated 5 days ago.

Status:
Resolved
Priority:
Normal
Assignee:
-
Category:
s9api API
Sprint/Milestone:
Start date:
2025-01-06
Due date:
% Done:

0%

Estimated time:
Legacy ID:
Applies to branch:
12, trunk
Fix Committed on Branch:
12, trunk
Fixed in Maintenance Release:
Platforms:
.NET, Java

Description

Testing with Saxon 12.5 EE Java, I have found a strange problem, I have an accumulator in a streamable stylesheet that is also then used for a "grounded" element node created with copy-of(); when I run the stylesheet stand-alone the grounded element node has the accumulator value, however, when I chain two streamable stylesheets with asDocumentDestination it appears as if the accumulator (value) is not copied to the element node created with copy-of().

Example XML;

<root>
    <foo>foo 1</foo>
    <bar>bar 1</bar>
</root>

Example XSLT with the accumulator:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:saxon="http://saxon.sf.net/"
                exclude-result-prefixes="#all"
                version="3.0"
                expand-text="yes">

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

    <xsl:mode on-no-match="shallow-copy" streamable="yes" use-accumulators="latest-foo-value"/>

    <xsl:mode name="grounded" on-no-match="shallow-copy"/>

    <xsl:template match="bar">
        <xsl:comment>node {node-name()}: accumulator-before('latest-foo-value'): {accumulator-before('latest-foo-value')}</xsl:comment>
        <xsl:apply-templates select="copy-of()" mode="grounded"/>
    </xsl:template>

    <xsl:template mode="grounded" match="bar">
        <xsl:comment>node {node-name()}: accumulator-before('latest-foo-value'): {accumulator-before('latest-foo-value')}</xsl:comment>
        <xsl:next-match/>
    </xsl:template>

    <xsl:template match="/">
        <xsl:copy>
            <xsl:apply-templates/>
            <xsl:comment>Run with {static-base-uri()} at {current-dateTime()}</xsl:comment>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Correct result when running that stylesheet stand-alone against the input sample:

<?xml version="1.0" encoding="UTF-8"?><root>
    <foo>foo 1</foo>
    <!--node bar: accumulator-before('latest-foo-value'): foo 1--><!--node bar: accumulator-before('latest-foo-value'): foo 1--><bar>bar 1</bar>
</root><!--Run with file:/C:/Users/marti/IdeaProjects/SerializerProblem2/./accumulator-test1.xsl at 2025-01-06T11:45:44.7716048+01:00-->

Result when chaining with a streamed identity transformation

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:saxon="http://saxon.sf.net/"
                exclude-result-prefixes="#all"
                version="3.0"
                expand-text="yes">

    <xsl:mode on-no-match="shallow-copy" streamable="yes"/>

    <xsl:template match="/">
        <xsl:copy>
            <xsl:apply-templates/>
            <xsl:comment>Run with {static-base-uri()} at {current-dateTime()}</xsl:comment>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

and the Java code

package org.example;

import net.sf.saxon.s9api.*;

import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Main {
    public static void main(String[] args) throws SaxonApiException, IOException {

        Processor processor = new Processor(true);

        XsltCompiler xsltCompiler = processor.newXsltCompiler();

        XsltExecutable xsltExecutable1 = xsltCompiler.compile(new File("identity-transformation.xsl"));

        Xslt30Transformer xslt30Transformer1 = xsltExecutable1.load30();

        XsltExecutable xsltExecutable2 = xsltCompiler.compile(new File("accumulator-test1.xsl"));

        Xslt30Transformer xslt30Transformer2 = xsltExecutable2.load30();

        xslt30Transformer1.applyTemplates(
                new StreamSource(new File("sample1.xml")),
                xslt30Transformer2.asDocumentDestination(xslt30Transformer2.newSerializer(Files.newOutputStream(Paths.get("result3.xml"))))
        );
    }
}

is

<?xml version="1.0" encoding="UTF-8"?><root>
    <foo>foo 1</foo>
    <!--node bar: accumulator-before('latest-foo-value'): foo 1--><!--node bar: accumulator-before('latest-foo-value'): --><bar>bar 1</bar>
</root><!--Run with file:/C:/Users/marti/IdeaProjects/SerializerProblem2/identity-transformation.xsl at 2025-01-06T11:42:17.241+01:00--><!--Run with file:/C:/Users/marti/IdeaProjects/SerializerProblem2/accumulator-test1.xsl at 2025-01-06T11:42:17.242+01:00-->

so here it seems the accumulator (value) is not copied to the bar element created with copy-of().

Please register to edit this issue

Also available in: Atom PDF