I am trying to do XSL transformation in Edge and using a document node as xslt parameter(via XSLTProcessor.setParameter). The transformToFragment returns null in Edge (and Chrome), but works ok in Firefox.
Is there a way to make the code below working (at least in Edge) or is there no support of document-node as a xslt parameter? Below is a minimal code to present the issue.
https://jsfiddle.net/BennyHilarious/nxzLf9g3/1/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<script type="text/javascript">
function example() {
let xsldocp = new DOMParser();
const xsldoc = xsldocp.parseFromString(`<?xml version='1.0'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method='xml' omit-xml-declaration='yes'/>
<!-- Parameters -->
<xsl:param name='ntParam'/>
<xsl:param name='strSpaces' select='"    "'/> <!-- Default to 4 spaces -->
<!-- Global variables -->
<xsl:variable name='numTransformLevel' select='$ntParam/PARAMETER/@VALUE'/> <!-- does not work in Edge & Chrome -->
<!--xsl:variable name='numTransformLevel' select='2'/--><!-- works OK -->
<!-- Handles a generic element node. -->
<xsl:template match='*'>
<div>
<b><xsl:value-of select='$numTransformLevel'/></b>
<i><xsl:value-of select='//GROOT/@VALUE'/></i>
</div>
</xsl:template>
</xsl:stylesheet>
`,"application/xml");
let xsltProcessor = new XSLTProcessor();
// use the xsl sheet
xsltProcessor.importStylesheet(xsldoc);
// create xml
let parser = new DOMParser();
const docData = parser.parseFromString("<ROOT><GROOT VALUE='IAM'/></ROOT>", "application/xml");
// create param xml and set the parameter
parser = new DOMParser();
const docParam = parser.parseFromString("<PARAM><PARAMETER VALUE='5'/></PARAM>", "application/xml");
xsltProcessor.setParameter(null, "ntParam", docParam.documentElement);
// do the transformation
var targetElm = document.getElementById("trCont5");
let resultFrag = xsltProcessor.transformToFragment(docData, targetElm.ownerDocument);
targetElm.appendChild( resultFrag );
}
</script>
</head>
<body>
<input type="button" onclick="example();" value="XLSTParam Test"/><!-- Outputs 5IAM -->
<div id="trCont5"></div>
</body>
</html>
CodePudding user response:
Using SaxonJS (docs at https://www.saxonica.com/saxon-js/documentation2/index.html, download at https://www.saxonica.com/download/javascript.xml):
function example() {
const xslt = `<?xml version='1.0'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method='html'/>
<!-- Parameters -->
<xsl:param name='ntParam'/>
<xsl:param name='strSpaces' select='"    "'/> <!-- Default to 4 spaces -->
<!-- Global variables -->
<xsl:variable name='numTransformLevel' select='$ntParam/PARAMETER/@VALUE'/> <!-- does not work in Edge & Chrome -->
<!--xsl:variable name='numTransformLevel' select='2'/--><!-- works OK -->
<!-- Handles a generic element node. -->
<xsl:template match='*'>
<div>
<b><xsl:value-of select='$numTransformLevel'/></b>
<i><xsl:value-of select='//GROOT/@VALUE'/></i>
</div>
</xsl:template>
</xsl:stylesheet>
`;
// create xml
let parser = new DOMParser();
const docData = parser.parseFromString("<ROOT><GROOT VALUE='IAM'/></ROOT>", "application/xml");
// create param xml and set the parameter
const docParam = parser.parseFromString("<PARAM><PARAMETER VALUE='5'/></PARAM>", "application/xml");
// do the transformation
var targetElm = document.getElementById("trCont5");
let result = SaxonJS.XPath.evaluate(`
transform(map {
'source-node' : .,
'stylesheet-text' : $xslt,
'stylesheet-params' : map {
QName('', 'ntParam') : $ntParam
}
})?output`,
docData,
{
'params' : {
ntParam : docParam.documentElement,
xslt : xslt
}
});
targetElm.appendChild( result );
}
</script>
</head>
<body>
<input type="button" onclick="example();" value="XLSTParam Test"/><!-- Outputs 5IAM -->
<div id="trCont5"></div>
</body>
<script src="https://martin-honnen.github.io/xslt3fiddle/js/SaxonJS2.js"></script>
<input type="button" onclick="example();" value="XSLTParam Test"/><!-- Outputs 5IAM -->
<div id="trCont5"></div>
Note that for compactness and self-containedness of the example I used the SaxonJS.XPath.evaluate
method to call the XPath 3.1 transform
function on the fly to run the provided XSLT. SaxonJS also allows you to run precompiled XSLT with the SaxonJS.transform
method, for that you need to use either SaxonEE or the Node.js xslt3
tool (from Saxonica/NPM https://www.npmjs.com/package/xslt3) to compile the XSLT file to a JSON file.