How about using an extension method to encapsulate the missing attribute cases:
public static class XmlExtensions
{
public static T AttributeValueOrDefault<T>(this XElement element, string attributeName, T defaultValue)
{
var attribute = element.Attribute(attributeName);
if (attribute != null && attribute.Value != null)
{
return (T)Convert.ChangeType(attribute.Value, typeof(T));
}
return defaultValue;
}
}
Note that this will only work if T
is a type to which string knows to convert via IConvertible. If you wanted to support more general conversion cases, you may need to look for a TypeConverter, as well. This will throw an exception if the type fails to convert. If you want those cases to return the default as well, you'll need to perform additional error handling.
You can cast the attribute to a string
. If it is absent you will get null
and subsequent code should check for null
, otherwise it will return the value directly.
Try this instead:
var books = from book in booksXml.Descendants("book")
select new
{
Name = (string)book.Attribute("name"),
Price = (string)book.Attribute("price"),
Special = (string)book.Attribute("special")
};
In C# 6.0 you can use monadic Null-conditional operator ?.
After applying it in your example it would look like this:
var books = from book in booksXml.Descendants("book")
select new
{
Name = book.Attribute("name")?.Value ?? String.Empty,
Price = Convert.ToInt32(book.Attribute("price")?.Value ?? "0"),
Special = book.Attribute("special")?.Value ?? String.Empty
};
You can read more here in part titled Null-conditional operators.