Introducing E4X
by Kurt Cagle
|
Pages: 1, 2, 3, 4
In this particular example, when the document initially loads, it asynchronously retrieves the atom feed from the server via the populate() function using an XMLHttpRequest call. The goal here is to minimize the amount of processing of the feed as a DOM, so here that process is handled by using the http.responseText method to get the feed as text. The Mozilla E4X implementation has a few serious limitations, one of the biggest of which is its inability to parse XML declarations that start with <? and end with ?>. Thus, it is necessary to run a quick regular expression to remove all of these:
var data = data.replace(/<\?(.*?)\?>/g,"")
Namespaces in E4X are something of a headache, for much the same reason that they are a headache in XML in general. However, it is possible to change the default namespace and work within the context of that namespace without needing to create a formal namespace declaration or use prefixes. In order to retrieve the feeds from the relevant returned document (which includes various HTTP request and response headers as part of the package), the default namespace was set to Atom as "http://www.w3.org/2005/Atom":
default xml namespace="http://www.w3.org/2005/Atom";
var feed = new XML(data);
Once so declared, it becomes possible to switch back and forth between then Atom namespace and the XHTML namespace, jumping from reading data appropriate to each entry to making new option elements for that entry:
for each (entry in feed..entry){
default xml namespace="http://www.w3.org/2005/Atom";
var title = entry.title.toString();
var id = entry.id;
default xml namespace="";
var option = <option value={id}>Introducing E4X</option>.toXMLString();
selectNode.innerHTML += option;
}
Note the use of the toString() and toXMLString() methods. E4X exposes a limited set of methods on E4X XML() and XMLList() objects (you don't have the same ability to assign methods to E4X objects that you do with ordinary objects for this reason). A reference such as entry.title actually returns an XML node; if this is used as part of a string expression then the JavaScript engine will automatically recast the node to its text value, but sometimes it is better to make this explicit via the toString() method (you could also do ""+entry.title to do the casting, but that operation isn't always obvious when looking at code). Similarly, the toXMLString() method will serialize an XML() node as XML content, while applying toXMLString() to an XMLList() object will return a serialized collection of nodes.
The mapping to the default namespace prior to the option will set the namespace to the namespace of the containing object, which in this case is the <select> node, if passed to the innerHTML property.
One of the more useful aspects of JavaScript as a language is the use of closures, in which variables that are defined at one point, then used within a function defined in the context of those variables, will continue to hold the values previously assigned so long as the function remains in scope.
This is used to good effect in the internally defined selectFeed() function. The feed is referenced within the function, as well as displayNode and linkNode, which defines the display area for a selected entry's content and a button for launching the original page in a second window. One interesting consequence of this is that because the selectFeed() function is then assigned at that point to the selection box listing the titles, the feed itself remains in memory, but is completely inaccessible to anything beyond the selectFeed() function. Admittedly, in this case it doesn't make that much difference (determining the feed is relatively simple), but from a security standpoint this provides a layer of protection on potentially sensitive information.
var selectFeed = function(){
default xml namespace="http://www.w3.org/2005/Atom";
var entry = feed..entry.(id==selectNode.value);
var link = entry.link.(@rel=='alternate').@href.toString();
var content = '<div xmlns="http://www.w3.org/1999/xhtml"><h2>'+
entry.title+'</h2>'+entry.content.text().toString()+'</div>';
var content= content.replace(/<\?(.*?)\?>/g,"")
default xml namespace="http://www.w3.org/1999/xhtml";
displayNode.innerHTML = content;
linkNode.setAttribute("href",link);
};
selectNode.addEventListener("change",selectFeed,false);
I wanted to include the link to the source not only because it's a logical piece of a feed viewer, but because it's useful to illustrate an attribute filter in E4X. In Atom, a given entry may have more than one link associated with that entry. The rel="alternate" link is typically the one that contains a reference to the relevant web page that the resource came from initially (and as such there is always only one such alternate link). The expression entry.link.(@rel=='alternate').@href thus retrieves from the link collection the link for which the @rel (relationship) tag is set to "alternate". The expression within the parentheses here is (more or less) JavaScript; the @rel retrieves the rel attribute relative to the link collection and compares it to the string 'alternate' (note the double equal signs). This is a filter, just as var entry = feed..entry.(id==selectNode.value); in the previous line is a filter.
A screenshot of the "app" is shown in Figure 1.

Figure 1. Metaweb Screenshot
At the end of this method you have the expression linkNode.setAttribute("href",link). This is a DOM statement, because linkNode is a DOM element, not an E4X element. At this stage, while one of the main goals of the E4X process was to create a simpler, more efficient way of working with document objects, this has not been realized in any significant way.
By the way, it is possible to convert an E4X object into a DOM tree and vice versa, though these are comparatively expensive operations. The function eNode2dNode performs the conversion one way, converting an E4X object into the root node of its own DOM-based document, while dNode2eNode makes the conversion in the other direction:
var eNode2dNode = function(eNode){
var str = eNode.toXMLString();
var doc = (new DOMParser()).parseFromString(str,"text/xml");
return doc.documentElement.cloneNode(true);
}
var dNode2eNode = function(dNode){
var str = (new XMLSerializer()).serializeToString(dNode);
var eNode = new XML(str);
return eNode;
}
E4X and JSON
It is not my wish to deprecate the importance or value of JSON in this article (well, not much anyway). JSON represents a minimally sufficient platform for information interchange within most browsers, and as such realistically will be around for quite some time (especially as Microsoft's Internet Explorer does not look like it will be adopting the most recent JavaScript changes any time soon).
However, it's worth noting that a lightweight XML protocol, LINQ, likely will be migrating to IE with its next release. While differing somewhat in syntax from E4X (and having a considerably broader role), LINQ will most likely be doing much the same duty in IE that E4X does in Firefox and Flash—providing a way of using XML easily and cleanly without having to use the rather cumbersome mechanism of DOM. Given the increasing dominance of XML as a messaging and transport protocol on the server and between server and client, the use of LINQ does open up the notion that you can take advantage of the rich characteristics that XML has to offer without having to complexify your code with DOM manipulation.
At a minimum, if you are specifically targeting the frameworks where E4X is supported, you should take some time to investigate the technology, especially when dealing with the increasingly syndicated nature of web technologies. Combining E4X and Atom, for instance, opens up all kinds of interesting potential usages, especially given the increasing role that Atom is playing as a data transport protocol for companies such as Google. While it is possible that you'll see more companies exposing JSON services, I personally see XML-based Atom services growing far faster, and in that case the use of a native XML datatype just cannot be beat.
Kurt Cagle is an author, research analyst with Burton Group, technology evangelist, information architect, and software developer specializing in web technologies. He is the webmaster for XForms.org. He lives in Victoria, British Columbia, where he's working on the open source x2o data server.
2010-07-06 04:24:31 bathroom furniture- #1 Carpet Rugs Upholstery Cleaning West Los Angeles 1-310-925-1720
2009-06-11 15:00:55 whats - you're fired
2008-02-26 03:51:43 jemptymethod - Errors
2007-12-17 10:22:56 altjeringa - Array programming
2007-11-30 13:32:40 iconara - Array programming
2007-12-01 10:39:36 Kurt Cagle - Arrr
2007-11-30 13:07:23 iconara - Prediction: It won't last
2007-11-30 12:40:42 shogun70 - Prediction: It won't last
2007-11-30 16:55:04 Dan Sickles - Prediction: It won't last
2007-12-01 10:52:35 Kurt Cagle - Safari 3.0 {E4X & XQuery}
2007-12-18 16:18:47 frederick.c.lee