E4X in Form Design

Over the time that I’ve been writing blog entries I’ve made many references to E4X and have included lots of samples that make use of this technology. However I’ve recently come to understand that I probably should have done a better job of introducing E4X usage, since it isn’t necessarily well understood by the average form developer.

For those of you who are unaware, E4X is an extension to JavaScript (ECMAScipt) for manipulating XML.  The reason it is not particularly well known among JavaScript developers is that few of the browsers have implemented E4X.  The notable exception is Mozilla / Firefox. And since the JavaScript engine inside Acrobat/Reader is based on Mozilla, E4X can be used reliably in Acrobat/Reader.

To learn more about E4X, here are some links you may find useful:

http://www.xml.com/pub/a/2007/11/28/introducing-e4x.html

http://www.ecma-international.org/publications/standards/Ecma-357.htm

http://rephrase.net/days/07/06/e4x

http://wso2.org/project/mashup/0.2/docs/e4xquickstart.html

The XMLData Object

Before E4X was invented, we had recognized the need to have generic XML processing in Acrobat / Reader. Consequently, we added the XMLData object to the Acrobat object model.

However, E4X was introduced shortly afterwards, and we ended up with two XML processing engines in Acrobat/Reader. In case there is any doubt, the right answer is to use E4X. You should no longer use the XMLData object. The XMLData object remains in the product for backward compatibility, but it does not get enhanced, it does not get bug fixes.  E4X is faster and uses less memory.

Some Usage Notes

There are several common learning curve issues you might encounter when using E4X:

Oddly, E4X refuses to process the xml processing instruction at the front of an XML fragment.  If it’s there, you will get a syntax error: “xml is a reserved identifier”.

The workaround is to remove leading processing instructions with a regular expression such as:

sXML = sXML.replace(/^[\s\S]*?(<[^\?!])/, “$1″);

Processing Instructions and Comments

By default E4X ignores processing instructions and comments. You can change the default with:

XML.ignoreProcessingInstructions = false;
XML.ignoreComments = false;

If you stop ignoring comments and processing instructions and if you are processing an XML fragment that includes an outer comment or processing instruction, you need to treat it as an XMLList object instead of an XML object:

XML.ignoreProcessingInstructions = false;
var xyz = new XMLList(‘data’);
xyz.toXMLString();

JSLint

Since I just finished recommending JSLint to you, I should point out that JSLint doesn’t handle the E4X syntax extensions to JavaScript.  e.g. XML literals. It will stop processing once it encounters syntax specific to E4X. In most cases you can keep JSLint happy by using function calls instead of the syntax extensions.  e.g. instead of:

xXML..a.length();

use:

xXML.descendants(“a”).length();

Mixed namespaces

Consider this example:

var xXML = <root><one><two>abc</two></one></root>;

The expression: xXML.one.two.toString(); returns “abc”. However, if I introduce another namespace, this expression no longer works:

var xXML = <root><one><two xmlns=”foo”>abc</two></one></root>;

Instead, use: xXML.one.*::two.toString();

And for completeness, the JSLint friendly version:

var xXML = new XML(‘<root><one><two xmlns=”foo”>abc</two></one></root>‘);
xXML.one.child(QName(null, “two”)).toString();