Handling Attribute Nulls in LINQ to XML Query

Posted on 2010-03-30
Medium Priority
Last Modified: 2013-11-11
What is the best way to handle null Attributes when assigning the value in an LINQ query?

See the code snippet below, many examples.  We are currently using inline if statements to check if the attribute exists and then handle if it does or not. For example:

 Height = (personsMetaData.Attribute("height") == null) ? null : personsMetaData.Attribute("height").Value,

If this is the best way, anybody have any examples of an extender function  that would cut down on the amount of code for checking nulls inside the query?  Something that could be a little easier maintained?

List<PersonsSportsInfo> personsSportsInfo =
                    (from persons in Root.Descendants("player")
                     let personsMetaData = persons.Elements("player-metadata").First()
                     let firstName = (personsMetaData.Element("name") == null) ? "" : (personsMetaData.Element("name").Attribute("first") == null) ? "" : personsMetaData.Element("name").Attribute("first").Value
                     let lastName = (personsMetaData.Element("name") == null) ? "" : (personsMetaData.Element("name").Attribute("last") == null) ? "" : personsMetaData.Element("name").Attribute("last").Value
                     let careerPhase = persons.Descendants("career-phase")
                     select new PersonsSportsInfo
                         Key = (personsMetaData.Attribute("player-key") == null) ? null : personsMetaData.Attribute("player-key").Value,
                         UniformNumber = (personsMetaData.Attribute("uniform-number") == null) ? null : personsMetaData.Attribute("uniform-number").Value,
                         PositionRegular = (personsMetaData.Attribute("position-regular") == null) ? null : personsMetaData.Attribute("position-regular").Value,
                         Height = (personsMetaData.Attribute("height") == null) ? null : personsMetaData.Attribute("height").Value,
                         Weight = (personsMetaData.Attribute("weight") == null) ? null : personsMetaData.Attribute("weight").Value,
                         Status = (personsMetaData.Attribute("status") == null) ? null : personsMetaData.Attribute("status").Value,
                         DOB = (personsMetaData.Attribute("date-of-birth") == null) ? null : personsMetaData.Attribute("date-of-birth").Value,
                         Health = (personsMetaData.Attribute("health") == null) ? null : personsMetaData.Attribute("health").Value,
                         Caliber = (personsMetaData.Attribute(xts + "caliber") == null) ? null : personsMetaData.Attribute(xts + "caliber").Value,
                         FirstName = firstName,
                         LastName = lastName,
                         FullName = firstName + " " + lastName,
                         PositionDepth = (personsMetaData.Element("player-metadata-american-football") == null) ? null : (personsMetaData.Element("player-metadata-american-football").Attribute(xts + "position-depth") == null) ? "" : personsMetaData.Element("player-metadata-american-football").Attribute(xts + "position-depth").Value,
                         ProExperience = careerPhase
                             .Where(c => c.Attribute("phase-type").Value == "professional")
                             .Select(c => c.Attribute("duration").Value).FirstOrDefault(),
                         CollegeName = careerPhase
                             .Where(c => c.Attribute("phase-type").Value == "college")
                             .Select(c => c.Attribute("name").Value).FirstOrDefault(),

Open in new window

Question by:kruegerste
  • 2
LVL 23

Expert Comment

by:Jens Fiederer
ID: 29217819
You could certainly make the code more palatable by defining a function

object GetValue(DataTypeOfAttributeEntry foo) {
      return (foo == null) ? null : foo.Value;

and using
 Key = GetValue(personsMetaData.Attribute("player-key"));

etc., instead.

(if you these values are always strings, it could be string GetValue)

LVL 64

Accepted Solution

Fernando Soto earned 2000 total points
ID: 29266036
Hi Steve;

Sorry but I have been sick as a dog for the last three days and have not even come near a computer to help out here and I am still a little sick.

In answer to your  questions the way you are doing it would be the best way. You could use extension methods to make it a little more readable. To do this add the class in the code snippet to your project read the comments for needed changes. then your line of code:

Height = (personsMetaData.Attribute("height") == null) ? null : personsMetaData.Attribute("height").Value,

would become:

Height = personsMetaData.Attributes().AttributeExist("height") ? personsMetaData.Attribute("height").Value :null,

The following is what is happening:
1. personsMetaData is a single element of type "player-metadata"
2. Attributes returns a collection of all its attributes
3. AttributeExist is the extension method which return true/false if its parameter exist
4. Height gets assign the value of the attribute if true otherwise null.

The length of the line is a little but longer but I think would be a little more readable.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

// use the same namespace as your project or create a new namespace then add a using statement where you will use it
namespace WindowsFormsApplication11
    // Create a public static class
    public static class Elements
        // Create the extension method that will be called from the Linq query. Give it a meaningful name in this cans
        // AttributeExist of generic type T also in this case returning a bool but can be of any type. The "this" keyword
        // in the first parameter makes it a extension method. The where at the end restricts it to type of XAttributes
        public static bool AttributeExist<T>(
            this System.Collections.Generic.IEnumerable<T> source, string attributeName) where T : System.Xml.Linq.XAttribute
            // Set up the return value
            bool nameFound = false;
            // Check the attribute names for a match
            foreach (XAttribute a in source as IEnumerable<T>)
                if (a.Name == attributeName)
                    // Attribute name was found set value and exit foreach
                    nameFound = true;
            return nameFound;

Open in new window


Author Closing Comment

ID: 31709071
Awesome example, thanks looks great.  Hope you are feeling better soon, thanks for taking time, it wasn't necessary.
LVL 64

Expert Comment

by:Fernando Soto
ID: 29297900
Not a problem, glad to help out.  ;=)

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello there! As a developer I have modified and refactored the unit tests which was written by fellow developers in the past. On the course, I have gone through various misconceptions and technical challenges when it comes to implementation. I would…
Native ability to set a user account password via AD GPO was removed because the passwords can be easily decrypted by any authenticated user in the domain. Microsoft recommends LAPS as a replacement and I have written an article that does something …
How to fix display issue, screen flickering issue when I plug in power cord to the machine. Before I start explaining the solution lets check out once the issue how it looks like after I connect the power cord. most of you also have faced this…
There may be issues when you are trying to access Outlook or send & receive emails or due to Outlook crash which leads to corrupt or damaged PST file. To eliminate the corruption from your PST file, you need to repair the corrupt Outlook PST file. U…
Suggested Courses
Course of the Month4 days, 21 hours left to enroll

601 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question