technology from back to front

E4X: I want my S-expressions back

E4X is a new ECMA standard (ECMA-357) specifying an extension to ECMAScript for streamlining work with XML documents.

It adds objects representing XML to ECMAScript, and extends the syntax to allow literal XML fragments to appear in code. It also supports a very XPath-like notation for use in extracting data from XML objects. So far, so good – all these things are somewhat useful. However, there are serious problems with the design of the extension.

If E4X objects were real objects, if there were a means of splicing a sequence of child nodes into XML literal syntax, and if E4X supported XML namespace prefixes properly, most of my objections would be dealt with. As it stands, the overall verdict is “clunky at best”.

These are my main complaints:

* It doesn’t do anything like Scheme’s unquote-splicing, and so using E4X to produce XML objects is verbose, error-prone and dangerous in concurrent settings.

There seems to be no way of splicing in a sequence of items – I’d like to do something like the following:

  function buildItems() {
   return [<item>Hello</item>,
           <item>World!</item>];
   }
   var doc = <mydocument>{buildItems()}</mydocument>;
  

and have doc contain

   <mydocument>
   <item>Hello</item>
    <item>World!</item>
 </mydocument>
  

What actually results is the more-or-less useless

  <mydocument>Hello,World!</mydocument>
  

The closest I can get to the result I’m after is

   function buildItems(n) {
      n.mydocument += <item>Hello</item>;
   n.mydocument += <item>World!</item>;
    }
   var doc = <mydocument></mydocument>;
  buildItems(doc);
  

* It’s full of redundant redundancy – it’s as verbose as XML, when you can do so much better.

* There’s no toXML() method (or similar) for use in papering over the yawning chasm between the XML objects and the rest of the language: you can’t even make a Javascript object able to seamlessly render itself to XML.

* The new types E4X introduces aren’t even proper objects – they’re a whole new class of primitive datum!

* Because they’re not proper objects, you can’t extend the system. You ought to be able to implement to an interface and benefit from the language’s XPath searching and filtering operations. E4X is so close to offering a comprehension facility for Javascript, but it’s been short-sightedly restricted to a single class of non-extensible primitives.

* You can’t even construct XML tags programmatically! If the name of the tag doesn’t appear literally in your Javascript code, you’re out of luck (unless you resort to eval…) [[Update: I was wrong about this - you can write <{expr}> and have the result of evaluating expr substituted into the tag.]]

* E4X XML objects have no notion of namespace prefixes (which are required for quality implementations of XPath and anything to do with XML signatures). Prefixes only turn up in the API as a means of producing (namespaceURI,localname) pairs. This is actually how it should be, but because there’s already broken software out there
that depends on prefix support, by not supporting prefixes properly you preclude ECMAScript+E4X from being used for XML signatures or ECMAScript-native XPath implementations.

In my opinion, E4X violates several programming language design principles: most importantly, those of regularity, simplicity and orthogonality, but also preservation of information, automation and structure. SXML, perhaps in combination with eager comprehensions, provides a far superior model for producing and consuming XML. Sadly, there’s no real alternative for ECMAScript yet – we’re limited either to library extensions, or to using the DOM without any syntactic or library support at all.

by
tonyg
on
24/06/06
  1. It’s also frustrating that you can’t take an E4X node and insert it directly into the browser DOM.

    There is no ‘toHTML’ which prevents the use of E4X for dynamically generating valid HTML – you have to stick with XHTML. Unfortunately some browsers require things like ‘SCRIPT’ tags to have a closing tag rather than the shortcut method. ie. They need not . E4X is incapable of handling this and is non extensible for generating your own output methods.

    As an s-expression style approach I tend to use code like this:

    http://mg.to/2006/02/27/easy-dom-creation-for-jquery-and-prototype

    Chris.

  2. Thanks for the link, Chris – something similar had occurred to me, too (both the SXML and Seaside HTML canvas approaches should translate to Javascript pretty well), but I haven’t had a chance to explore the design space properly yet.

    As it happens, I got into experimenting with E4X through hacking a Seaside-a-like onto your server-side javascript [http://www.bluishcoder.co.nz/2006/05/server-side-javascript.html] implementation. I’ll post about that soon :-)

  3. Nice! I look forward to seeing what you’ve done :)

  4. As it happens, I was wrong about the lack of computed tags:

    js> var y = 'sometag';
    js> (<{y}/>).toXMLString();
    <sometag/>
  5. Second embarrassing update: If I’d used an XMLList instead of an array, my buildItems() would have worked just as I intended:

    function buildItems() {
      return <><item>Hello</item>
               <item>World!</item></>;
    }
    var doc = <mydocument>{buildItems()}</mydocument>;
  6. Prestaul
    on 17/09/08 at 10:11 pm

    I think that this article was a badly researched, knee-jerk reaction. This works:

    function buildItems() {
      return &lt;&gt;
        Hello
        World!
      ;
    }
    var doc = {buildItems()};

    So does this:

    function buildItems() {
      var list = &lt;&gt;; // or: new XMLList()
        list += Hello;
        list += World!;
      return list;
    }
    var doc = {buildItems()};

 
 


6 + nine =

2000-14 LShift Ltd, 1st Floor, Hoxton Point, 6 Rufus Street, London, N1 6PE, UK+44 (0)20 7729 7060   Contact us