loading...

JavaScript – E4X: ECMAScript for XML

ECMAScript for XML, better known as E4X, is a standard
extension[22] to JavaScript that defines a number of powerful features
for processing XML documents. E4X is supported by Spidermonkey 1.5 and
Rhino 1.6. Because it is not widely supported by browser vendors, E4X
may perhaps be best considered a server-side technology for script
engines based on Spidermonkey or Rhino.

E4X represents an XML document (or an element or attribute of an
XML document) as an XML object and represents XML fragments (more than
one XML element not included in a common parent) with the closely
related XMLList object. We’ll see a number of ways to create and work
with XML objects throughout this section. XML objects are a
fundamentally new kind of object, with (as we’ll see) much
special-purpose E4X syntax supporting them. As you know, the typeof operator returns “object” for all
standard JavaScript objects other than functions. XML objects are as
different from ordinary JavaScript objects as functions are, and the
typeof operator returns “xml”. It
is important to understand that XML objects are unrelated to the DOM
(Document Object Model) objects used in client-side JavaScript (see
Chapter 15). The E4X standard defines optional
features for converting between the E4X and DOM representations of XML
documents and elements, but Firefox does not implement these. This is
another reason that E4X may be best considered a server-side
technology.

This section presents a quick tutorial on E4X but does not
attempt to document it comprehensively. In particular, the XML and
XMLList objects have a number of methods that are not mentioned here.
Neither are they covered in the reference section. Readers who want to
use E4X will need to refer to the specification for definitive documentation.

E4X defines quite a bit of new language syntax. The most
striking bit of new syntax is that XML markup becomes part of the
JavaScript language, and you can include XML literals like these
directly in your JavaScript code:

// Create an XML object
var pt =
    <periodictable>
      <element id="1"><name>Hydrogen</name></element>
      <element id="2"><name>Helium</name></element>
      <element id="3"><name>Lithium</name></element>
    </periodictable>;

// Add a new element to the table
pt.element += <element ><name>Beryllium</name></element>;

The XML literal syntax of E4X uses curly braces as escape
characters that allow you to place JavaScript expressions within XML.
This, for example, is another way to create the XML element just
shown:

pt = <periodictable></periodictable>;              // Start with empty table
var elements = ["Hydrogen", "Helium", "Lithium"];  // Elements to add
// Create XML tags using array contents
for(var n = 0; n < elements.length; n++) {
    pt.element += <element id={n+1}><name>{elements[n]}</name></element>;
}

In addition to this literal syntax, you can also work with XML
parsed from strings. The following code adds another element to your
periodic table:

pt.element += new XML('<element ><name>Boron</name></element>');

When working with XML fragments, use XMLList() instead of XML():

pt.element += new XMLList('<element id="6"><name>Carbon</name></element>' +
                          '<element ><name>Nitrogen</name></element>');

Once you have an XML document defined, E4X defines an intuitive
syntax for accessing its content:

var elements = pt.element;    // Evaluates to a list of all <element> tags
var names = pt.element.name;  // A list of all <name> tags
var n = names[0];             // "Hydrogen": content of <name> tag 0.

E4X also adds new syntax for working with XML objects. The
.. operator is the descendant
operator; you can use it in place of the normal . member-access operator:

// Here is another way to get a list of all <name> tags
var names2 = pt..name;

E4X even has a wildcard operator:

// Get all descendants of all <element> tags.
// This is yet another way to get a list of all <name> tags.  var
names3 = pt.element.*;

Attribute names are distinguished from tag names in E4X using
the @ character (a syntax borrowed
from XPath). For example, you can query the value of an attribute like
this:

// What is the atomic number of Helium?
var atomicNumber = pt.element[1].@id;

The wildcard operator for attribute names is @*:

// A list of all attributes of all <element> tags 
var atomicNums = pt.element.@*;

E4X even includes a powerful and remarkably concise syntax for
filtering a list using an arbitrary predicate expression:

// Start with a list of all elements and filter it so
// it includes only those whose id attribute is < 3
var lightElements = pt.element.(@id < 3);

// Start with a list of all <element> tags and filter so it includes only
// those whose names begin with "B". Then make a list of the <name> tags
// of each of those remaining <element> tags.
var bElementNames = pt.element.(name.charAt(0) == 'B').name;

The for/each loop we saw
earlier in this chapter (see The for/each Loop) is
generally useful, but it was defined by the E4X standard for iterating
through lists of XML tags and attributes. Recall that for/each is like the for/in loop, except that instead of
iterating through the properties of an object, it iterates through the
values of the properties of an object:

// Print the names of each element in the periodic table
for each (var e in pt.element)  {
    console.log(e.name);
}

// Print the atomic numbers of the elements
for each (var n in pt.element.@*) console.log(n);

E4X expressions can appear on the left side of an assignment.
This allows existing tags and attributes to be changed and new tags
and attributes to be added:

// Modify the <element> tag for Hydrogen to add a new attribute
// and a new child element so that it looks like this:
//
// <element  symbol="H">
//   <name>Hydrogen</name>
//   <weight>1.00794</weight>
// </element>
//
pt.element[0].@symbol = "H";
pt.element[0].weight = 1.00794;

Removing attributes and tags is also easy with the standard
delete operator:

delete pt.element[0].@symbol; // delete an attribute
delete pt..weight;            // delete all <weight> tags

E4X is designed so that you can perform most common XML
manipulations using language syntax. E4X also defines methods you can
invoke on XML objects. Here, for example, is the insertChildBefore() method:

pt.insertChildBefore(pt.element[1],
                     <element ><name>Deuterium</name></element>);

E4X is fully namespace-aware
and includes language syntax and APIs for working with XML
namespaces:

// Declare the default namespace using a "default xml namespace" statement:
default xml namespace = "http://www.w3.org/1999/xhtml";

// Here's an xhtml document that contains some svg tags, too:
d = <html>
      <body>
	This is a small red square:
	<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10">
	  <rect x="0" y="0" width="10" height="10" fill="red"/>
	</svg>
      </body>
    </html>

// The body element and its namespace uri and its local name
var tagname = d.body.name();
var bodyns = tagname.uri;
var localname = tagname.localName;

// Selecting the <svg> element is trickier because it is not in the
// default namespace.  So create a Namespace object for svg, and use the
// :: operator to add a namespace to a tagname
var svg = new Namespace('http://www.w3.org/2000/svg');
var color = d..svg::rect.@fill  // "red"


[22] E4X is defined by the ECMA-357 standard. You can find the
official specification at http://www.ecma-international.org/publications/standards/Ecma-357.htm.

Comments are closed.

loading...