04
Mon, Nov
1 New Articles

Build Interactive Apps with XML Data Islands

Web Languages
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

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. It’s 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 doesn’t 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, there’s 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 you’re there, download the XML software development kit (SDK) so you’ll 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 tag, to help you make data islands work. I’ll start by showing you how to use it. A little later, you’ll look at another way to accomplish the same thing without using nonstandard tags.

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 doesn’t conform to any HTML standard.

Skipping to Figure 1, Section C, the page content consists of a heading element, some text, and a

element that serves as a container for the data island. The
has an id attribute so that it can be referenced easily by name. Following this, at Figure 1, Section D, are two elements. The first identifies the XSL stylesheet that will transform the XML data into HTML, and the second references the XML document itself.

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

(its inner HTML property) in Figure 1, Section C. Note that transformNode() is a method of the object named data, which is the XML document referenced by the second element in Figure 1, Section D. When the browser loads this page, the documents referenced by the src attribute of the elements are retrieved and processed automatically by MSXML, so both data and stylesheet actually represent DOM document objects. In this example, both are static documents, but they could just as easily have been retrieved from the HTTP server. The script itself is a function named initialize(). It is executed when the onload event of the element fires (see Figure 1, Section C). This happens immediately after the HTML page has completely loaded in the browser.

The XML document is timezones.xml. Here’s 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 it’s 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 element in the XML document. It contains the entire list of time zones, so this template is also instantiated only once, but unlike the root template, which processes the document itself, this template processes the document element. It creates an HTML table and extracts the groupname attribute of the element, which it formats as a heading for the table. It also creates column headings for the table data. The command passes control to any lower-level templates, of which there is only one.

At Figure 2, Section D, the element is processed by creating a table row () and table cells () to contain the id (@id) and name (@name) attributes of each within the scope of the calling context, which is all of them, because the calling context is the element, and it contains the entire document. Since there is no element specified in the template, all elements are processed in document order.



In addition to supporting an src attribute, which references an external document, the proprietary element also allows inline data. The XML data document itself could have been specified between the and tags.

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. I’ve intentionally not added any formatting so that you can easily identify the essential parts of the process.

Dynamic Document Loading with Script

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. It’s 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 tags, you need to make surprisingly few changes to the original source.

Referring back to Figure 1, Section A, you’ll insert a

At Figure 1, Section D, remove the tags. Once you’ve done this, you can now conform to the HTML 4.01 specification, so replace the document type definition at Figure1, Section A with:

http://www.w3.org/TR/html40/loose.dtd”>

At Figure 1, Section B, rewrite the script like this:

var timeZoneProcessor =
new templateProcessor(‘timezonelist.xsl’);

function initialize() {
timeZoneProcessor.loadXMLDocument(‘timezones.xml’);
island1.innerHTML = timeZoneProcessor.transform();
}

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, it’s still not very dynamic. It could be, though—stay tuned.

The Batch Entry Application

I’ve 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 element containing a specified zone ID. It does this by executing an XPath query. XPath is another of the W3C standards. It describes a query language that’s used to navigate through the structure of an XML document. If the zoneId function parameter contained the numeral 3, the expression would evaluate to:

recordNode = timeZones.selectSingleNode(‘timezone[@id=”3”]’);

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:

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++;
}

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 I’ve included it because I want to demonstrate how parameters are passed to an XSL stylesheet. Here’s what a radio button looks like, as defined in zoneedit.html:

value=”id;ascending;number” tabindex=”60”
checked onclick=”reSequence(this);”>

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 templateProcessor’s addParameter() method.

If you look at Figure 4, Section A, you’ll 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 element. They are in scope throughout the stylesheet. Figure 4, Section B



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 you’re 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.” That’s 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.

Don’t feel badly if you don’t get that one. It’s one of the most confusing aspects of XSL and does require some additional reading. The XSLT Programmer’s Reference, cited at the end of this article, will help.

As long as you’re 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 elements that have the asterisk symbol (*) as a name value. This is a crude device for storing deleted time zones so that they can be returned to the host. The server code then must look for this condition and delete the appropriate data rows. There is no delete function in zoneedit.html, but you can make a node disappear by replacing its descriptive name with a single asterisk.

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. It’s commented out and replaced with an alert dialog, which will show you what the serialized XML looks like.

At Figure 3, Section D, I’ve shown the method that inserts or replaces elements in the XML document. Figure 3, Section E contains a helper function that appends the required attribute values to the node. I’ve used a DocumentFragment for manipulating nodes. Document fragments are designed to have low processing overhead. Try out the result by double-clicking zoneedit.html in the example code folder.

Get Started!

By now, you may have just as many questions as answers. Within the limited space available here, I’ve 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 haven’t already done so, get started. XML is becoming more pervasive every day. We all need a little of it in our bag of tricks.



REFERENCES AND RELATED MATERIALS

• Applied XML: A Toolkit for Programmers. Alex Ceponkus and Faraz Hoodbhoy. New York, New York: John Wiley & Sons, Inc., 1999
• Microsoft Windows Script Technologies page: http://msdn.microsoft.com/scripting
• XSLT Programmer’s 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">
Simple Data Island




A Simple Data Island


Here is a group of time zones







A

B

C

D

Figure 1: It doesn’t take much to build a simple data island.




xmlns:xsl="http://www.w3.org/1999/XSL/Transform">















Time Zones

IDName









A

B

C

D

Figure 2: The XSL stylesheet transforms XML to HTML.



// =============================================================

// If the zone ID is valid, construct an XPath query
// and execute it to retrieve the current value of
// the time zone being edited.
// (formzones is the HTML form)
// (timeZones is a global reference to the documentElement node)
// =============================================================

function getRow(zoneId, updateDisplay) {
var zone = parseInt(zoneId);
var recordNode = null;

checkData('zone');
formzones.updatebatch.disabled = true;

try {
recordNode = timeZones.selectSingleNode('timezone[@id="'

+ zone.toString(10) + '"]');

if (updateDisplay) {
if (recordNode == null) {
formzones.zonetext.value = '';
} else {
formzones.zonetext.value =
recordNode.selectSingleNode('@name').value;
}

setFocus(formzones.zonetext);
}

return recordNode;

} catch (e) {

if (e.number != E_OBJECT_REQUIRED) {
alert('An error occurred while retrieving data '

+ 'in function getRow() with input values '
+ zoneId + ', ' + updateDisplay + ': '
+ e.description);
}

formzones.zonetext.value = '';
setFocus(formzones.zonetext);
return null;

}

// =============================================================

// Return the updated batch to the server
// Actual submit code is commented out for this example
// =============================================================

function submitBatch() {
// var request = new ActiveXObject("Msxml2.XMLHTTP")
// request.Open('POST', requestURI, true);
// request.Send(timeZoneProcessor.xmlDocument);
alert(timeZoneProcessor.xmlDocument.xml);

}

// =============================================================

// Add or update a row in the XML document
// (timeZones is a global reference to the documentElement node)
// =============================================================

function updateDocument(f) {
var xmlDocument = timeZoneProcessor.xmlDocument;
var recordNode = null;
var timeZone = null
var fragment = null;
var attribute = null;
var zoneId = parseInt(f.zoneid.value).toString(10);

checkData('all');

if (!abort) {
timeZone = xmlDocument.createElement('timezone');
fragment = xmlDocument.createDocumentFragment();
fragment.appendChild(timeZone);
appendAttribute(xmlDocument, timeZone, 'id', zoneId);
appendAttribute(xmlDocument, timeZone, 'name', f.zonetext.value);
recordNode = getRow(zoneId, false);

if (recordNode == null) {
timeZones.appendChild(fragment);
} else {
timeZones.replaceChild(fragment, recordNode);
}

island1.innerHTML = timeZoneProcessor.transform();
f.zoneid.value = '';
f.zonetext.value = '';
f.submitbatch.disabled = false;
f.updatebatch.disabled = true;
setFocus(f.zoneid);

}

C

D

A

Figure 3: Let’s debunk the smoke and mirrors thing.


}

}

// =============================================================

// Resequence the batch data list
// radioButton.value contains either
// "id;ascending;number" or "name;ascending;text"
// sort order could also be "descending",
// but that's not used here
// =============================================================

function reSequence(radioButton) {
var parameters = radioButton.value.split(';');
timeZoneProcessor.addParameter('sort-element', parameters[0]);
timeZoneProcessor.addParameter('sort-order', parameters[1]);
timeZoneProcessor.addParameter('sort-data-type', parameters[2]);
island1.innerHTML = timeZoneProcessor.transform();

}

// =============================================================

// Append attributes to a new timezone node
// =============================================================

function appendAttribute(aDocument, aNode, aName, aValue) {
var attribute = aDocument.createAttribute(aName);
attribute.value = aValue;
aNode.setAttributeNode(attribute);

}

B E



xmlns:xsl="http://www.w3.org/1999/XSL/Transform">











order="{$sort-order}"
data-type="{$sort-data-type}" />











A

B

C

Figure 4: You can pass external parameters to XSL.


BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: