Project

Profile

Help

Bug #5039

Chaining two XSLTs where the first creates a fragment with two element children works under Node.js but not in the browser

Added by Martin Honnen 2 months ago. Updated 2 months ago.

Status:
New
Priority:
Low
Assignee:
-
Category:
-
Sprint/Milestone:
-
Start date:
2021-07-15
Due date:
% Done:

0%

Estimated time:
Applies to JS Branch:
2
Fix Committed on JS Branch:
Fixed in JS Release:
SEF Generated with:
Company:
-
Contact person:
-
Additional contact persons:
-

Description

When I run the code

const SaxonJS = require("saxon-js")

const xslt1Source = `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all">

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

    <xsl:template match="data">
        <h1><xsl:value-of select="name" /></h1>
        <div>Age: <xsl:value-of select="age" /></div>
    </xsl:template>
    
</xsl:stylesheet>`;

const xslt2Source = `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all">

    <xsl:mode on-no-match="shallow-copy"/>
  
    <xsl:template match="h1">
        <p>My name is <xsl:value-of select="." />!</p>
    </xsl:template>

</xsl:stylesheet>`;

const xmlSource = `<data>
<name>John</name>
<age>25</age>
</data>`;

const result = SaxonJS.XPath.evaluate(`
    fold-left(
        $xsltSources,
        parse-xml($xmlSource),
        function($node, $xsltText) {
            transform(
                map {
                    'source-node' : $node,
                    'stylesheet-text': $xsltText
                }
            )?output
        }
    )`, [], { 'params' : { 'xmlSource' : xmlSource, 'xsltSources' : [xslt1Source, xslt2Source] } })

console.log(SaxonJS.serialize(result));

under Node.js it works fine and outputs <p>My name is John!</p><div>Age: 25</div>.

Trying to run the same (minus the first line with the require call) in the browser gives an error "Uncaught DOMException: Failed to execute 'appendChild' on 'Node': Only one element on document allowed." in SaxonJS2.js:4407.

So somehow it seems the Node.js version manages to create a document fragment node with two element children while the browser version seems to try to put two element nodes into a document node.

The error only occurs when trying to chain the two stylesheets, the first run alone creating the fragment with two element children runs fine.

History

#1 Updated by Martin Honnen 2 months ago

Looking at the fn:transform spec I think it might be safer to use 'delivery-format' : 'raw' in the argument map to the transform() call.

It doesn't change the error, however, somehow, although I have checked that the result after the first transformation is a document fragment node, Saxon-JS 2.2 in the browser tries to create a document node in addition to the returned document fragment node to run the second transformation, then tries to appendChild() clones of the first step transform result's document fragment node's children to the document node; appending two elements to a document node is obviously not possible in the DOM.

Please register to edit this issue

Also available in: Atom PDF Tracking page