XmlElementAsDictionary: A very simple wrapper for LINQ to XML

Why?

I’ve been forced into engaging with XML in all its gory details recently, as part of my AzureKit project (more on which in another post). Being a big fan of all things LINQ, I started out trying to use the LINQ-to-XML framework. I had problems. This is not a fault of the framework; as a fundamental part of the .NET Framework it must provide a way to achieve everything, and that’s not the same as providing a way to do things simply.
The REST API for Windows Azure uses a hybrid of the Atom syndication format and the ADO.NET Data Services format. Here is the XML required for an Insert to an Azure Table:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<
entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns="http://www.w3.org/2005/Atom">
<
title />
<
updated>2008-09-18T23:46:19.3857256Z</updated>
<
author><name /></author>
<
id />
<
content type="application/xml">
<
m:properties>
<
d:Address>Mountain View</d:Address>
<
d:PartitionKey>mypartitionkey</d:PartitionKey>
<
d:RowKey>myrowkey1</d:RowKey>
<
d:Timestamp m:type="Edm.DateTime">0001-01-01T00:00:00</d:Timestamp>
</
m:properties>
</
content>
</
entry>

I can’t post the LINQ-to-XML code you need to use to create that small document, because I deleted it. Then I formatted the hard drive that it had been on. Then I burned it, just to be on the safe side. The code was not clean. The code was feculent.

The quickest example that I can give is that to use a prefixed namespace, you don’t use new XElement(“m:properties”); you use new XElement(parentElement.GetNamespaceForPrefix(“m”) + “properties”). Seriously. I’m just not doing that.

If you don’t like an interface, wrap it

For these purposes, an XML tree is a collection of named elements, some of which have values, some of which have sub-elements, and each of which may have a number of attributes.

More importantly a single Atom entry does not involve “lists”; that is, there are not multiple children with the same name within a parent element, like this:

<numbers>
<
number>One</number>
<
number>Two</number>
</
numbers>

In fact, an Azure Atom entry is a lot like a dictionary, except with nesting.

I like dictionaries. In some other languages, I like hashes. But we’re talking about .NET and C# here, so I like dictionaries.

XmlElementAsDictionary

I’ve created a very simple class which wraps around an XElement object and provides access to that element’s children, attributes and value using the Dictionary paradigm. Into this class I have baked support for namespaces which does not violate the Principle of Least Astonishment.

Using this class to create the Azure/Atom XML element above looks like this:

var entry = new XmlElementAsDictionary("entry", "http://www.w3.org/2005/Atom");

entry.AddPrefixedNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices");
entry.AddPrefixedNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");

entry["title"].Clear();
entry["updated"].Value = DateTime.Now.ToString("s");
entry["author"]["name"].Clear();
entry["id"].Clear();
entry["content"].Attributes["type"] = "application/xml";
entry["content"]["m:properties"]["d:Address"].Value = "Mountain View";
entry["content"]["m:properties"]["d:PartitionKey"].Value = "mypartitionkey";
entry["content"]["m:properties"]["d:RowKey"].Value = "myrowkey1";
entry["content"]["m:properties"]["d:Timestamp"].Value = DateTime.MinValue.ToString("s");
entry["content"]["m:properties"]["d:Timestamp"].Attributes["m:type"] = "Edm.DateTime";

The class will also accept an XElement to its constructor, and so can be used for reading XML in this manner as well as writing.

Once complete, the element can be converted back into XML using ToElement() or ToDocument(), or to plain-text using ToString() (which gives the same result as calling ToElement().ToString().

Limitations

As specified, this approach also applies the Dictionary limitation of unique keys, so you can’t have lists. But you can construct elements using this wrapper and then compose them into lists.

Availability

I’m collecting various helpful utility classes that get created in support of other projects together in an open-source project called NExtLib. You can download the source from Codeplex. Releases will happen in sync with other, higher-level projects, including AzureKit, the first version of which I’m releasing later this month and hope to present on at user groups in the near future.

Feedback

I’d love to hear any thoughts, ideas for improvement, criticisms, abuse or death threats.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: