I often work with dynamic XML documents which might or might not contain the element, field or attribute that I am looking for. The Standard .NET XElement class is pretty strict (as it should be) and returns a null reference execption if you ask for the value of an element that is not there:
<employees> <employee id="bp"> <name>Brian</name> </employee> <employee id="ap"> <name>Anita</name> <position>CEO</position> </employee> </employees>
In the example above I can look for the position element for employee AP, but not for employee BP. Instead of building my exception handling every time I ask for the position element, I have built a set of extension methods that take care of this.
Extension methods 1 and 2: SafeValue and SafeAttribute
The following methods allows me to return a default value if the value of either an element or an attribute is not present:
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace MyCode.Extensions
{
public static class XElementExtension
{
public static string SafeValue(this XElement element, string defaultValue)
{
if (element == null)
return defaultValue;
if (element.Value == null)
return defaultValue;
return element.Value;
}
public static string SafeAttribute(this XElement element, XName name, string defaultValue)
{
if (element == null)
return defaultValue;
if (element.Attribute(name) == null)
return defaultValue;
if (element.Attribute(name).Value == null)
return defaultValue;
return element.Attribute(name).Value;
}
}
}
Extensions 3 and 4: GetElementFromPath and GetValueFrompath
These extensions are more exotic. They allow me to ask for an element or a value down a path from the current element, returning a default value if the element or value is not present:
public static XElement GetElementFromPath(this XElement element, params string[] path)
{
if (element == null)
return null;
XElement current = element;
foreach (string s in path)
{
if (current != null && current.Element(s) != null)
current = current.Element(s);
}
return current;
}
public static string GetValueFromPath(this XElement element, params string[] path)
{
if (element == null)
return string.Empty;
XElement current = element;
foreach (string s in path)
{
if (current != null && current.Element(s) != null)
current = current.Element(s);
}
return current != null ? current.Value : "";
}
The functions might seem strange, but it’s cool to be able to do this:
element.GetValueFromPath("employee", "position");
Extension 5: Convert XElement to XmlElement
The last extension method is a old goodie. Converting from the LINQ based XElement to the old-fashioned XmlElement class is handy when working with web services or other methods that requires the old XmlElement.
public static XmlElement ToXmlElement(this XElement element)
{
return new XmlService(element).CreateXmlElement();
}
#region internal conversion class
internal class XmlService
{
private readonly StringBuilder _sb;
private readonly XmlWriter _writer;
private XmlService()
{
_sb = new StringBuilder();
_writer = new XmlTextWriter(new StringWriter(_sb))
{
Formatting = Formatting.Indented,
Indentation = 2
};
}
public XmlService(XNode e) : this()
{
e.WriteTo(_writer);
}
public XmlService(XmlNode e) : this()
{
e.WriteTo(_writer);
}
public XElement CreateXElement()
{
return XElement.Load(new StringReader(_sb.ToString()));
}
public XDocument CreateXDocument()
{
return XDocument.Load(new StringReader(_sb.ToString()));
}
public XmlElement CreateXmlElement()
{
return CreateXmlDocument().DocumentElement;
}
public XmlDocument CreateXmlDocument()
{
var doc = new XmlDocument();
doc.Load(new XmlTextReader(new StringReader(_sb.ToString())));
return doc;
}
}
#endregion

January 31, 2012 at 12:31 pm
// For extensions 1 and 2, there is a simple way to do.
XElement x = new XElement(“Node”, new XText(“123″));
XElement y = new XElement(“Node”);
XElement z;
string xValue = (string)x; // “123″
string yValue = (string)y; // “”
string zValue = (string)z; // null
// If you need a empty string as default
string xValue = (string)x ?? “”; // “123″
string yValue = (string)y ?? “”; // “”
string zValue = (string)z ?? “”; // “”
// Get the XAttribute Value in the same way.
// For extensions 3 and 4, .Net Framework 4.0 supports XPath.
// For extensions 5, I didn’t convert the XElement to XmlElemtn, but XDocument to XmlDocument, and also used the extenstion method.
public static XmlDocument CreateXmlDocument(this XDocument xDoc)
{
XmlReader reader = xDoc.CreateReader();
reader.MoveToContent();
XmlDocument doc = new XmlDocument();
XmlNode cd = doc.ReadNode(reader);
doc.AppendChild(cd);
return doc;
}