Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have the following code to find xml elements that have a particular attribute value:

IEnumerable<XElement> elems = 
    xmlDoc.Descendants("elemName")
    .Where(x => 
        x.Attribute("attrName").Value
        .Equals(
            filename,
            StringComparison.OrdinalIgnoreCase
        )
    );

The problem is that if the element does not have that attribute, according to the docs, it will return null and we'll get a crash when we try to do null.Value.

I've rewritten it like this:

IEnumerable<XElement> elems = 
     xmlDoc.Descendants("elemName")
     .Where(x => 
         ((x.Attribute("attrName") == null) 
         ? "" 
         : x.Attribute("attrName").Value).Equals(
             filename,
             StringComparison.OrdinalIgnoreCase
         )
     );

But I think it's a bit ugly. Is there an idiomatic way of doing this - I imagine this is a fairly common operation? I suppose I could just do a regular loop.

share|improve this question
up vote 4 down vote accepted

I think you could use the null-conditional operator for x.Attribute("attrName").Value and swap arguments of String.Equals to avoid the NullReferenceException as follows:

IEnumerable<XElement> elems =
     xmlDoc.Descendants("elemName")
     .Where(x =>
         filename.Equals(
             x.Attribute("attrName")?.Value,
             StringComparison.OrdinalIgnoreCase
         )
     );
share|improve this answer

There is a trick - you can cast XAttribute to some data types: string, int, long, Guid, DateTime, bool etc and their nullable brothers. And if type supports null value there will be no NullReferenceException. You will simply get null as result:

(string)x.Attribute("attrName")

Next: I suggest you to use more meaningful names for variables, even if it's one-letter variable. I.e. instead of x for element you can use e.

And last, you can write following extension method to nicely compare strings

public static bool EqualsIgnoreCase(this string s, string value)
{
     return String.Equals(s, value, StringComparison.OrdinalIgnoreCase);
}

And finally your parsing query will look like

from e in xmlDoc.Descendants("elemName")
where filename.EqualsIgnoreCase((string)e.Attribute("attrName"))
select e;
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.