Friday, July 8, 2011

XElement.Load - removing or reading Namespace


One of the super irritating things about loading xml with XElement.Load(url) is that every. single. node. inherits the namespace of the root node. Normally this isn't problematic and can be dealt with by adding the namespace of the containing node's parent with a little of THIS action:

xml.Element(xml.Name.Namespace + "title").Value;

If you know that ALL nodes in the entire tree have the same namespace, the more performant way to go would be:

const string _title="title";
const XNamespace _namespace ="http://foo.com";

...

xml.Element(_namespace+ _title).Value;


Now this is all well and good, but what if there are multiple namespaces in the root element and you don't know which one the node is inheriting (and it isn't inheriting its direct parent)?

You might want to get rid of all of the namespaces all together and just deal with the node name. That's where THIS handy little piece of code comes in:

foreach (XElement el in xml.Descendants())
el.Name = el.Name.LocalName;

See, the node name you're looking for is always stored in the Name.LocalName (weird, I know). By replacing the Name (which by default is a marriage of the Namespace and the LocalName) with the LocalName, you leave yourself with only the node name you WANT to work with, thus turning your xml name handling into something that works like every other xml node selector you've ever worked with.

Some might say - hey, you should know what your data looks like before you try to read it.

I say - Sure, but sometimes you want to read something slightly unpredictable.
They might reply - hey, this removes the semantic and probable empirical intent of the namespacing away.
I say - hey look, I don't know what the data is empirically and can't write code for a million cases. I know GENERALLY what I'm looking for and can write in special cases if the importance of the dataset rises enough to justify it. And here's - hey look! Elvis!

Ahem -

So here's your CAVEAT:
If you know your data like the back of your hand, use namespaces and tightly map things as precisely as you can. If you don't, just know that if your data sources re-use names in different namespaces, the above might give you ambiguous inaccurate data. If you can live with that ambiguity because the standards themselves are tight enough to protect you, this code might get out around some irritation.

Kisses.



No comments: