XML Message - Ajax Patterns

XML Message

From Ajax Patterns

Evidence: 3/3

Tags: Document Format Hierarchical PlainOldXML POX Structured XML


Contents

Ajax/Javascript Programming and Usability in "Ajax Design Patterns" Book

In A Blink

Diagam Server talks (balloon).

  • Browser: "Tell me about the account balance."
  • Server: "<accountBalance><credit>3000000</credit><debt>1000000</debt><balance>2000000</balance></accountBalance>"


Goal Story

Dave is creating an Ajaxian search engine. The results are offered as a RESTful service, so that external developers can create their own interface. The results are presented as XML, and Dave's own search interface pulls it down with an XMLHttpRequest call, then transforms the result to HTML.


Problem

How can you transfer data between server and browser?


Forces

  • Many Ajaxian applications use semantic messages.
  • Both browser and the server must be able to access the message. That usually means the format must be easily accessed in Javascript as well as whichever server-side language is used.


Solution

Pass messages between server and browser in XML format. It's feasible to pass XML in both directions. On the server-side, it's a common way to expose structured data as text, and browser-side applications can download XML with an XMLHttpRequest Call and parse it in different ways. Where the browser needs to upload some complex data, it's fairly easy to serialise the data as XML and upload it in the body of an XMLHttpRequest Call.

XML is the definitive standard for data transfer across the industry, so just about any server-side development language has comprehensive support. The great advantage of XML over custom formats is the massive base of supporting frameworks, libraries, editors, and general tools. How you deal with XML on the server is language-specific, and a few choices are outlined in the Decisions below. However you do it, make sure the server presents XML content with the appropriate header to ensure its handled correctly by XMLHttpRequest:

 Content-type: text/xml

As the name implies, XMLHttpRequest was developed with XML transfer in mind. To retrieve an object with an XMLHttpRequest, you first point it to a URL known to serve XML.

 xReq.open("GET", "http://ajaxify.com/run/portal/drilldown/drilldown.phtml?categoryName=Overviews", true);

When XMLHttpRequest delivers a response, the response can be interpreted as XML or plain-text.

 var domObject = xReq.responseXML
 alert(domObject) // Outputs "[Object]" (IE)
                  // or "[object XML Document]" (Firefox)
 var xmlString = xReq.responsetText
 alert(xmlString) // Outputs the whole string
                  // i.e. "<category ...> ... </category>"

In most cases, you want to use responseXML because it gives you a well-structured DOM object: a hierarchical structure which can be navigated using industry-standard conventions. With recent browsers, you can rely on some basic parsing functionality to interrogate DOM objects. HowToCreate has a good list of DOM traversal functions and many of the Ajax Patterns demos perform such parsing (e.g. the Basic Wiki Demo).

If you're parsing XML, consider delegating to a cross-browser library. Sarissa, for example, has a variety of cross-browser XML manipulation routines. Another library, Interactive Website Framework, simplifies XML expressions. Instead of the following standard DOM query:

 var node = doc.documentElement.firstChild.firstChild.getAttribute("size");

You can write this:

 var node = doc.groceries.frozen[0].pizza[0].size;

With a DOM object representing server data, the browser can do one or more things (based on Semantic Message:

  • Transform the XML into some HTML. (See Decisions below.)
  • Interrogate it to decide what to do next.
  • Store it for later use in a XML Data Island.
  • Modify it based on client state and upload it again.

This discussion has mostly focused on downloading XML from server to browser. That's the most common direction, but XML can also flow upwards too. Sometimes, it's easier to upload complex data as an XML document than as a set of CGI-style variables. To do this with XMLHttpRequest, you simply pass in the whole XML string as the argument to send(). You'll also need to ensure the transport type is suitable, typically POST (or PUT).

 xReq.send(xmlString);

The XML string being sent usually represents browser state or user input. Most often, it's simply built up with some manual coding, appending strings together and including variables where appropriate. However, you can also use a library like Sarissa or Anders Noras's XmlSerializer to convert from a DOM object - or some other object - into an XML string.

Finally, a note of caution. "XML" is the X in "AJAX", so it's sometimes considered a core Ajax technology. And its association with XMLHttpRequest also strengthens the argument for XML Messages. However, don't let all this make you feel obligated to use XML Messages. XMLHttpRequest supports transfers in any plain-text format and it's fine to use Plain-Text Messages in many situations. XML is relatively simple, and there's good browser support, but sometimes it just doesn't fit the bill. The Solution for Plain-Text Message compares the two approaches in more detail.


Decisions

How will the server generate XML?

There are many ways the server might generate XML messages:

  • With custom code that hand-creates the XML string.
  • By building up a DOM object and serialising it.
  • Using a generic framework to convert standard data structures into XML.
  • Retrieving existing XML documents from the file system or external sources.

Will you specify a DTD or Schema?

When you pass XML Messages back and forth, each end must assume the same document format. That's a standard requirement with XML, and you can define the format precisely using a separate document: either a Document Type Definition or a stricter XML Schema document.

When the browser needs to render the message, how will it transform the XML?

The browser doesn't always need to render incoming XML messages - sometimes it just uses the data. But, for situations when it does render the XML, there are a few options. In all cases, the script is building up some HTML, which will then be injected onto a DOM element by setting its innerHMTL property to the HTML string.

  • Manual Javascript Conversion: For simple messages, you might find it easier to just perform a little parsing and manually create an HTML string.
  • XSLT: If you have the skill base and a suitable framework for the browsers you're targeting, Browser-Side XSLT allows for powerful conversion of XML.
  • Templating: Sometimes, Browser-Side Templating is a happy medium between the above two approaches. You still have to parse the XML document somehow, but the HTML generation is more straightforward.


Real-World Examples

Netflix Top 100

When you roll over a movie title in the Netflix Top 100, a balloon soon appears with summary details. What happens after the rollover is an XMLHttpRequest Call which receives movie details as follows.

  <MOVIES>
  <MOVIE ID="60031236" POS="17" DS="0">
    <TITLE>Kill Bill: Vol. 1</TITLE>
    <SYNOPSIS>In this film noir tale written ... </SYNOPSIS>
    <DETAILS RATED="R" RELYEAR="2003" GENREID="296" GENRENAME="Action & Adventure" />
    <STARRING>
      <PERSON ID="92495" NAME="Uma Thurman"/>
      <PERSON ID="20008295" NAME="Lucy Liu"/>
    </STARRING>
    <DIRECTOR>
      <PERSON ID="20001496" NAME="Quentin Tarantino"/>
    </DIRECTOR>
  </MOVIE>
  </MOVIES>

Protopage

Protopage is a portal-style application with excellent personalisation capabilities. Each time you change something on the page, a command is uploaded to the server via an XMLHttpRequest Call. For example, here's what the browser sent when I moved a Portlet around.

 <command accountId="25570" protopageId="25568" protopagePath="mahemoff" name="save-panel-geometry">
   <param name="id">129644</param>
   <param name="left">216</param>
   <param name="top">476</param>
   <param name="width">423</param>
   <param name="height">71</param>
   <param name="collapsed">false</param>
   <param name="zIndex">33</param>
   <param name="verticalScrollProportion">0</param>
 </command>

Google Maps

Google Maps is perhaps the most famous usage of XML Messages. Meta-information is downloaded as XML and rendered with Browser-Side XSLT.


Refactoring Illustration

The Basic Sum Demo uses a Plain-Text Message to transfer the sum result from server to browser. So if the browser sends a GET query requesting the sum of 4 and 8, the entire response is "12". That works fine, but sometimes we'd like a response to contain the original query too - it's convenient for caching, for instance (see Browser-Side Cache). If we're going to provide the original figures of the sum, the data's becoming a bit more complex - we now have a list as well as different types of data. To keep the format self-describing, let's refactor to XML.

The XML Sum Demo behaves the same as the original version, but the server-side returns results like this:

  <sum>
    <inputs>
      <figure id="1">4</figure>
      <figure id="2">8</figure>
      <figure id="3"></figure>
    </inputs>
    <outputs>12</outputs>
  </sum>

To avoid confusion, the server-side service is now called sumXML.php and reflecting the new location is the only change required to the browser call. The server-side service has been altered to output the full XML. Note the XML content-type declaration in the header, which is necessary for the XMLHttpRequest Call.

  <?php

    header("Content-Type: text/xml");

    $sum = $_GET["figure1"] + $_GET["figure2"] + $_GET["figure3"];

    echo <<< END_OF_FILE
  <sum>
    <inputs>
      <figure id="1">{$_GET["figure1"]}</figure>
      <figure id="2">{$_GET["figure2"]}</figure>
      <figure id="3">{$_GET["figure3"]}</figure>
    </inputs>
    <outputs>$sum</outputs>
  </sum>
  END_OF_FILE

  ?>

In this refactoring, the figures aren't used, but the sum is still required. The callback function therefore navigates through the response XML Message to obtain the sum figure.

 function onSumResponse(xml, headers, callingContext) {
   var sum = xml.getElementsByTagName("outputs")[0].firstChild.nodeValue;
   self.$("sum").innerHTML = sum;
 }


Alternatives

Plain-Text Message

As mentioned in the Solution, XML can often be overkill for simple messages, and Plain-Text Messages are worth considering as an alternative.

JSON Message

Just like XML Message, JSON Message is a suitable representation for data of various complexities. The Alternatives section of JSON Message compares the two formats.


Related Patterns

Semantic Response

A Semantic Response can often be expressed as an XML Message.


Want to Know More?

热转印机 有机玻璃 IBM服务器 Dell服务器 IBM服务器 HP服务器 CISCO交换机 IBM服务器 [1] 调查 单片机培训 顺义旅游 工控机 北京搬家 北京搬家 会议服务 装饰装潢 展览制作 北京装潢公司 北京装饰公司 北京装修公司 北京月嫂 顺义房产 门窗厂 代开发票  北京物流  北京搬家 门窗厂 北京保洁    [2] 代开发票 北京汽车陪练  空调维修 空调回收 大金中央空调 电地暖 冷库 格力中央空调 约克中央空调 风幕机 劳保用品  北京物流公司 机柜 机柜 电机修理 净化工程 五粮液酒 燃气灶维修