Reputation: 13377
i have the follow code:
searchResults.SearchResultCollection.Add(
new SearchResult()
{
Header =
HttpUtility.HtmlDecode(
htmlDocument.DocumentNode
.SelectSingleNode(initialXPath + "h3")
.InnerText),
Link = HttpUtility.HtmlDecode(
htmlDocument.DocumentNode
.SelectSingleNode(initialXPath + "div/cite")
.InnerText)
}
);
Sometimes htmlDocument.DocumentNode.SelectSingleNode(....) returns null and my application crashed with NullReferenceException. Ofcourse i can write code which check returned value on null reference but then code will be overly verbose. What is graceful way to do that?
Upvotes: 3
Views: 2242
Reputation: 20703
Create a Try version of SelectSingleNode
as an extension method.
public static class XmlNodeExtensions
{
public static bool TrySelectSingleNode(this XmlNode node,
string xpath,
out XmlNode result)
{
result = node.SelectSingleNode(xpath);
return (result != null);
}
}
You would then change your code to:
XmlNode node;
searchResults.SearchResultCollection.Add(
new SearchResult
{
Header = HttpUtility.HtmlDecode(
htmlDocument.DocumentNode
.TrySelectSingleNode(initialXPath + "h3", out node)
? node.InnerText
: null),
Link = HttpUtility.HtmlDecode(
htmlDocument.DocumentNode
.TrySelectSingleNode(initialXPath + "div/cite", out node)
? node.InnerText
: null)
});
Upvotes: 3
Reputation: 59705
Just write an extension method.
public static class Extensions
{
public static String SafeInnerText(this XmlElement node, String default)
{
return (node != null) ? node.InnerText : default;
}
}
And then use it as follows.
[...].SelectSingleNode(initialXPath + "h3").SafeInnerText("NoInnerText");
Yes, I know, default
is a reserved keyword...
Upvotes: 2
Reputation: 72678
You could create an extension method on XmlNode, like so:
public static class ExtensionMethods
{
public string GetNodeText(this XmlNode node, string xPath)
{
var childNode = node.SelectSingleNode(xPath);
return (childNode == null)
? "" : childNode.InnerText;
}
}
searchResults.SearchResultCollection.Add(
new SearchResult()
{
Header = HttpUtility.HtmlDecode(
htmlDocument.DocumentNode.GetNodeText(initialXPath + "h3"),
Link = HttpUtility.HtmlDecode(
htmlDocument.DocumentNode.GetNodeText(initialXPath + "div/cite")
}
);
Personally, I'd probably just suck it up and put in the null tests explicityly, though :)
Upvotes: 3
Reputation: 95588
I don't see how checking for null is overly verbose. If you're doing the exact same thing everywhere (pulling a node out). You can abstract that out into a single method/function that performs the null-check. That way you won't have a null-check everywhere you are trying to grab a node since the null-check is neatly encapsulated inside the function/method.
Otherwise, I think you would have to perform an explicit null-check. There may be other ways to do it, but be careful. There is a fine line between elegant, clever, and hackish. ;)
Upvotes: 1