The World’s Leading Microsoft .NET Magazine
   
 
timstall

Donate Today!

Search Box

 

Calendar

««Sep 2010»»
SMTWTFS
    1234
567891011
12131415161718
19202122232425
2627282930

My RSS Feeds








Mailing List

Most Popular Tags

                                                           

Why XLinq is awesome - the benefits

posted Friday, 5 June 2009

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(
    @"<configuration>
        <client enabled='true'>
          <timeout>30</timeout>
        </client>
      </configuration>");

  //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(
        @"<configuration>
            <client enabled='true' attr2='aaa'>
              <timeout>30</timeout>
            </client>
          </configuration>"
);

      //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("<newNode>bbb</newNode>");
      XElement xNew2 = XElement.Parse("<newNode>ccc</newNode>");
      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"

<Speakers>
  <Speaker SpeakerCode="Homer_Simpson">
    <Name>Homer Simpson</Name>
    <Email>homer@email.com</Email>
    <Bio>Nuclear engineer...</Bio>
  </Speaker>
  ...
</Speakers>


<Abstracts>
  <Abstract AbstractCode="Nuclear_101" SpeakerCode=Homer_Simpson">
    <Title>How to be a good employee</Title>
    <Description>
      Eat donuts and sleep...
    </Description>
  </Abstract>
  ...
</Abstracts>

The following XLinq snippet shows how to:

  1. Instantiate an array of Abstract objects from xml by mapping the node, attribute, and inner text values.
  2. Filter the xml file by multiple expressions and complex logic
  3. Join multiple xml files together, such as the Abstract and Speaker xml files via a common attribute (SpeakerCode)
  4. Use external functions (LinqHelper.GetNonNull) in your XLinq query.
  5. Apply transformations (.Replace() ) to the xml data you're reading
  6. 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","<br>"),
        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.

tags:  

links: digg this    technorati    




1. DevLanfear left...
Tuesday, 9 June 2009 6:15 am

I' ve already read that XLing is the fastest way for parsing XML. It's great


2. Casino Amerika left...
Tuesday, 30 June 2009 12:28 am :: http://www.amerikanischeskasino.net

After we published the code samples for LINQ in Action's first chapters in LINQPad a few weeks ago, the samples of three more chapters have just been added. These chapters cover LINQ to XML. Thanks Ji...