Section 11.2. Browser-Side XSLT


11.2. Browser-Side XSLT

Presentation, Render, Style, Stylesheet, Transform, View, XML, XPath, XSLT

Figure 11-3. Browser-Side XSLT


11.2.1. Developer Story

Dave has just received a request to change the weather portlet on the homepage. The image must now be on the bottom, not the top, and the wording should be more precise. The browser receives periodic weather updates in the form of an XML specification, and it uses Browser-Side XSLT to get HTML for the portlet. The stylesheet is embedded inside the static homepage HTML file. So Dave just has to tweak the XSLT to get all the browsers rendering the new design.

11.2.2. Problem

How can you render incoming XML?

11.2.3. Forces

  • Many Web Services (Chapter 6) output XML Messages (Chapter 9), and Ajax clients have to convert them into HTML.

  • While modern browsers provide good support for XML parsing via the JavaScript's DOM support, the direct interface is lengthy and tedious to use.

  • Code gets complex and error-prone when you mix HTML generation with application logic. JavaScript is not well-suited to programmatically building up HTML strings from input XML.

11.2.4. Solution

Apply XSLT to convert XML Messages into XHTML. XSLTExtensible Stylesheet Language Transformations (http://www.w3.org/TR/xslt)is a language for transforming XML documents into other forms. Here, XML is transformed to XHTML, a type of HTML that conforms to the XML standard. (You could get away with converting to plain-old HTML, but things works better if you stick to XHTML.) XSLT is fairly well-supported in modern browsers and, although browser APIs vary, there are good cross-browser toolkits available.

XSLT is well-suited to rendering XML. An XML document is designed to encapsulate a data object, and an XSLT stylesheet is a strategy for presenting such objects. Previously, XSLT has been used as a server-side technologythe server grabs some XML from a repository or another process and creates a web page by transforming it into XHTML. All that happens on the server. More recently, browsers have incorporated XSLT functionality, so the browser can automatically create an HTML page by marrying together an XML document with an XSLT stylesheet.

Browser-Side XSLT is slightly different. Here, the XML document does not constitute the contents of the entire page, but it does constitute a response from an XMLHttpRequest Call (Chapter 6). The transformation to XHTML can take advantage of the browser's built-in XSLT support, or alternatively an XSLT processor can be implemented in JavaScript, building on the browser's more primitive XML features. However the XSLT occurs, you're unlikely to be implementing it yourself. There are a couple of good cross-browser libraries available, discussed in later in this chapter in "Real-World Examples."

It's beyond the scope of this pattern to explain XSLT in any detail; however, here's a quick overview:

  • An XSLT stylesheet is itself an XML document.

  • An XSLT processor transforms an XML document into another form, by parsing the original document and using the stylesheet as the transformation strategy.

  • XSLT expressions are specified in another language, XPath. Among its capabilities, XPath provides a powerful mechanism for expressing a position within an XML document. For example, the XPath expression /category/items/category will match twice when the following document is processed:

       <category>     <items>       <category name="popular">         <!-- XPath expression matches this category node -->         ...       </category>       <category name="extras">         <!-- XPath expression matches this category node -->         ...       </category>     </items>   </category> 

  • A stylesheet is composed of rules. Each rule has a pattern that defines when it applies, and a template that dictates what will be output each time the pattern is encountered. Continuing with the example, here's a full rule:

       <xsl:template match="/category/items/category">       <div              onclick="retrieveCategory('{@name}')">             <xsl:value-of select="@name"/>       </div>   </xsl:template> 

    When each node is reached, the template is outputted. @name refers to the name attribute on the category tag. So when the processing engine reaches the following XML segment:

       <category name="extras"> 

    the following XHTML will be output:

       <div         onclick="retrieveCategory('{extras}')">        <xsl:value-of select="extras"/>   </div> 

This discussion has focused on the most obvious application of Browser-Side XSLT: conversion to HTML for display to the user. You can also convert the XML to JavaScript too, and then execute it with the eval( ) method. For example, it would be possible to build a native JavaScript object by converting some XML into some code that creates the object.

11.2.5. Decisions

11.2.5.1. How will you obtain the XSLT stylesheet?

Any Browser-Side XSLT processor requires two things:

  • An XML document

  • An XSLT stylesheet

Both are usually passed in to the XSLT processor as plain strings representing the entire document (as opposed to URLs, say). The XML document usually comes from an XMLHttpRequest Call (Chapter 6), but where does the XSLT stylesheet come from? You have a few options.


Store the stylesheet server side

You can hold the file server side, and then use an independent XMLHttpRequest Call (Chapter 6) to retrieve it. In this case, you'll probably want to keep the copy in a Browser-Side Cache for later use. Also, if you use an asynchronous call, which is advisable, there's a potential race condition: you need to ensure the stylesheet is retrieved before any transformation takes place, possibly with a loop that keeps checking for it. The later section "Code Refactoring: AjaxPatterns XSLT Drilldown Demo" demonstrates this approach.


Handcode the stylesheet as a JavaScript string

You can build up a string in JavaScript, though this leads to messy code that blurs the distinction between logic and presentation. There is one benefit of this approach: the stylesheet is dynamic, so could potentially vary according to the current context.


Store it inside the initial HTML document

You can tuck the stylesheet somewhere inside the initial HTML document where it won't be seen by the user. Techniques include:

  • Make it the content of an invisible textarea.

  • Store it in an XML Data Island the within document.

11.2.6. Real-World Examples

11.2.6.1. Google Maps

Google Maps (http://maps.google.com) is the most famous application of Browser-Side XSLT, where the technology is used to transform data such as addresses and coordinates into HTML. Based on this work, the Googlers have also released Google AJAXSLT (http://goog-ajaxslt.sourceforge.net), an open source framework for cross-browser XSLT and XPath.

11.2.6.2. Kupu

Kupu (http://kupu.oscom.org/demo/) is an online word processor (Figure 11-4) that stores content in XML and renders it with Browser-Side XSLT, using the Sarissa framework described shortly (Figure 11-4).

Figure 11-4. Kupu Word Processor


11.2.6.3. AJAX-S

Robert Nyman's AJAX-S (http://www.robertnyman.com/ajax-s/) is a slideshow manager, where raw content is maintained in XML, and transformed to slides using Browser-Side XSLT.

11.2.6.4. Sarissa framework

Sarissa (http://sarissa.sourceforge.net/doc/) is an open source, cross-browser framework for all things XML. XSLT is supported as well as XML parsing, XPath queries, and XMLHttpRequest invocation.

11.2.7. Code Refactoring: AjaxPatterns XSLT Drilldown Demo

This refactoring is similar to that performed in Browser-Side Templating but uses XSLT instead of templating. The starting point, the Basic Drilldown Demo (http://ajaxify.com/run/portal/drilldown), converts XML to HTML using a series of JavaScript string concatenations. The callback function, which receives the XML, therefore performs lots of string concatenations as follows:

   html+="<div id='categoryName'>" + categoryName + "</div>"; 

In this refactoring, all that string handling is replaced by an XSLT transformation using the Sarissa library (http://sarissa.sourceforge.net/doc/). One slight complication is the stylesheethow does the script access it? The solution here is to keep it as a separate file on the server and pull it down on page load:

   var xsltDoc;   window.onload = function( ) {     ...     ajaxCaller.getXML("./drilldown.xsl",function(response) {xsltDoc = response;});     ...   } 

As was mentioned earlier in "Decisions," there's a race condition here, because the XML response may come before the stylesheet. To deal with this, the drilldown callback function keeps looping until the stylesheet is defined:

   function onDrilldownResponse(xml) {     if (xsltDoc==null) {       setTimeout(function( ) { onDrilldownResponse(xml); }, 1000);       return;     }     ...   } 

Beyond that, the callback function is simply an invocation of Sarissa's XSLT processor:

   function onDrilldownResponse(xml) {     ...     var xsltProc  = new XSLTProcessor( );     xsltProc.importStylesheet(xsltDoc);     var htmlDoc = xsltProc.transformToDocument(xml);     var htmlString = Sarissa.serialize(htmlDoc);     $("drilldown").innerHTML = htmlString;   } 

The only thing left is the stylesheet itself, shown below. I'll spare a walkthrough. The output here is the same as that in the Basic Drilldown Demo (http://ajaxify.com/run/portal/drilldown), which generates the HTML using manual JavaScript processing.

   <?xml version="1.0"?>   <xsl:stylesheet version="1.0"                   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <xsl:template match="/">       <html>         <body>           <xsl:apply-templates/>         </body>       </html>     </xsl:template>     <xsl:template match="/category">       <div id='categoryName'><xsl:value-of select="@name" /></div>       <xsl:if test="@parent!=''">         <div id='parent' onclick='retrieveCategory("{@parent}")'>           Back to <xsl:value-of select="@parent" />         </div>       </xsl:if>       <xsl:apply-templates/>     </xsl:template>     <xsl:template match="/category/items/link">       <div ><a href="{url}"><xsl:value-of select= "name"/></a></div>     </xsl:template>     <xsl:template match="/category/items/category">         <div                onclick="retrieveCategory('{@name}')">               <xsl:value-of select="@name"/>         </div>     </xsl:template>   </xsl:stylesheet> 

11.2.8. Alternatives

11.2.8.1. Browser-Side Templating

Browser-Side Templating (see the next pattern) is a solution for rendering content in any formatplain-text, XML, and so on. You could extract key variables from an XML Message and render them with a templating engine. Browser-Side Templating is a simpler approach as it builds on existing JavaScript knowledge, while Browser-Side XSLT allows for more powerful transformations and avoids the cumbersome querying of XML in JavaScript.

11.2.9. Related Patterns

11.2.9.1. XML Message

Browser-Side XSLT is driven by the need to deal with incoming XML Messages (Chapter 9).

11.2.9.2. XML Data Island

Browser-Side XSLT can be used to render an element contained in an XML Data Island (see earlier). Also, XML Data Island is a good place to stick an XSLT stylesheet.

11.2.10. Metaphor

Browser-Side XSLT is a strategy for presenting abstract data in a human-readable form. People do this all the time with diagrams. For instance, a family tree is one way to render the abstract set of relationships in a family. A UML diagram is a visual representation of some (real or imagined) code.




Ajax Design Patterns
Ajax Design Patterns
ISBN: 0596101805
EAN: 2147483647
Year: 2007
Pages: 169

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net