This may be a simple fix (well, it probably is) but for some reason I just can't figure it out.
So, I have some xml that looks something like this:
XElement xml = XElement.Parse (
@"<Alphabet>
<a name="A" />
<b name="B" />
<d name="D" />
<e name="E" />
</Alphabet>");
So later in my code, I reference a node that may or may not exist in there like so:
var name = (from b in xml.Descendan开发者_运维百科ts("c")
select b.Attribute("name")).FirstOrDefault().Value;
But when it doesn't exist, instead of returning null or "" it throws a NullReferenceException: Object reference not set to an instance of an object.
What's the best way to check and see if a node actually exists in my linq query? Or do I need to check if it exists some other way?
Well, you're selecting the attribute - so just use:
var nameAttribute = xml.Descendants("c").Select(b => b.Attribute("name"))
.FirstOrDefault();
if (nameAttribute != null)
{
string name = nameAttribute.Value;
}
else
{
// Whatever...
}
(I've changed it from a query expression to dot notation because the query was trivial - query expression syntax wasn't actually buying you anything.)
One problem with this solution: it doesn't differentiate between there being a "c" element but it not having a "name" attribute, and there not being a "c" element in the first place. Do you need to be able to tell the difference?
I created extension methods to do that for me.
public static string GetAttributeValue(this XElement element, string attributeName)
{
XAttribute attribute = element.Attribute(attributeName);
return attribute != null ? attribute.Value : string.Empty;
}
public static string GetElementValue(this XElement element)
{
return element != null ? element.Value : string.Empty;
}
public static string GetElementValue(this XElement element, string elementName)
{
XElement child = element.Element(elementName);
return child != null ? child.Value : string.Empty;
}
FirstOrDefault
returns null
or an XAttribute
which you can cast to a string
to get the value:
var name = (string)((from b in xml.Descendants("c")
select b.Attribute("name")).FirstOrDefault());
or
var name = (string)xml.Descendants("c")
.Select(b => b.Attribute("name"))
.FirstOrDefault();
You can do something like this:
var name = (from b in xml.Descendants("c")
select b.Attribute("name").Value).FirstOrDefault();
or if you really need the element:
var name = (from b in xml.Descendants("c")
select b.Attribute("name")).FirstOrDefault();
if (name != null)
{
// your logic ...
}
精彩评论