LA.NET [EN]

Apr 29

LINQ To XML: building documents with a functional approach

Posted in C#      Comments Off on LINQ To XML: building documents with a functional approach

In the previous post I”ve talked about some of the classes you”ll find in this new API. Today we”ll see how easy it is to create a new XML document with the new API. Most of the time, you”ll end up working with the XElement or XAttribute classes. Lets start with an existing XML tree:

<clients>
  <client id=”1″>
    <name>Luis</name>
    <address>
      <street>Some place</street>
      <zipCode>YYY Somewhere</zipCode>
    </address>
  </client>
  <client id=”2″>
    <name>John</name>
    <address>
      <street>Some other place</street>
      <zipCode>EEE Somewhere</zipCode>
    </address>
  </client>
</clients>

Creating this kind of document on the fly is really simple since we”re talking about a new lightweight XML API based on an functional construction approach. In practice, this means that the following code represents the previous XML tree:

 

var xml = new XElement(
                   “clients”,
                       new XElement(
                           “client”,
                               new XAttribute(“id”, 1),
                               new XElement(“name”, “Luis”),
                               new XElement(“address”,
                                   new XElement(“street”, “Some place”),
                                   new XElement(“zipCode”,”YYY Somewhere”)
                               )
                           ),     
                       new XElement(“client”,
                           new XAttribute(“id”, 2),
                               new XElement(“name”, “John”),
                               new XElement(“address”,
                                   new XElement(“street”, “Some otherplace”),
                                   new XElement(“zipCode”, “EEE Somewhere”)
                               )
                           )
               );

As you can see, this is much better than, say, using the traditional MS .NET DOM implementation (ie, than using the XMLDocument et al classes). Notice also that in the previous example I”ve just created an XML tree (and not an XML document!). This kind of approach is only possible because the XElement class defines a constructor that receives several parameters, as you can from the following snippet:

public XElement(XName name, params object[] content)

Internally, the constructor will end up calling the AddContentSkipNotify (internal) method which will do its best to parse the content that is being passed to it. Do notice that it might receive a simple string, or maybe an attribute…or maybe an attribute and the element”s content. who knows?  The best part is that we don”t need to worry about that: we only need to enjoy it.

Ok, now there”s more cool stuff here! If you”ve looked carefully at the signature of the previous constructor, you”ve surely noticed that it receives an XName, but we”re simply passing a string. XName is a new class which represents the name of an element or attribute that exists on an XML tree. Fortunately for us, the MS team implemented the string implicit operator which is responsible for converting a string into an XName instance. pretty neat, if you ask me.

So, by now you may be thinking that “this is all good, but I will always use a namespace to set the scope of my XML documents”. Good for you! You should keep doing it! To show how you can add namespaces to the previous example, lets add all the elements to a new default namespace (http://msmvps.com/blogs/luisabreu/xmlTests). The new XNamespace class represents a namespace and does implement an implicit string operator which means that you can convert a string to a namespace by simply writing the following code:

XNamespace ns = “http://msmvps.com/blogs/luisabreu/xmlTests“;

And now, you can put all the elements on this namespace by just doing this:

var xml = new XElement(
                 ns + “clients”,

Do notice that you need to keep adding ns to the names of all the other elements that belong to that namespace (if you don”t, they”ll be put on the global namespace). If you try printing the xml, you”ll see that you have the following:

<clients xmlns=”http://msmvps.com/blogs/luisabreu/xmlTests”>

Great! It”s important to note that I don”t really need to create a new XNamespace explicitly. I could just have written this:

var xml = new XElement(
                    “{http://msmvp
s.com/blogs/luisabreu/xmlTests}clients”,

Internally, XName implicit string operator will do the parsing and ends up creating a namespace that is used to scope the elements maintained on the tree. You can also associate a prefix with a namespace. For instance, lets suppose that only the top <clients> element is defined on the previous namespace and that I want to use a prefix to show that association. Here”s the code I”d need to write:

var xml = new XElement(
                  ns + “clients”,
                  new XAttribute(XNamespace.Xmlns + “my”, ns),

Really similar to the previous case, but we need to add a xmlns attribute with the name of the prefix and associate it with the correct namespace.

Now, I”m not sure on what you”re thinking, but I can assure you that  I”m finding this stuff really cool (just like the new stuff that C# 3.0 introduced) and I”m having lots of fun using it on my apps. More to come on the next days! keep tuned!