[This was originally posted at
http://timstall.dotnetdevelopersjournal.com/why_xlinq_is_awesome__the_benefits.htm]
I'm a big fan of Xml, especially for internal tools and processes. In order to juggle xml, I'd usually resort to XPath queries, the XmlDocument, and Xml Serializers. However, the new XLinq that came out with .Net 3.0, seems to completely overpower XPath for C# applications. It rocks.
You can see a general overview here. I also found the Linq and Xlinq chapters from C# 3.0 in a Nutshell to be wonderful. Linq alone is powerful, and XLinq applies linq to xml. There are several specific benefits of XLinq that I want to highlight:
Easy round-tripping from files or strings:
XLinq makes it very easy to load or save files from either a string or uri. [TestMethod]
public void Create_1()
{
//Load from string
XElement x1 = XElement.Parse(
@"
30
");
//Load from uri
XElement x2 = XElement.Load(@"C:\temp\x2.xml");
//save to string
string s = x1.ToString();
//save to file
x2.Save(@"C:\temp\x2a.xml");
}
Easy DOM access and modification
I recall with XmlDocument (at least how I understood it), nodes were tightly coupled to their original XmlDocument, so it could be a pain to pull out an xml snippet from one doc and insert it into another. With XLinq, you can pretty much juggle it any way - insert/update/remove either attributes, nodes, or inner text.
[TestMethod]
public void ModifyDom_1()
{
//Load from string
XElement x1 = XElement.Parse(
@"
30
");
//Get a reference to a node:
XElement xClient = x1.Element("client");
//Modify DOM
// Attribute - insert new
xClient.SetAttributeValue("new1", "val1");
// Attribute - update
xClient.SetAttributeValue("enabled", "false");
// Attribute - remove
xClient.SetAttributeValue("attr2", null);
// Node - insert new
XElement xNew1 = XElement.Parse("bbb");
XElement xNew2 = XElement.Parse("ccc");
xClient.AddAfterSelf(xNew1);
xClient.AddAfterSelf(xNew2);
// Node - remove
xNew2.Remove();
// InnerText - update
xClient.Element("timeout").Value = "60";
//save to string
string s = x1.ToString();
}
Populating objects from an XLinq Query:
You can see a ton of gems in this snippet from the Chicago Code Camp website:
Say you have a class "Abstract" with properties AbstractCode, SpeakerCode, CoSpeakerCode, Author, Description, and Title.
There are two xml files - one for "Abstracts" and the other for "Speakers"
Homer Simpson
homer@email.com
Nuclear engineer...
...
How to be a good employee
Eat donuts and sleep...
...
The following XLinq snippet shows how to:
- Instantiate an array of Abstract objects from xml by mapping the node, attribute, and inner text values.
- Filter the xml file by multiple expressions and complex logic
- Join multiple xml files together, such as the Abstract and Speaker xml files via a common attribute (SpeakerCode)
- Use external functions (LinqHelper.GetNonNull) in your XLinq query.
- Apply transformations (.Replace() ) to the xml data you're reading
- Order it all.
XElement xeAbstracts = XElement.Load("Abstracts.xml");
XElement xeSpeakers = XElement.Load("Speakers.xml");
Abstract[] abs =
(
from a in xeAbstracts.Elements("Abstract")
from s in xeSpeakers.Elements("Speaker")
where a.Attribute("SpeakerCode").Value
== s.Attribute("SpeakerCode").Value
select new Abstract()
{
AbstractCode = a.Attribute("AbstractCode").Value,
SpeakerCode = a.Attribute("SpeakerCode").Value,
CoSpeakerCode = LinqHelper.GetNonNull(a.Attribute("CoSpeakerCode")),
Author = s.Element("Name").Value,
Description = a.Element("Description").Value.Replace("\r\n","
"),
Title = a.Element("Title").Value
}
).OrderBy(n => n.Title).ToArray();
Many of these things would have been either difficult or impossible to do in XPath (unless I'm missing some major trick).
This alone makes a very powerful case for XLinq.