In this day and age of JSON data everywhere, a lot of developers are leaving XML behind. There are, however, still some areas where XML is still used quite heavily; web and application configuration files are a start. There are also many financial institutions that still do pretty much everything internal to a core banking system in XML.
.NET has always had great support for handling XML data, and there are certainly more than a handful of different APIs for dealing with it. In this article, I’m going to go over a quick refresher of using the XElement interface, and in the process introduce you to one place where XML is still used that’s potentially quite useful to you.
Constructing XML
The XElement interface makes it almost childlike to construct valid XML. Let’s imagine for a moment we wanted to create something that looks similar to the following XML data:
<person> <name>Peter Shaw</name> <email>shawty.d.ds@googlemail.com</email> </person>
Using XElement to construct this is a simple as using the following code:
using System; using System.Xml.Linq; namespace blogxelementrefresh { class Program { static void Main() { XElement myRoot = new XElement("person"); myRoot.Add(new XElement("name", "Peter Shaw")); myRoot.Add(new XElement("email", "shawty.d.ds@googlemail.com")); Console.Write(myRoot.ToString()); } } }
If we press F5 to run this, we get the following in our console window:
Figure 1: The results of running the preceding code
Very easy, and very simple to understand.
Adding nested elements is not any harder either.
using System; using System.Xml.Linq; namespace blogxelementrefresh { class Program { static void Main() { XElement myRoot = new XElement("person"); myRoot.Add(new XElement("name", "Peter Shaw")); myRoot.Add(new XElement("email", "shawty.d.ds@googlemail.com")); XElement nestedElement = new XElement("location"); nestedElement.Add(new XElement("area", "North Durham")); nestedElement.Add(new XElement("country", "United Kingdom")); myRoot.Add(nestedElement); Console.Write(myRoot.ToString()); } } }
Which, when run, gives us the following:
Figure 2: After running the code containing nested elements
By combining multiple levels of elements, it’s possible to very simply build an XML structure to match anything you need; then, by using the ‘ToString’ method on the root element, get an appropriately formatted string ready to save into a file. XElement also makes it easy to parse XML. To demonstrate that, however, we need a source of XML data.
Many of you who have a Gmail account may not know this, but it’s possible to get an XML summary of your Gmail inbox, and very easily too. If you point your browser at
https://mail.google.com/mail/feed/atom
and enter your Gmail user name and password when prompted, you can take a look at the output in your browser.
Figure 3: Viewing the preceding output in a browser
You can easily retrieve this feed in a .NET program by using the WebClient class and an old-fashioned base64 encrypted access request. Needless to say, you must do this over HTTPS. In fact, Google doesn’t give you any choice; it’s HTTPS or bust. You can grab the XML data by using the following code:
string gmailFeed; using (WebClient client = new WebClient()) { client.Credentials = new NetworkCredential("user", "password"); gmailFeed = client.DownloadString ("https://mail.google.com/mail/feed/atom"); }
If you still have problems accessing the feed when using this procedure, you may also need to configure your GMail account settings to allow ‘Less Secure apps’ to access the account. Generally, if this is the case, you’ll get an automatic EMail to your alternative email address, warning you of the fact.
Figure 4: Google-generated warning
The second link in the EMail will take you to the following page:
Figure 5: The Google page where you can allow access
where you can allow your application to have access. Once you have the received XML in a regular string, you then can parse it using XElement as follows:
XElement gmailDoc = XElement.Parse(gmailFeed);
Because the XML is an ‘Atom’ feed, you’ll also need to create a namespace:
XNamespace ns = "http://purl.org/atom/ns#";
Then, with all that done, it’s simply just a matter of extracting the information you need. The following code shows the inbox title and message count, then outputs a summary of all the waiting emails available.
Console.WriteLine(gmailDoc.Element(ns + "title").Value); Console.WriteLine("{0} {1}", gmailDoc.Element(ns + "fullcount").Value, gmailDoc.Element(ns + "tagline").Value); Console.WriteLine(); foreach (XElement entry in gmailDoc.Elements(ns + "entry")) { Console.WriteLine(entry.Element(ns + "title").Value); Console.WriteLine(entry.Element(ns + "summary").Value); Console.WriteLine(entry.Element(ns + "author").Element(ns + "email").Value); Console.WriteLine(); }
Grabbing a single element is as easy as using the ‘Element’ method with the name (optionally prefixed with a namespace) of the element you wish to retrieve. To get an IEnumerable collection, use the ‘Elements’ method instead. There are others, too, but I leave exploring them to you, the reader.
Got something in .NET you’d like to know more about, or a trick you’d like to share, feel free to drop a comment in the comments section below or bend my ear on Twitter where I can usually be found as @shawty_ds. Let me know if there’s anything you’d like to see covered in this column.