|XML in C# - Using XElement|
|Written by Mike James|
|Tuesday, 02 September 2014|
Page 1 of 2
.NET has some really easy-to-use facilities for creating and editing XML. Many of these facilities were introduced to make Linq to XML work better, but you can make use of them in more general situations.
There always was good XML support in .NET but Linq adds a set of classes that makes it easier to work with XML, particularly if you’re not an XML specialist.
There are a number of standard protocols and ways of working with XML – Xpath, SAX, DOM and so on.
All of them are good but they all focus on some specific particular aspect of XML and a particular way of getting the job done. Linq’s version of XML goes “back to basics”.
It is important to realise that much of what we are about to investigate can be used without the need to make use of Linq - it all just happens to be a very easy way to work with XML in general.
Even if you aren’t interested in working with XML looking at how Linq handles a more complicated data structure, a tree in this case, is instructive and has a lot to teach you about the way Linq is designed, how it works and how you might extend it to other data structures.
In this article we look at how to construct the tree structure that XML is all about and in a future article we look at how to use such structures with Linq.
The core of XML is the tag as in
The rules for XML are simple – tags occur, almost always, in matched pairs and you can nest tags as if they were brackets.
The only exception to the matched pairs rule is a tag that is its own closing tag – as in <Record/> which opens and closes the tag in one go.
It’s not difficult to see that you can use tags to build a general tree structure and all you need to represent it in a program is a class that has a collection of itself as a property.
This is exactly how the xNode class, and the more useful xElement descended from it via xContainer, operate.
The important point is that xElement has a Nodes collection which can be used to store an element’s child elements.
A simple example will make this clear.
First we need a root node:
The string “Record” is automatically converted to an XName object and this is used to set the Name property of the new XElement.
An XName is used instead of a simple string because XML names have some additional behaviour because of namespaces – more later.
Now have a root for our tree let’s create a leaf node
and hang it off the tree….
If you place a textbox on a form you can see the XML that the tree represents using:
What you will see is:
You can carry on in the same way to build up a tree of any complexity you like.
creates the following XML:
The idea of nesting XElements within XElements is fairly obvious but there are neater ways of achieving the same result.
For example, you can combine the two Add methods into a single call:
The reason this works is due to an overload of Add not mentioned in the documentation:
You can, of course construct a list of child objects to insert into multiple XElements if you want to.
Another style of XML tree construction is based on the use of the XElement constructor.
One overloaded version allows you to specify the XElements content. So to create an XElement with two children you would use:
You can continue this nested construction to any level you need to.
For example, the following creates the same XML tree we had earlier:
This is generally referred to as “functional construction” and if you format it correctly then it looks like the tree it is constructing and it has the advantage that you can pass it directly to any method that cares to make use of it.
Of course in this style of construction you don’t get variables to keep track of each node but in most cases you don’t need them.
Converting XML To XElements
There are two additional very easy ways of converting XML into an XElement tree – the static Load and Parse methods.
Load will take a file specification as a URI or as a TextReader or XmlReader and parse the text stream into an XElement tree.
The Parse method does the same but by accepting a string of XML tags.
For example, to construct the same XML tree given earlier:
If the XML you try to load or parse is syntactically incorrect then you will have to handle the resulting exception.
If you want to go the other way then there is a Save method and you can specify options on the Save and the ToString methods that control some aspects of formatting.
Now you can see how to build an XElement tree but what about content?
A tree of XML tags isn’t usually the whole story. The main data payload in XML is suppose to be anything you put between opening and closing tags.
In the XElement tree any text between tags is stored as an XText node in the node collection i.e. it is just another type of child node.
As such you can add XText nodes using all of the methods described earlier – if you try to add a string object as a child then the methods simply convert it to an XText object and add it to the collection of nodes.
This adds “Address Record” and “Mike” as text between the specified tags. It is also worth knowing that if an XElement object has only a single XText child then this is also its string Value property.
Text between the tags isn’t the only sort of data carried by XML.
You can also specify any number of name value pairs within the tags themselves as attributes.
Attributes are supposed to be used as “metadata”, i.e. they describe the nature of the data between the tags - formatting, time zone, context etc - and within the XElement tree they are stored as XAttribute objects within the Attributes collection.
The reason for this is that if you enumerate the tree you will list each of the tags and text between tags but not the attributes. Once you have found a tag, i.e. an XElement object, you can enumerate its attributes.
Viewed in this way it should be clear that the main distinction between attributes and other nodes is that attributes are not part of the tree structure being simply stored at each node of the tree.
The rule that you have to keep in mind is that if you add an XAttribute object to an XElement object then it will automatically be added to the Attributes collection.
adds an attribute Epoc= “2000” to the Attributes collection. The XML generated reads:
You can achieve the same result using the function method of constructing an XML tree:
|Last Updated ( Tuesday, 02 September 2014 )|