devxlogo

Simplify Your Apps with the XML Binding Language 2.0

Simplify Your Apps with the XML Binding Language 2.0

s web applications replace web pages on the Internet, there are a number of approaches that are being taken to add new functionality to these sites. One approach, the one perhaps most heavily used by applications, is programmatically controlling different parts of a web page via scripts and user events. In most cases, this process creates some form of binding on elements after the fact, which can often lead to fairly messy java-script code both in terms of long blocks of scripts and inline event handlers calling those java-script functions.

However, there’s another approach that may have the potential to both simplify your applications and contribute significantly to reuse. The idea behind it is deceptively simple: in a web page’s CSS page, you define what’s called a behavior, a script that binds to a given behavior language document written in mixed XML and java-script called the XML Binding Language (XBL). Once the page loads, any element that’s associated with that particular rule will gain the behavior, essentially acting as a new “element” with its own presentation, its own responses to user input, and its own underlying data.

XBL has been floating around in various incarnations since the early 2000s. Microsoft created a type of binding called behaviors in the late 1990s, but the technology never really caught on with other browsers. In early 2003, XBL was introduced in Firefox as one way of building extensions using the XML User-interface Language (XUL), though XBL wasn’t formally specified as a standard outside of Firefox. XBL bindings have worked in Firefox web pages almost from the inception of the browser, but again, other vendors didn’t follow suit.

In 2006, Ian Hickson of Google published the first version of the XBL 2.0 specification as part of the W3C Web Application Formats Working Group, based in part upon the Mozilla XBL 1.0 language but aimed towards rectifying a number of the design issues that tended to cause problems with the Firefox implementation. XBL 2.0 has been a candidate recommendation since 16 March 2007, but has been waiting for the required two formal implementations of XBL 2 to be submitted that are considered a necessary precondition for a working draft to become a formal recommendation (typically after a short “Proposed” status for final comments).

Mozilla announced in 2008 that they were looking to have an XBL 2 version likely with their 4.0 release … this effort is underway now, and it’s very likely that they will achieve this goal, especially with a formal candidate recommendation status that’s unlikely to change its underlying functionality.

Google, for it’s part, took an alternative route that’s similar to the approach they took recently with the SVG Web project. Rather than waiting for other browser vendors to adopt XBL 2, they’ve recently created a java-script based XBL2 code project at http://code.google.com/p/xbl/, with the code designed in such a way that it will work across any browser. Currently it supports all major browser versions produced within the last four years. While it doesn’t completely mitigate the requirement for scripting, implementing it within your web page only requires the addition of a single script element in the header of the document:

[xml][/xml]

Once included, any behaviors that are defined within the CSS stylesheet will be invoked, regardless of browser. Additionally, the xbl.js library (available from the project site above) also performs a check before calling the library to see if XBL2 support is enabled natively. If it is, then the code will defer to the (presumably browser optimized) XBL library that’s native to that platform.

Declaring a Twitter XBL Element

An interesting exercise, echoing something I’ve done previously on this site, is to build a mechanism that would take Twitter feeds and display the most recent messages in a person’s “friends” channel within a website. This isn’t a pure client solution: it assumes that there is a proxy on the same server as supplies the initial web page that communicates with twitter and passes a JSON stream back to the client. However, the XBL component handles the presentation and updating of this information.

A typical web page that uses XBL can often seem remarkably clean and straightforward. In the case of the Twitter app, for instance, the code would look as follows:

            Twitter Test                       ...      ...      ...   

The element is run prior to instantiation of any of the bindings (and the results are available to all bindings), and as such often contains references for libraries such as jQuery. The java-script that this supports can either be placed inline or could be specified as a distinct file referenced by the [xml]@src[/xml] attribute. In the case of twitter.xml, no script is needed (it's typically not, unless you need specialized libraries).

The element holds HTML markup code that will be visually substituted for (or more properly contained by) the existing bound tag and its descendants. In essence, describes the markup "bones" of the component. Not all XBL bindings need specific hard coded template implementations, though most do. In the case of the Twitter component, the structure describes the various core pieces, though without the rows of Twitter data (this is generated in the implementation section. See Listing 1).

Identifiers (ids) are in scope only to the containing binding, not the overall document. This means that you can't retrieve something like the

using document.getElementById('interval') -- as #interval is effectively non-existent within the containing document's scope. There are a number of advantages to this approach, not least of which being that you can have multiple bindings on the same page with the same internal ids without namespace collision, something that was a major problem with the Mozilla XBL 1.0 version.

If the template provides the bones, the implementation provides the muscle and brains. The element holds java-script, though this typically is specified as a JSON object that is then associated with the specific target or bound element. This is essentially the code "interface" for the object. In the case of the twitter binding, this is fairly exhaustive (see Listing 2).

In this particular case, the xblBindingAttached method is invoked whenever the binding is "attached" to the element in question, and is almost always used for initialization. Similarly, the xblBindingDetached method is invoked just prior to the binding connection being removed (such as through some form of CSS class manipulation), and typically is used for cleaning up the associated changes.

In order for a binding to work, a temporary HTML tree is built and kept under the control of the XBL binding code. This tree -- called a shadowTree, holds the actual working copy of the bindings document object model (or DOM), and is a property of the bound element. In order to retrieve elements within the shadowTree, this, rather than document, should be the root class for getElementByID, such as in the line:

this.shadowTree.getElementById('feedbutton').addEventListener('click', this.getFeed, false);

which retrieves the feedbutton object.

The boundElement property is manually associated here with the this object pointer, in order to make it more evident what object is being referenced (especially as this can have different values within different contexts.

The getFeed() function, on the other hand, is specifically assigned as the handler when the feed button is depressed, and does the bulk of the real work within the binding. It retrieves the username and password for a given Twitter account, then performs an XMLHttpRequest in order to get the feed as a JSON object. The request is made to a server proxy (written in XQuery below, though it could be written in any language) that actually pulls the twitter feed from Twitter.com then passes it on to the client on the same server that the Twitter.xhtml page came from. While there are some implementations of the newer cross-domain XMLHttpRequest() calls, the technology is still new enough that it's not yet widely adopted -- thus the use of a proxy server.

Once retrieved as JSON and converted into an array of status messages known informally as "tweets", the getFeed() function iterates through the set and retrieves the tweet.id property, then compares this with the existing panes in the Twitter panel table. If the id matches an existing object, the new tweet is dropped, but if not, it's added to the top of the tweet stack, pushing old messages down. From there, the text is cleaned up (the incoming stream is not always HTML friendly, especially with regard to ampersands and related constructs), and images, names and text are all packaged together into a tweet to be displayed.

Bindings can be difficult to work with when dealing with asynchronous invocations of methods -- such as timeouts and other threaded events, so closures can be useful to pass relevant contexts to the appropriate handlers. In this case, once getFeed() is called, it also invokes a setTimeout call which invokes the method again after an interval specified by the @interval attribute, defaulting to thirty seconds. If @interval is set to 0, this will turn off the update capability by bypassing this call.

The section provides generalized event handlers for the XBL binding overall. While there are none specified in the example, a typical set of XBL handler might look something like the following:

          this.activate();          this.activate();          if (event.target == this.boundElement)      this.boundElement.ownerDocument.location.href = this.href;       ...   

In general, such event handlers are wrappers around the relevant java-script handler scripts. Note as well that these are relevant only to the domain within the binding, not the larger document.

Resources cover both the use of stylesheets and external media resources (images, sounds, video, etc.) that may be used by the binding itself. In the case of the Twitter component, the stylesheet for controlling the component is expressed inline as:

   

The same stylesheet could also be referenced as an external file via the [xml]@src[/xml] attribute.

   

The

element (also part of [tt]) performs a preload of media resources for assignment to or similar HTML (or related) elements. By preloading, you can assure that the images are automatically loaded in before the binding initially renders. The syntax is straightforward:

   

with a required src and option id. The W3C specification for XBL2 provides a sample of how such resources would be prefetched and referenced:

                   ({      red: function() {        this.shadowTree.getElementById('l').src = 'red.png';      },      green: function() {        this.shadowTree.getElementById('l').src = 'green.png';      },   })   

The full XBL document for the Twitter binding is contained in Twitter.xml (see Listing 3).

Generating the Data Stream

As mentioned previously, because of the cross-browser and cross-domain issues, in general it is better to make use of a server proxy to pull in the relevant Twitter streams. While there are a number of different potential implementations for such a stream, I laid it upon myself as a challenge to create such a proxy stream for an XML REST-based Database, in this case the eXist-db server, both because the application I was developing was based on it and because I was trying to figure out how to proxy a JSON stream.

The xquery to build such a stream was pretty straightforward (and corresponds to how one would do it in a language such as Ruby or PHP):

declare namespace httpclient = "http://exist-db.org/xquery/httpclient";declare option exist:serialize "method=text mediatype=text/plain";let $username := request:get-parameter("username","")let $password := request:get-parameter("password","")let $auth := concat("Basic ",util:string-to-binary(concat($username,":",$password)))let $results := httpclient:get(     xs:anyURI("http://twitter.com/statuses/friends_timeline.json"),     false(),             
    
)let $tweets := util:binary-to-string($results)return $tweets

In this case, the username and passwod were retrieved from the relevant query string parameters, then were munged together into a basic authentication string to be used as a header. The routine util:string-to-binary() converts a text string to Base 64 Binary (which is used to encode binary content over the web). http-client:get() then invoked a GET command over HTTP (much as you would with the XMLHttpRequest object), with the result returned as a binary representation that then needs to be converted back into a JSON string with util:binary-to-string(). This is then returned to the output of the call. Then,

http://localhost:8080/rest/twitter/twitter.xq?username=kurt_cagle&password=mypassword

would invoke the XQuery routine and retrieve the relevant Twitter friends stream. This could be extended to other user streams as well just by changing the Twitter URL.

Tying Up Bindings

It's hard to say whether Google's XBL2 implementation will really catch on, although it has a number of factors going for it. The code is remarkably cross platform - it works on all contemporary browsers with the possible exception of Konquerer. That doesn't necessarily mean that java-script code written within the bindings will satisfy that same restriction, of course, but having the framework in place can go a long way to making such code browser independent.

Bindings make for cleaner layout and code and encourages componentization at the browser level, which in turn promotes code reuse and the development of core libraries. Because of the encapsulation involved, you don't generally have to worry about id or namespace collisions at the scripting or styling level, which reduces the likelihood that such code won't work because a given id happens to be a core one in the base scripting library. It also makes it much easier to test component development in isolation without having to worry about dependencies within a given web page causing spurious debugging results.

Overall, it may very well be that XBL's time is just now arriving. With the stabilizing of the AJAX space, and the resources of a company like Google behind it, XML as a binding language has a great deal to offer and very little downside.

devx-admin

Share the Post: