Using parameter(s) with XML and XSL

The following example demonstrates how to use client side JavaScript to pass a parameter to an XSL stylesheet for transforming an XML file. The notes show IE, Mozilla and then a version that works on both. That is, the html/JavaScript code is different, but please note that the xml and xsl files are the same. The version working in both IE and Mozilla uses the try/catch construct for what is termed graceful handling of errors.

The example shown here uses a parameter to display only a portion of a contacts list. Actually, there are two examples: in the first one, the parameter is 'hard coded' in the HTML file. In the second example, the parameter is set by action by the user.

These examples use a more complex way of client side xml/xsl processing. In place of transformnode in the JavaScript IE example given before, for the IE case there are 4 different 'things': a xsl template, an xsl document, a processor, and an xml object. The processor has two methods, addParameter and transform, that do what the names imply. For the Mozilla case (which may also work with Netscape 7.1, but I have not tried it), there also are several 'things': holders for the xsl and the xml, a processor, and a document.

The xml file is contactsextra.xml. It is the familiar contacts file with a new child element: discipline. Here is the whole file. Notice that there is no reference to an xsl file.

<?xml version="1.0" ?>

<mylist>

<contact>

<name>Peter Ohring</name>

<email></email>

<discipline>mathematics</discipline>

</contact>

<contact>

<name>Joel Tenenbaum</name>

<email></email>

<discipline>physics</discipline>

</contact>

<contact>

<name>Marty Lewinter</name>

<email></email>

<discipline>mathematics</discipline>

</contact>

<contact>

<name>Jeanine Meyer</name>

<email></email>

<discipline>computer science</discipline>

</contact>

<contact>

<name>Irina Shablinsky</name>

<email></email>

<discipline>computer science</discipline>

</contact>

<contact>

<name>Mekhala Reddi</name>

<email></email>

<discipline>physics</discipline>

</contact>

<contact>

<name>Tim Bocchi</name>

<email></email>

<discipline>mathematics</discipline>

</contact>

</mylist>

The xsl file is contactsuseparm.xsl. It has 3 changes from previous examples.

  1. An xsl:param element sets up the situation for there to be a parameter named 'subj'. Look back to the use of <xsl:param> in the beer bottle song.
  2. The parameter is used directly by the element: <xsl:value-of select="$subj"/>. Note here the use of the dollar sign before the parameter name.
  3. The parameter is used (again) in a when element (child of a choose element child of a for-each) to display only the content of the contact where the discipline node is equal to the value of $subj.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="

xmlns:fo="

<xsl:output method="html"/>

<xsl:param name="subj"/>

<xsl:template match="/">

<html>

<head>

<title>Faculty </title>

</head>

<body> <h1>Here is the

<xsl:value-of select="$subj"/>

faculty </h1> <br/>

<table border="2">

<tr<th>Name </th> <th> E-mail </th> </tr>

<xsl:for-each select="mylist/contact">

<xsl:sort select="name"/>

<xsl:choose>

<xsl:when test="discipline=$subj">

<tr<td>

<xsl:value-of select="name"/</td>

<td>

<xsl:value-of select="email"/</td>

</tr>

</xsl:when>

</xsl:choose>

</xsl:for-each>

</table>

</body>

</html>

</xsl:template>

</xsl:stylesheet>

Next, here are two html files. I strongly suggest that you follow my example and do the 'hard coded' one first and then the more general one. Note: both use the same xml and xsl files.

xmlparms.html is a file with 'hard coding' of the setting of the subj parameter to be mathematics. Get it working and then change 'mathematics' to 'physics' and to 'computer science'. Notice how the template, xsl, xml, and processor objects are created and connected.

<html> <head> <script type="text/javascript">

var xslt = new ActiveXObject("Msxml2.XSLTemplate");

var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");

var xslProc;

xslDoc.async = false;

xslDoc.resolveExternals = false;

xslDoc.load("contactsuseparm.xsl");

xslt.stylesheet = xslDoc;

var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");

xmlDoc.async = false;

xmlDoc.resolveExternals = false;

xmlDoc.load("contactsextra.xml");

xslProc = xslt.createProcessor();

xslProc.input = xmlDoc;

xslProc.addParameter("subj", "mathematics");

xslProc.transform();

document.write(xslProc.output);

</script> </head>

<body>

</body>

</html>

The last example allows the user to select one of the 3 disciplines by clicking on links. Each link invokes a function that sets the parameter as appropriate. I went from xmlparms to xmlparmsg by putting the code into a function with a parameter. The parameter is set in the call to the function in the href values in the a links. The document.write overwrites the original html file. Note: alternative approaches are to name the body or a div of an html document

<div id='place'>

and then use

place.innerHTML = xslProc.output.

<html> <head> <script type="text/javascript">

function outputgroup(subject) {

var xslt = new ActiveXObject("Msxml2.XSLTemplate");

var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");

var xslProc;

xslDoc.async = false;

xslDoc.resolveExternals = false;

xslDoc.load("contactsuseparm.xsl");

xslt.stylesheet = xslDoc;

var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");

xmlDoc.async = false;

xmlDoc.resolveExternals = false;

xmlDoc.load("contactsextra.xml");

xslProc = xslt.createProcessor();

xslProc.input = xmlDoc;

xslProc.addParameter("subj", subject);

xslProc.transform();

document.write(xslProc.output);

}

</script> </head>

<body>

<a href="javascript:outputgroup('computer science');">Computer Science </a<br/>

<a href="javascript:outputgroup('physics');">Physics </a<br/>

<a href="javascript:outputgroup('mathematics');">Mathematics </a<br/>

</body>

</html>

Note: when you view source before clicking on the links, you will see the original file, with the JavaScript code. If you view source after clicking on the links, you see what the HTML produced by the transform is.

Note: alternative approaches are to name the body or a div of an html document

<div id='place'>

and then use

place.innerHTML = xslProc.output.

This allows you to change just some of the HTML document.

Here is the Mozilla version. It corresponds to the more general IE version.

<html> <head> <script type="text/javascript">

var xslStylesheet;

var xsltProcessor = new XSLTProcessor();

var myDOM;

var xmlDoc;

function outputgroup(subject){

// load the xslt file

var myXMLHTTPRequest = new XMLHttpRequest();

myXMLHTTPRequest.open("GET", "contactsuseparm.xsl", false);

myXMLHTTPRequest.send(null);

xslStylesheet = myXMLHTTPRequest.responseXML;

xsltProcessor.importStylesheet(xslStylesheet);

// load the xml file

myXMLHTTPRequest = new XMLHttpRequest();

myXMLHTTPRequest.open("GET", "contactsextra.xml", false);

myXMLHTTPRequest.send(null);

xmlDoc = myXMLHTTPRequest.responseXML;

// set the parameter using the parameter passed to the outputgroup function

xsltProcessor.setParameter(null,"subj",subject);

var fragment = xsltProcessor.transformToFragment(xmlDoc,document);

document.getElementById("answer").innerHTML = "";

myDOM = fragment;

document.getElementById("answer").appendChild(fragment);

}

</script> </head>

<body>

<body>

<a href="javascript:outputgroup('computer science');">Computer Science </a<br/>

<a href="javascript:outputgroup('physics');">Physics </a<br/>

<a href="javascript:outputgroup('mathematics');">Mathematics </a<br/>

<div id="answer">

</div>

<br/> <br/>

<a href="xmlparmsmozilla.html">Repeat</a>

</body>

</html>

</body>

</html>

Now the challenge is to make a version that works in either case. I could have tried to detect the browser using various methods such as the navigator object or I could have done a check on one of the objects used in the code. After some frustrating research, I decided to go with the JavaScript try and catch mechanism. This is used for what is called error-trapping. Rather than allow the system to detect an error, the system turns control to your code. The code is given completely below, but the outline is:

try {

the code for the IE way

}

catch(e) {

try {

the Mozilla way}

catch(e) {

display a message that this couldn't be done—this happens with Netscape

}

}

The argument e in the two occurrences of catch is never used. In other examples of try and catch, you may use e to display information on the error.

Here is xmlparmseither.html

<html> <head> <script type="text/javascript">

function outputgroup(subject){

// load the xslt file

try {

var xslt = new ActiveXObject("Msxml2.XSLTemplate");

var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");

var xslProc;

xslDoc.async = false;

xslDoc.resolveExternals = false;

xslDoc.load("contactsuseparm.xsl");

xslt.stylesheet = xslDoc;

var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");

xmlDoc.async = false;

xmlDoc.resolveExternals = false;

xmlDoc.load("contactsextra.xml");

xslProc = xslt.createProcessor();

xslProc.input = xmlDoc;

xslProc.addParameter("subj", subject);

xslProc.transform();

document.write(xslProc.output);

}

catch(e) {

try{

var xslStylesheet;

var xsltProcessor = new XSLTProcessor();

var myDOM;

var xmlDoc;

var myXMLHTTPRequest = new XMLHttpRequest();

myXMLHTTPRequest.open("GET", "contactsuseparm.xsl", false);

myXMLHTTPRequest.send(null);

xslStylesheet = myXMLHTTPRequest.responseXML;

xsltProcessor.importStylesheet(xslStylesheet);

// load the xml file

myXMLHTTPRequest = new XMLHttpRequest();

myXMLHTTPRequest.open("GET", "contactsextra.xml", false);

myXMLHTTPRequest.send(null);

xmlDoc = myXMLHTTPRequest.responseXML;

// set the parameter using the parameter passed to the outputgroup function

xsltProcessor.setParameter(null,"subj",subject);

var fragment = xsltProcessor.transformToFragment(xmlDoc,document);

document.getElementById("answer").innerHTML = "";

myDOM = fragment;

document.getElementById("answer").appendChild(fragment);

}

catch(e) {

alert("Unable to do xml/xsl processing");

}

}

}

</script> </head>

<body>

<a href="javascript:outputgroup('computer science');">Computer Science </a<br/>

<a href="javascript:outputgroup('physics');">Physics </a<br/>

<a href="javascript:outputgroup('mathematics');">Mathematics </a<br/>

<div id="answer">

</div>

<br/> <br/>

<a href="xmlparmseither.html">Repeat</a>

</body>

</html>

</body>

</html>