I just want to document a solution to a problem I was having with transformToFragment.
I was having trouble with XSLTProcessor::transformToFragment() returning null on WebKit browsers (Safari and Chrome). Having read comments about issues with the load() method and xsl:import element, I used XMLHttpRequest and a very simple stylesheet and XML document for testing. Even after having eliminated the well-known problems, I was still disappointed to get a null return value from transformToFragment().
Finally, I noticed that one example used:
<xsl:output method=“html” />
where I had been using:
<xsl:output method=“xml” … />
When I changed my method to “html”, the transformToFragment() worked.
I hope this small bit of information will help someone.
In other words, the node you pass to transformToFragment is treated as a document element and thus causes your <xsl:template match=“/”> to run.
I can think of several ways this could defeat a stylesheet design if the stylesheet is used to process arbitrary document nodes for an XSL-driven web page.
I offer this simple function to pre-process an XSL document prior to calling XSLTProcessor::importStylesheet, assuming that the contents of the document-matching template are not needed once the page has been rendered:
function fixWebKitStylesheet(doc)
{
// ensure output method = html:
var node = doc.selectSingleNode("/xsl:stylesheet/xsl:output");
if (node && node.getAttribute("method")=="xml")
node.setAttribute("method", "html");
// gut out document node template to deal with Webkit bug
// Google: webkit bug 28744 "root one"
if ((node=doc.selectSingleNode("/xsl:stylesheet/xsl:template[@match='/']")))
{
var child;
while ((child=node.lastChild))
node.removeChild(child);
child = node.appendChild(doc.createElement("xsl:apply-templates"));
child.setAttribute("select", "*");
}
}
(Please forgive the extra conditional parens, emacs gripes if they’re not used)
and here is a sample if how that function might be called:
function getProcessor(doc)
{
// detect WebKit implementation (incomplete example pulled out
// of other code that handles cross-browser XMLDOM differences):
var d = document.implementation.createDocument("","",null);
var isWebKit = !(d.load);
var proc = new XSLTProcessor();
if (isWebKit)
fixWebKitStylesheet(doc);
proc.importStylesheet(doc);
return proc;
}
It’s a relief to me that my XML-XSL methods can finally support Safari and now especially Chrome. The above code works for the ways I use transformToFragment, it may not work in every situation.