Check null link

I have the following 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 breaks with a NullReferenceException. Of course, I can write code that checks the return value on a null reference, but then the code will be overly verbose. What an elegant way to do this?

+3
source share
4 answers

You can create an extension method in XmlNode, for example:

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 would probably just drag it in and put it into zero tests explicitly :)

+3
source

Create a test version SelectSingleNodeas 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);
    }
}

Then you 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)
    });
+3
source

.

public static class Extensions
{
   public static String SafeInnerText(this XmlElement node, String default)
   {
      return (node != null) ? node.InnerText : default;
   }
}

.

[...].SelectSingleNode(initialXPath + "h3").SafeInnerText("NoInnerText");

, , default - ...

+2

I don't see how checking for null is too verbose. If you do the same everywhere (pulling out a node). You can abstract this into a single method / function that does a null check. This way you will not have a null check wherever you try to grab a node, since a null check is neatly encapsulated inside a function / method.

Otherwise, I think you will have to do an explicit zero-check. There may be other ways to do this, but be careful. There is a fine line between elegant, smart and hacker.;)

+1
source

Source: https://habr.com/ru/post/1737074/


All Articles