Skip to main content

Browser-independent XSLT with Javascript

Tags:
Reading time: 2 minutes Suggest an edit

To piggy-back on the Javascript function to load an XML document: what can be done to load an XSL stylesheet and apply it to the XML? For the most part, loading it is a snap… but, as is often the case, Internet Explorer is the exception to the rule. So, we write a function that tells every browser except for IE to use our previously-defined loadXML() function, and an exception for Internet Explorer to load the XSL as a "free-threaded document." Note: The reason for this is that IE's Javascript engine will throw a hissy-fit if you try to transform an XML tree using an XMLDOM object as your XSL.

Javascript code:

function loadXSL(dname) {
	if (window.ActiveXObject) {
		// Internet Explorer
		try {
			var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
			xslDoc.async = false;
			xslDoc.resolveExternals = false;
			xslDoc.load(dname);
			return xslDoc;
		} catch (e) {
			alert("Cannot load XSL stylesheet\\n\\nError:\\n" + e.message);
			return false;
		}
	} else {
		// Everything else
		return loadXML(dname);
	}
}

Next, we will need a function for applying the XSL stylesheet to the XML tree. The following function does just that–browser-agnostic, of course–and sends the resulting formatted XML to a given container (i.e., a <div /> element):

Javascript code:

function xslTransform(xml, xsl, div, par) {
	if (typeof par == "undefined") par = null;
	div.innerHTML = "";

	if (window.ActiveXObject) {
		// Internet Explorer
		var xslt = new ActiveXObject("Msxml2.XSLTemplate");
		xslt.stylesheet = xsl;
		var xsltProc = xslt.createProcessor();
		xsltProc.input = xml;
		for (var a = 0; a < par.length; a++)
			xsltProc.addParameter(par[a].pname, par[a].pval);
		xsltProc.transform();
		div.innerHTML = xsltProc.output;
	} else if (
		document.implementation &&
		document.implementation.createDocument
	) {
		// Mozilla/Firefox, Opera, WebKit (Safari, Chrome), etc.
		var xsltProc = new XSLTProcessor();
		xsltProc.importStylesheet(xsl);
		for (var a = 0; a < par.length; a++)
			xsltProc.setParameter(null, par[a].pname, par[a].pval);
		div.appendChild(xsltProc.transformToFragment(xml, document));
	}
}

XSL parameters are a handy way for Javascript to influence the XSL stylesheet's behavior during transformation. The par parameter is used for just that. It is an array of objects/associative arrays that have two members: pname and pval. This could easily be reconfigured to use a two-dimensional, integer-indexed array (or whatever data structure you may prefer). If no par is supplied, it will default to null and the for-loop will not execute. Remember, an XSL stylesheet must be loaded in Internet Explorer as a "free-threaded document" (see above), or the transformation will fail!