Do you have a network of Windows clients? Would you like to use a browser-based user interface for batch data entry? Do you cringe at the thought of installing and maintaining custom software on dozens or hundreds of client workstations? If so, read on.
As you probably know, XML stands for Extensible Markup Language. Its a close cousin of HTML, and it can be manipulated with Document Object Model (DOM) methods. The World Wide Web Consortium (W3C) controls the standards for these and many other acronyms that are near and dear to our hearts. What you might not know is that there are several DOM implementations available; at this time, however, only the Microsoft version of XML (MSXML) provides support for Extensible Stylesheet Language (XSL) and works in the browser. Although Microsoft doesnt completely implement the DOM standard, the lights are burning late into the night in Redmond in order to change that. By the time you read this, the situation might be different. The Microsoft DOM is reasonably complete and completely usable right now, so, if yours is a Microsoft shop, theres no reason to wait any longer.
The examples I use in this article work with Internet Explorer Version 5.5 and MSXML version 3.0, which is the first production version of MSXML. Download the latest copy of Internet Explorer at www.microsoft.com/windows/ie/default.htm. Get the latest version of MSXML at http://msdn.microsoft.com/xml/general/xmlparser.asp and while youre there, download the XML software development kit (SDK) so youll have easy access to the documentation. Install MSXML in Replace mode according to the instructions in the SDK (search for Replace Mode).
A Simple Data Island
As you might guess, an XML data island is an area in an HTML page that contains output rendered from XML instead of HTML. Microsoft has implemented a proprietary HTML element, the
I will start by examining Figure 1. It shows a very simple HTML page displaying a list of North American time zones. Figure 1, Section A contains the document type declaration, a tag to identify the content type and encoding, another that specifies the default scripting language (ecmascript is the proper name for JavaScript or JScript) and
the page title. Note that the document type definition does not specify a document type description (DTD). Since you are using proprietary tags in the document, this page doesnt conform to any HTML standard.
Skipping to Figure 1, Section C, the page content consists of a heading element, some text, and a
Now, go back and look at Figure 1, Section B. It contains a script that uses one of the MSXML methods, transformNode(), to populate the content of the island1
The XML document is timezones.xml. Heres a small piece of it:
- - etc.
Figure 2 shows the timezonelist.xsl stylesheet. Figure 2, Section A contains the required document type declaration and defines the XML namespace for stylesheets. It also specifies that the stylesheet output should be HTML. I should mention here that in the December 2000 MC article, Demystifying XML: A Practical Example, I showed a stylesheet that used an earlier, provisional version of XSL. There are some syntactic and functional differences between the two versions. The Microsoft DOM implementation is backward compatible. Internet Explorer will process either version if the namespace declaration is appropriate for the stylesheet content.
Figure 2, Section B contains the root template. In this stylesheet, its only purpose is to instantiate the lower-level templates. This is exactly the default behavior when there is no root template, so its not needed here but is included for clarity. The root template is instantiated once only and is a good place to output static content.
Figure 2, Section C contains a template that processes the
At Figure 2, Section D, the In addition to supporting an src attribute, which references an external document, the proprietary You can view the result by downloading the example code from www.midrangecomputing.com/mc and double-clicking on the simpleisland.html file. The browser output is not pretty. Ive intentionally not added any formatting so that you can easily identify the essential parts of the process. The DOM standard defines the behavior of a proscribed group of functions and objects. With only a few exceptions, all DOM implementations must behave identically from the vantage point of the developer. However, some very necessary functions are not defined by the standard. There is, for instance, no method defined for retrieving an XML document. This very necessary function, unfortunately, is left to the discretion of the DOM implementer. Microsoft has provided this service with two functions in MSXML. The loadXML() method will create a DOM document object from a string containing XML markup, and the load() method will retrieve and instantiate a DOM document contained in a text stream, which could be represented by a file or an HTTP request. This is all very fine, but it becomes unwieldy when there are multiple XML document and stylesheet combinations within the same scripting context. It simplifies matters greatly if an XML stylesheet and the processing that it implies are encapsulated in an object, which can both maintain scope and mask the complexity of implementing an XSL transform. Happily, JavaScript provides a way to build a reasonable facsimile of a traditional class object, which can serve both purposes, so I built one. Its the templateProcessor class, which is included in the global scripts file, javascript/global.js, in the downloadable code for this article. To create the time zone list with templateProcessor instead of Referring back to Figure 1, Section A, youll insert a At Figure 1, Section D, remove the At Figure 1, Section B, rewrite the script like this: A global timeZoneProcessor variable has been declared. It contains an instance of the templateProcessor class, which encapsulates the timezonelist.xsl stylesheet. This object is then used to populate the data island in a straightforward manner in the initialize() function. A listing of the templateProcessor methods and an explanation of what each of them does is contained in javascript/global.js. Double-click dynamicisland.html in the example code directory to see the result. In reality, its still not very dynamic. It could be, thoughstay tuned. Ive extended the dynamicisland.html example into a complete interactive batch entry and edit application. Look at the important parts of the script that does the job. The getRow() function in Figure 3 (page 51), Section A locates and returns a reference to the If the requested zoneid value is not already in the XML document, recordNode will be null. Note that the timeZones object is a global reference to the XML document element ( The selectSingleNode() function is a Microsoft extension to the DOM methods. If you wanted to use only standard functions, you would need to walk down the tree in script with something like this: The reSequence() function, shown in Figure 3, Section B, redisplays the list body in the requested order, based on the value attribute of a radio button. Sorting is not important in this example, but Ive included it because I want to demonstrate how parameters are passed to an XSL stylesheet. Heres what a radio button looks like, as defined in zoneedit.html: Notice that the value attribute actually contains three values delimited by semicolons (;). The reSequence() function separates them by calling the ECMAScript split() function. It returns the parsed words as elements of an array, which is ideal for the purpose here. The individual parameter values are passed to the XSL stylesheet by calling the templateProcessors addParameter() method. If you look at Figure 4, Section A, youll see how these parameters are defined in the stylesheet. They each have a default value, which is used until you change it with an addParameter() call. These are top-level (global) parameters, because they are children of the shows how they are actually used to define the sort. If you were specifying the sort key with a literal value, you would simply have written: In this instance though, since youre using a parameter, you need to use the slightly more complicated select syntax: This really means retrieve a node set containing all attributes of the current element, then filter that node set and return the subset having a name equal to the string value of the sort-element parameter. Thats fairly ugly, but required because the lexical constraints of XSL effectively prevent an xsl:param or xsl:variable from matching anything that is not a value or a node-set. The name() function in the expression above converts the names of the attribute node children of the current element to string values so that they can be compared with the value of the sort-element parameter. The sort-element parameter can also be a node-set, but in this case is treated as a scalar, because it receives its value from a literal select attribute, rather than from an XPath expression or a child template body. Notice also that the sort-order and sort-data-type parameters are enclosed in curly braces ({}). This syntax defines them to be attribute value templates, whose text value is used to provide the order and data-type attribute values. The select attribute of xsl:sort requires a string value. It will not accept an attribute value template. Dont feel badly if you dont get that one. Its one of the most confusing aspects of XSL and does require some additional reading. The XSLT Programmers Reference, cited at the end of this article, will help. As long as youre looking at Figure 4, I may as well point out that the timezone template in Figure 4, Section C has a match attribute which excludes Returning back to Figure 3, Section C, the submitBatch() function contains the code needed to send the updated batch back to the server for processing. Its commented out and replaced with an alert dialog, which will show you what the serialized XML looks like. At Figure 3, Section D, Ive shown the method that inserts or replaces By now, you may have just as many questions as answers. Within the limited space available here, Ive tried to give you a feel for the power of this new technology. Download the example code from www.midrangecomputing.com/mc. Use the examples as a starting point. Borrow pieces of them, if you like. Start with something simple, but if you havent already done so, get started. XML is becoming more pervasive every day. We all need a little of it in our bag of tricks. Applied XML: A Toolkit for Programmers. Alex Ceponkus and Faraz Hoodbhoy. New York, New York: John Wiley & Sons, Inc., 1999 Here is a group of time zones) and table cells ( ) to contain the id (@id) and name (@name) attributes of each
Dynamic Document Loading with Script
http://www.w3.org/TR/html40/loose.dtd>
var timeZoneProcessor =
new templateProcessor(timezonelist.xsl);function initialize() {
timeZoneProcessor.loadXMLDocument(timezones.xml);
island1.innerHTML = timeZoneProcessor.transform();
}
The Batch Entry Application
recordNode = timeZones.selectSingleNode(timezone[@id=3]);
var childNodes = timeZones.childNodes;
var nodeCount = childNodes.length;
var i = 0;while ((i < nodeCount) && (recordNode == null)) {
if (childNodes[i].getAttribute(id) == zoneId) {
recordNode = childNodes[i];}
i++;
}value=id;ascending;number tabindex=60
checked onclick=reSequence(this);>
Get Started!
REFERENCES AND RELATED MATERIALS
Microsoft Windows Script Technologies page: http://msdn.microsoft.com/scripting
XSLT Programmers Reference. Michael Kay. Birmingham, United Kingdom: Wrox Press Inc., 2000
W3C XSLT Specification: www.w3.org/TR/xslt/
W3C DOM Level 2 Core specification: www.w3.org/TR/DOM-Level-2-Core/ core.html
content="text/html; charset=UTF-8">
content="text/ecmascript">
A Simple Data Island