Share via


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 AttributeValueOrEmpty

  • Anonymous
    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 post

  • Anonymous
    December 25, 2012
    thanks

  • Anonymous
    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.html

  • Anonymous
    October 23, 2013
    Sweet, Exactly what i was after

  • Anonymous
    May 22, 2014
    i am beginner in linq this post is really help full to me implement the logic .thanks you so much