e4x
ECMAScript for XML (E4X): Debunking an example
I'd never heard of E4X (ECMAScript for XML), an extension to ECMAScript (JavaScript) specifically for handling data encumbered by XML, before today. It was developed several years ago, has been adopted by Ecma and published in June 2004, and is apparently now implemented in Mozilla's products.
The article I stumbled across is titled Native XML Scripting in BEA WebLogic Workshop and offers an argument for the extension over using the standard JavaScript DOM bindings.
Looking at the example scripts the article presents it's clear the E4X notation is much cleaner and easier to work with; the DOM oriented function is horrible and full of tree maneuvering (why didn't they use a TreeWalker then?). Below is the short and sweet E4X function which completes the job outlined in the article.
// the E4X function
function toHTML (srcDoc) {
var destDoc = <html/>;
for (var atom in srcDoc..ATOM) {
var ptext = "";
for(var item in atom.children()) {
ptext += item + "\n";
}
destDoc[destDoc.length] = <P>{ptext}</P>;
}
return destDoc;
}
The same job can apparently be accomplished using the function below, this time using DOM API calls to crawl the trees and create a document.
// the original DOM function
public Document toHTML(Document srcDoc) throws Exception {
Document destDoc = srcDoc.getImplementation().createDocument("","HTML",null);
Node root = destDoc.getFirstChild();
Node node = srcDoc.getFirstChild().getFirstChild();
while (node != null) {
if (node.getNodeName().equals("ATOM")) {
Node pNode = destDoc.createElement("P");
root.appendChild(pNode);
Node tempNode = node.getFirstChild();
while (tempNode != null) {
if (tempNode.getNodeType() == Node.ELEMENT_NODE) {
Node n = tempNode.getFirstChild();
while (n != null) {
if (n.getNodeType() == Node.TEXT_NODE) {
Node tValue = destDoc.createTextNode(n.getNodeValue() + "\n");
pNode.appendChild(tValue);
}
n = n.getNextSibling();
}
}
tempNode = tempNode.getNextSibling();
}
}
node = node.getNextSibling();
}
return destDoc;
}
This code isn't JavaScript 1.5 (ECMAScript 3) and from the looks of it it's Java. Right away, this isn't comparing like with like, Java is much more verbose. Next the author has this to say about the example:
[T]he logic of the program is almost completely overwhelmed and obscured by tree navigation logic and DOM API calls. Consequently, creating, reading, and maintaining the code is tedious, time consuming and error prone. In addition, the DOM requires the programmer to learn and adopt a tree-based object model and a relatively extensive API for performing operations on this object model.
This is just plain unfair! The DOM example is very poorly written. Rewriting the function, using JavaScript so as to align the goal posts, I came out with this:
// my re-written DOM function
function toHtml(srcDoc) {
var destDoc = srcDoc.implementation.createDocument(null,"html",null);
var atoms = srcDoc.getElementsByTagName("ATOM"), atom;
for (var i = 0; (atom = atoms[i]); i++) {
var p = destDoc.createElement("p");
destDoc.documentElement.appendChild(p);
for (var j = 0, item; (item = atom.childNodes[j]); j++) {
if (item.nodeType == Node.ELEMENT_NODE)
p.textContent += item.textContent + "\n";
}
}
return destDoc;
}
Now this is almost the same as the E4X example. It only requires a tiny bit more work to mould it into a form using only the fragments of the DOM current browsers support. The function is only 3 lines longer and to someone who knows the syntax for both languages, equally as readable. The biggest advantage the DOM code holds, however, is that it will probably also be familiar to those who have used the DOM in other languages (say, Java!).
The E4X example also appears to use an abbreviated version of the for statement which allows iteration of an array with unpacking of each element in the statement (à la Python). If we were able to use this then my function would look like this:
function toHtml(srcDoc) {
var destDoc = srcDoc.implementation.createDocument(null,"html",null);
for (var atom in srcDoc.getElementsByTagName("ATOM")) {
var p = destDoc.createElement("p");
destDoc.documentElement.appendChild(p);
for (var item in atom.childNodes) {
if (item.nodeType == Node.ELEMENT_NODE)
p.textContent += item.textContent + "\n";
}
}
return destDoc;
}
So in terms of real difference, this function is really not any from that written using E4X. The harshly worded statement in the article is founded on false claims and really just serves to stengthen the case for the author's baby.
I'm not judging E4X here, this is a very simplistic use case, and I don't know much about the syntax, but to argue for it's adoption by producing a shoddy example for the opposition is not really fair. The DOM is not beautiful but neither is it ugly—at least give credit where credit is due.

2 Comments:
You're absolutely right about the comparison not being fair.
I attended a presentation today by Brendan Eich about E4X. What he presented there made it fairly clear to me that there's nothing really that makes it 'better' than standard JS, just more conveniant to handle XML. I haven't seen anything yet we couldn't do before.
I agree (not that it should matter to you! ;-).
E4X is about convenience. But convenience matters. Think about your car, your TV, your latest computer purchase. E4X is not going to cure cancer, but it is already making XML handling in Mozilla-based apps easier and more pleasant.
/be
Post a Comment
<< Home