uch of the focus of XSLT has been on its "stylesheet" capabilitiesthe ability to convert XML into some form of displayed HTML. However, XSLT is a functional language, one that takes an XML "state" and converts it into a different XML statein essence, a form of black box that takes data in and spits different data out. You can use this to your advantage to turn XSLT scripts into client (or server side) methods that add significant power to your web development toolset, especially if your clients use Internet Explorer. <xsl:sort
select="*[name(.)=$sortKey]|@*[name(.)=$sortKey]"
order="{$sortOrder}"/>
The select attribute performs a generalized search, looking for either elements ("*[name(.)") or attributes ("@*[name(.)") that have the name of the sort key. By checking both, you can easily sort on attributes as well as elements, minimizing the need to have two such routines. You must escape the order attribute using the {} brackets, because its content is explicitly defined to be a string (in fact, it's a Name Token, but at least with most XSLT parsers, tokens are typically mapped to the string type).
Wrapping XSLT in Procedural Clothes
An XML Data Island is a Microsoft-specific way to include XML content within HTML pages in Internet Explorer. A data island has an <xml> tag with optional id and src attributes. While you can use data islands to provide local XML for data population operations, you can also use these islands to store your XSLT code. For example, you can create a data island consisting of the XML code in Listing 1 as follows:
<xml id="records">  <records>  <record id="101">  <firstname>Kurt</firstname>  <lastname>Cagle</lastname>  </record> <!-- more records --> </records> </xml>Similarly, you can store the XSLT as:
<xml id="_ShowRecords"> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:param name="sortKey" select="'firstname'"/> <xsl:param name="sortOrder" select="'ascending'"/> <!-- more of the same --> </xsl:stylesheet> </xml>You can then retrieve an XML DOM version of the data island with the XMLDocument property of the <xml> element. For example, to retrieve the XSL document as a DOM element using JavaScript, you would write:
var xslDoc= _ShowRecords.XMLDocument;I added the underscore to the ID to indicate that this is a data island function as opposed to a simple transform.
<xml id="_ShowRecords" src="ShowRecords.xsl"/>After you have the XML and XSLT documents in data islands, you can pass the XML to the stylesheet using some basic JavaScript. However, rather than writing a function that calls the stylesheet internally, you can pass the stylesheet itself as an argument to a generalized function, as well as passing additional parameters. I did this by creating a generic call() function in JavaScript (see Listing 5):
function call(xslIsland,xmlIsland){
var xslDoc = new
ActiveXObject
("MSXML2.FreeThreadedDOMDocument");
var rsltDoc = new
ActiveXObject
("MSXML2.FreeThreadedDOMDocument");
var xslTemplate = new ActiveXObject
("MSXML2.XSLTemplate");
xslDoc.load(xslIsland.XMLDocument);
xslTemplate.stylesheet=xslDoc;
var xslProc=xslTemplate.createProcessor();
xslProc.input=xmlIsland.XMLDocument;
xslProc.output=rsltDoc;
if (arguments.length > 2 &&
arguments.length % 2 == 0){
for (var i = 0;
i < Math.floor
((arguments.length) / 2) - 1;
i++) {
paramName=arguments[2*i+2];
paramValue=arguments[2*i+3];
xslProc.addParameter
(paramName,paramValue);
}
}
xslProc.transform();
return rsltDoc;
}
The call() function takes two primary arguments -- an XML data island reference and an XSL Data Island reference. While I could have passed both XML and XSL as DOMs, passing them as data island references de-emphasizes their roles as files and instead makes the function act more like a method. The following example shows how to invoke the call() function to display the records by first name in ascending order:call(_ShowRecords,records,"sortKey","firstname", "sortOrder","ascending");This technique encapsulates the XSL processing within a transparent process, with a very straightforward call syntax. Note, however, that a few parameters snuck into the call() function invocation. The function takes advantage of a JavaScript capability that VBScript doesn't supportthe ability to create virtual parameters. The first two parameters specify the data on which the method works. Each succeeding pair of parameters contains a name and value that the call() function will in turn pass to the XSLT function as parameters. Thus, the first parameter is named "sortKey" with a value of "firstname", the second parameter is named "sortOrder" with a value of "ascending". This was specifically done with the arguments JavaScript collection:
if (arguments.length > 2 &&
arguments.length % 2 == 0){
for (var i=0;
i < Math.floor((arguments.length)/2)-1;
i++){
paramName=arguments[2*i+2];
paramValue=arguments[2*i+3];
xslProc.addParameter(paramName,paramValue);
}
}
The routine iterates over all arguments after the first two, retrieves the parameter name and parameter value (the parameters must be in that order), and then uses the XSL Processor object (part of the MSXML3 and MSXML4 library) to set the specified XSLT parameter name to the specified value. function showRecords(sortKey,sortOrder){
var resultDoc =
call(_ShowRecords,records,"sortKey",
sortKey,"sortOrder",sortOrder);
window.container.innerHTML=resultDoc.xml;
}
The showRecords() function uses the call() function internally to retrieve an XML DOM object that's placed in the variable resultDoc. The showRecords() function obtains the resulting XML string using the resultDoc.xml property and places the contents in the <div> element with the id "container," where it displays as HTML.
| DevX is a division of Internet.com. © Copyright 2010 Internet.com. All Rights Reserved. Legal Notices |