XML Data Island - Ajax Patterns

XML Data Island

From Ajax Patterns

Evidence: 1/3

Tags: Data DOM Storage XML


Contents

In A Blink

Diagram xml transported and baked into DOM


Technical Story

Dave's demographics viewer stores each table of statistics as an XML document. A big cache of XML documents is held within the page, one for each table. The user can rearrange the tables, and switch them between visible and hidden, but all the XML metadata remains on the page. To render the tables, Dave exploits the browser's ability to translate XML into HTML tables.


Problem

How can you render incoming XML and retain the data?


Forces

  • Many Ajaxian applications receive XML Messages and have to convert them into HTML.
  • The incoming data often has to be retained as well.


Solution

Retain XML responses as "XML Data Islands", nodes within the HTML DOM. Strictly speaking, an XML Data Island is an XML document embedded in a standard XHMTL document, usually within an <xml> tag. The initial page looks like this:

  <html>
    <head>
      ...
    </head>
    <body>
      <h1>Top Score</h1>
      <p>Here's the ... </p>
      ...
      <xml id="scoreData"></xml>
    </body>
  </html>

After an XMLHttpRequest Call brings the browser an XML Message, the message is retained in the tag, e.g. by setting the scoreData element's innerHTML property. The HTML DOM now includes the full XML.

  <html>
    <head>
      ...
    </head>
    <body>
      <h1>Top Scores</h1>
      <p>Here's the ... </p>
      ...
      <xml id="scoreData">
        <score>
          <title>Galaga"</title>
          <player>AAA</player>
          <score>999610</score>
        <score>
      </xml>
    </body>
  </html>

In a more general sense, this pattern involves retaining XML Messages in one form or another. While the DOM is convenient, and has some value-add described below, you could also save the XML in a normal Javascript variable. The key characteristic of the pattern is that you're retaining the XML Message and using it as a data structure, rather than transforming it into a custom Javascript object.

It's easy enough to do this, but what's the point? Here are three applications:

  • Transforming XML Data Islands to and from HTML. (Note: this is browser-specific.)
  • Retaining XML for later use.
  • Including an XML document on initial page load.

Transforming XML Data Islands to and from HTML. XML Data Islands are traditionally an IE-specific capability. From IE5, you can tie HTML controls to an embedded XML document. When the XML data changes, the HTML is also updated. And when the HTML changes - if the control is editable - the XML is updated. In IE, to tie an HTML element to a data island, you indicate the XML data island, preceded by a # and the field within that island. So to create an input field based on the player field above:

  <input type="text" datasrc="#scoreData" datafld="player">

Now, this is an IE-specific function, but Firefox has its own alternative: eXtensible Binding Language. The idea is similar, but the updating behaviour isn't automatic. With Mozilla, you have to create an XBL document that explicitly states how HTML controls relate to the XML.

Even without these browser-specific capabilities, it's still fairly straightforward to make the transformation using a technology like Browser-Side XSLT.

Retaining XML for Later Use. Sometimes, it's useful to retain the response for later use. For example, you can keep it to build up a Browser-Side Cache. Another application is for validation - a response might contain setup information for a form, and once that's been entered, the response data can also be used for browser-side validation.

To store a response for later use, you could wrap it into a custom data structure. But that requires some coding effort and also complicates things a bit by adding a new data structure. When the response is an XML Message, you have an alternative: just keep the XML. While it may not be the optimal format, it's still a structured format which you can query quite easily.

Including an XML Document on Initial Page Load: Sometimes, the initial page load sequence requires an XML document. For example, the XML document might contain the inital data to be viewed. You could go through the motions of extracting it with an XMLHttpRequest Call, but it would be faster to load the XML as part of the initial page load. An XML Data Island is an easy way to do this: just output the XML content wrapped inside an <xml> tag. Alternatively, IE lets you specify a URL in the src attribute.


Decisions


Real-World Examples

Production grade application completely built using xml data islands and client side xml/xslt transformations can be found on Losru. This advanced data management system currently performs client side transformations for IE and server side transformations for other browsers. To find more about used technology visit Webutilis

PerfectXML Demo

Darshan Singh's IE demo is explained in the corresponding PerfectXML article. It's a straightforward table, populated by an XML Data Island embedded in the corresponding HTML. The demo only works in IE.


Mozilla.org Demo

Thad Hoffman's Mozilla demo is explained in a corresponding mozilla.org article. It simulates IE's behaviour, using standard XML parsing in Javascript to convert XML to HTML. This demo only works in Mozilla or Firefox.

TechRepublic Demo

Philip Perkin's example explains how to use Mozilla's answer to XML Data Islands, eXtensible Binding Language. The code's online and there's a demo available for TechRepublic members.


Code Examples


Refactoring Illustration

XML Data Island Sum Demo

This example adds a very simple caching mechanism to the Basic Sum Demo. The most recent XML response is retained as an XML Data Island, so if the user tries to resubmit the query, no server call occurs. In the absence of an XML Data Island, the script would need to retain the call and response in a custom data format. But retaining it as XML means no data format has to be created. Also, the Interactive Website Framework (IWF) is used to ease navigation through the XML document.

Some minor changes are made to the XML format for easier parsing, leading to the following data format:

  <sum>
    <inputs>
      <figure1>4</figure1>
      <figure2>6</figure2>
      <figure3></figure3>
    </inputs>
    <outputs>10</outputs>
  </sum>

To the intial HTML, a placeholder has been introduced to retain the most recent XML response - the XML Data Island.

 <xml id="sumResponse"></xml>

The xml is retrieved as a plain-text document and IWF used to transform it into a special DOM-like format for convenient parsing. The IWF document is interrogated to get the sum, which is injected onto the DOM status element as before. Finally, the XML Data Island is populated with the XML response, in its plain-text format (as opposed to a DOM object). The XML response includes the input figures as well as the resulting sum, so we'll be able to use it later on to decide if the figures have changed since the last response.

 function onSumResponse(xml, headers, callingContext) {
   var doc = new iwfXmlDoc(xml);
   $("sum").innerHTML = doc.sum.outputs[0].getText()
   $("sumResponse").innerHTML = xml;
 }

The XML Data Island is used to decide whether a call is necessary. To make the effect more visible, the status area is blanked as soon as the user clicks submit. It's re-populated with the retained value if it turns out the current data was the same as the previous query.

  function submitSum() {
    $("sum").innerHTML = "---";
    var figures = {
      figure1: $("figure1").value,
      figure2: $("figure2").value,
      figure3: $("figure3").value
    }
    var sumResponseXML = $("sumResponse").innerHTML;
    if (sumResponseXML!="") {
      doc = new iwfXmlDoc(sumResponseXML);
      var alreadyStoredInDOM = (
           figures.figure1 == doc.sum.inputs[0].figure1[0].getText()
        && figures.figure2 == doc.sum.inputs[0].figure2[0].getText()
        && figures.figure3 == doc.sum.inputs[0].figure3[0].getText()
      );
      if (alreadyStoredInDOM) {
        // No need to fetch - just retrieve the sum from the DOM
        $("sum").innerHTML = doc.sum.outputs[0].getText()
        return;
      }
    }
    ajaxCaller.get("sumXML.phtml", figures, onSumResponse, false, null);
  }


Alternatives

Browser-Side XSLT

Browser-Side XSLT is a more general way to transform XML into HTML. Also, you can store an XSLT stylesheet as an XML Data Island within the initial page content.

Browser-Side Templating

Browser-Side Templating is a general technique for convert XML, or other data formats, into HTML.


Related Patterns

Browser-Side Cache

XML Data Island can be used to store a Browser-Side Cache.


Want to Know More?