LINQ to XML : Handling blank or no Element and Attribute
It quite so happen that you are working with XML where you are expecting a specific element in every set. But somehow that is missing in some of the sets.
Now at runtime you would get an error..
The XML file which I am targeting
<?xml version="1.0" encoding="utf-8"?>
<Employees>
<Employee Location="Earth">
<Name>Wriju</Name>
<Email>a@a.com</Email>
</Employee>
<Employee Location="Moon">
<Name>Tupur</Name>
<Email>a@b.com</Email>
</Employee>
<Employee>
<Name>Wrishika</Name>
</Employee>
</Employees>
Notice above the third element has missing Location attribute and Email element. So this would throw me a runtime error if I try to execute as below.
var xml = XElement.Load(@"D:\Temp\Employee.xml");
var q = from e in xml.Descendants("Employee")
select new
{
Name = e.Element("Name").Value,
Location = e.Attribute("Location").Value,
Email = e.Element("Email").Value
};
foreach (var k in q)
{
Console.WriteLine("Name : {0}, Email : {1}, Location : {2}",
k.Name, k.Email, k.Location);
}
Error would come for the 3rd element where both Location attribute and Email element are missing.
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object
Now what I need is simple. By using C# 3.0 extension method I can create two additional methods in a public static class as below
//This method is to handle if element is missing
public static string ElementValueNull(this XElement element)
{
if (element != null)
return element.Value;
return "";
}
//This method is to handle if attribute is missing
public static string AttributeValueNull(this XElement element, string attributeName)
{
if (element == null)
return "";
else
{
XAttribute attr = element.Attribute(attributeName);
return attr == null ? "" : attr.Value;
}
}
Now my code would look like and would not throw any runtime error
var xml = XElement.Load(@"D:\Temp\Employee.xml");
var q = from e in xml.Descendants("Employee")
select new
{
Name = e.Element("Name").ElementValueNull(),
Location = e.AttributeValueNull("Location"),
Email = e.Element("Email").ElementValueNull()
};
foreach (var k in q)
{
Console.WriteLine("Name : {0}, Email : {1}, Location : {2}",
k.Name, k.Email, k.Location);
}
Namoskar!!!
Comments
Anonymous
February 15, 2012
ElementValueOrEmpty AttributeValueOrEmptyAnonymous
August 05, 2012
Thank you for this post, it looks like exactly what I'm looking for...but I can't get it to work. I created a method and ran my linq-to-xml query in there. The query works well but there are a couple records where expected nodes don't exist just like in your example. So, I copied and pasted your ElementValueNull method below the method with the query in it. Then I changed the query to look for loop.Element("pan").ElementValueNull() instead of loop.Element("pan").Value() but I keep getting an error "System.Xml.Linq.XElement does not contain a definition for..." How do I get my query to see my new method?Anonymous
September 06, 2012
great postAnonymous
December 25, 2012
thanksAnonymous
May 16, 2013
Here is how I made it work for me: public static class XElementExtensionMethods { code for ElementValueNull(this XElement element){} code for AttributeValueNull{} } It worked for me only after I moved the declaration of XElementExtensionMethods to outside of my class. Make it the very first class in your program after "using ;" statements. --- this part of my message can be removed by blogger --- Here is another person doing it: tutorialgenius.blogspot.com/.../linqtoxml-safe-element-and-attribute.htmlAnonymous
October 23, 2013
Sweet, Exactly what i was afterAnonymous
May 22, 2014
i am beginner in linq this post is really help full to me implement the logic .thanks you so much