Announcing LINQ to XML for JavaScript Beta 2

Over the last couple of months, I have been using the Ltxml.js (LINQ to XML for JavaScript) library in earnest.  The project that I am working on consists of several
thousand lines of JavaScript code, most of which I have hand-converted from C# to JavaScript.  I have gained a lot of experience with Ltxml.js, and it is working well for me.  I delivered the first release of my portion of the project several weeks ago.  I am doing some pretty fancy stuff, and it is really cool to see interesting Open XML functionality working client-side, in the browser.

You can download this latest version at ltxmljs.codeplex.com.

In addition to getting it working both in node.js and in the browser, I also needed to make it play well with RequireJS.  The larger project is using the dojo toolkit, so making Ltxml.js work with RequireJS was a must.  In addition, a requirement was to make it play nicely with JQuery.  As it turns out, I need to support the following matrix:

Environment

RequireJS

JQuery

Browser

N

N

Browser

N

Y

Browser

Y

N

Browser

Y

Y

Node

N

n/a

Node

Y

n/a

In the release, in addition to the requisite example and test applications, I include six very simple example applications that contain ‘hello world’ for each of the above situations.  The accompanying screen-cast shows installation of ltxml.js, and running each of the various examples.

In addition to the ‘hello world’ examples for each of the above environments, there are two more example programs:

Also in this release, I reworked the serialization code.  As experienced LINQ to XML developers know, you control namespace prefixes when serializing using namespace XAttribute objects.  However, if the required namespace XAttribute objects do not exist, then there are circumstances where Ltxml.js needs to manufacture namespace prefixes.  LINQ to XML for .NET has the same situation, and requires a similarly
engineered solution.  I had uncovered a bug in Beta 1 when serializing XML trees where the namespace prefixes were not fully specified, and I decided that I needed to rework the serialization code fairly significantly.  I am now happy with the serialization code.  I believe that it will always serialize valid XML for any XML tree, even when there are namespace prefixes that are not specified, and when there are XML trees that contain conflicting namespace
prefix specifications.

I made a couple of small breaking changes.  I split the
extension axis methods out into their own JavaScript module (ltxml-extensions.js). 
This was necessary to get it working with RequireJS.  The ltxml-extensions
module ‘requires’ linq.js and ltxml.js so to set up the proper
dependencies, it was necessary to split it out.  This means that you need to
include a script tag explicitly for the extensions, like this:

<script src=”linq.js” type=”text/javascript”></script>

<script src=”ltxml.js” type=”text/javascript”></script>

<script src=”ltxml-extensions.js” type=”text/javascript”></script>

Further, I changed the idiom that you should use for the Ltxml extension methods.  Previously, I was adding the various extension methods to the Enumerable constructor function (which comes from linq.js).  This works in many cases, but it has been pointed out that this is potentially dangerous in that there may be other modules using linq.js, and if they also modified Enumerable in a similar fashion, you might be subject to collisions.  But further, when using RequireJS with Node, it
breaks completely.  Whenever you ‘require’ a module using Node.js, it returns a completely new object, so any mods you made to the original object are no longer there.  And further it is bad style to be modifying the object returned by another module.

So whereas in LINQ to XML, if you need to retrieve a collection of the grandchild elements, you write code as follows:

var result = source.Elements().Elements();

In Ltxml.js, you need to surround the call to the axis method with a call to the XEnumerable constructor, at which point you can dot into the elements extension method.

var result = new XEnumerable(source.elements()).elements();

It is a little bit of an inconvenience, and makes the idiom to be not so neat, but really not a big deal at all.  The resulting code is more explicit, and there is less ‘magic’ happening behind the scenes, so this makes the tradeoff worth it.

In the next blog post on Ltxml.js, I will go through the 20 examples in ltxml-examples.html, and explain what each example is demonstrating, why it is important.

The following screen-cast walks through unzipping and running Ltxml in its various configurations.