|XML in C# - Using XElement|
|Written by Mike James|
|Tuesday, 02 September 2014|
Page 2 of 2
The Constructor Rules!
What the constructor or the Add method does with an object you supply to it depends on the object’s type.
The rules are:
Less obvious behaviour is that if you supply an object that implements IEnumerable then it is enumerated and the resulting objects are treated as above and if an object is anything that can’t be handled by the above rules it’s converted to a String and then to an XText object and added to Nodes.
The IEnumerable behaviour is very handy because it means you can add a collection of objects in one step.
Manipulating the tree
Constructing a tree is usually just the beginning of the problem. You usually want to process, i.e. examine and change the tree as a result. As an XElement tree is dynamic this is fairly easy.
You can of course use Add to add additional elements of any kind and there are also two remove methods – RemoveNode and RemoveAttribute. These simply remove the object that they belong to from the parents collection.
This first adds child4 to root’s node collection and then removes it.
A particularly useful method is SetElementValue as this will modify an elements value and create a new object if it doesn’t already exist.
For example, the instruction:
will set an existing XElement child of root with XName “Tel” to a value of “123” or if such a XElement doesn’t exist it will first create a new instance.
There is some apparently odd behaviour here in that the value “123” is applied between a new pair of tags <Tel>123</Tel> but it is also appended to root’s Value property as if it was new text located between the <root></root>.
The reason for this is that the Value property is the concatenation of all the XText objects contained within its opening and closing tags. This makes the Value property often less than helpful.
Notice that if you add some additional text in the form of a string then it is simply added to any existing XText object as a concatenation. If you first explicitly create XText objects and add these then you get new child objects – which seems reasonable behaviour.
The SetAttributeValue method works in much the same way but on the Attribute collection.
updates or adds an Epoc attribute. As an attribute generally has only one value, its Value property is much more useful.
Another useful pair of methods are AddBeforeSelf and AddAfterSelf which, as their names suggest, allow the adding of elements above and below the current element in the tree.
There are lots of other methods that modify the tree structure but they are all fairly obvious and contain no surprises – check the documentation for details.
The value of it all
XML is about a standard format for data and just occasionally we need to actually get at the data.
As already mentioned, if an XElement has a single XText child node then you can access this data as a string using the Value property.
However, if it has multiple XText child objects, perhaps contained within other XElement child objects, then the Value property contains a concatenation of these strings.
This makes processing data contained within tags a matter of navigating down to the XElement object which corresponds to the last pair of tags that enclose the text in question. Again, as already mentioned, XAttributes are easier to deal with in this sense because they always correspond to a single name value pair. In this case the Value property always contains the data we are interested in.
For simplicity the following examples will deal with XAttributes but the same methods work with XElement objects.
You could just assign a new value to the Value property but it is usually easier to use the SetValue method because this performs automatic type conversions.
works and sets the attribute to a string “2008”.
generates a runtime error because you need an explicit conversion.
The good news is that:
works without the need for an explicit conversion, as does:
Going the other way is almost as easy but you do have to use an explicit cast and don’t need to use Value.
doesn’t work, neither does;
but, perhaps surprisingly:
You can cast and XAttribute to any numeric, bool, DateTime, TimeSpan and Guid.
You can also cast to nullable versions of each of these data types, which can make handing missing data easier.
Converting to real XML
There is more to XML than a node tree.
You can add many of the XML “decorations” by wrapping the root XElement node in an XDocument object. This can have only one XElement object as the root but also a single XDeclaration, single XDocumentType and any number of XProcessingInstruction and XComment objects.
As you can easily work out, each of these objects adds a corresponding “meta” tag to the XML that the XDocument represents.
There are various, very reasonable, rules about when declarations are emitted, default declarations, and other bookkeeping concerns – all very obvious.
Namespaces are also fairly simple but deserve a simple example. All XNames are created by default with an empty namespace. There are lots of different ways of adding a namespace specifier but the most useful is via the XNamespace class.
For example, to add a namespace to a name you could use:
Notice that an XName has LocalName, NameSpace, and NameSpaceName properties to allow you to work more creatively with XML names. Also remember that all strings that you use in XElement, XAttribute etc names are automatically converted to XName objects.
If you use a namespace then you have to explicitly include it when creating each element of the tree and you have to use it when searching for elements with specific names.
That's more or less all there is to working with XML. Next we look at how to manipulate it using Linq see: Linq and XML.
To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter, Facebook, Google+ or Linkedin, or sign up for our weekly newsletter.
or email your comment to: email@example.com
|Last Updated ( Tuesday, 02 September 2014 )|