HTML Agility Pack Null参考

时间:2011-04-27 09:17:12

标签: c# html-agility-pack

我在使用HTML Agility Pack时遇到了一些麻烦。

当我在不包含特定节点的HTML上使用此方法时,我得到一个空引用异常。它起初工作,但后来停止工作。这只是一个片段,还有大约10个foreach循环选择不同的节点。

我做错了什么?

public string Export(string html)
{
    var doc = new HtmlDocument();
    doc.LoadHtml(html);
    // exception gets thrown on below line
    foreach (var repeater in doc.DocumentNode.SelectNodes("//table[@class='mceRepeater']"))
    {
        if (repeater != null)
        {
            repeater.Name = "editor:repeater";
            repeater.Attributes.RemoveAll();
        }
    }

    var sw = new StringWriter();
    doc.Save(sw);
    sw.Flush();

    return sw.ToString();
}

5 个答案:

答案 0 :(得分:25)

如果没有找到节点,

AFAIK,DocumentNode.SelectNodes可以返回null

这是默认行为,请参阅codeplex上的讨论主题:Why DocumentNode.SelectNodes returns null

因此,解决方法可能是重写foreach块:

var repeaters = doc.DocumentNode.SelectNodes("//table[@class='mceRepeater']");
if (repeaters != null)
{
    foreach (var repeater in repeaters)
    {
        if (repeater != null)
        {
            repeater.Name = "editor:repeater";
            repeater.Attributes.RemoveAll();
        }
    }
}

答案 1 :(得分:5)

此内容已更新,您现在可以通过设置doc.OptionEmptyCollection = true来阻止SelectNodes返回null,如this github issue中所述。

如果没有与查询匹配的节点,这将使它返回一个空集合而不是null(尽管我不知道为什么这不是默认行为)

答案 2 :(得分:2)

在每个?示例给出打击之前添加简单的.

var titleTag = htdoc?.DocumentNode?.Descendants("title")?.FirstOrDefault()?.InnerText;

答案 3 :(得分:1)

根据Alex的回答,但我解决了这个问题:

public static class HtmlAgilityPackExtensions
{
    public static HtmlAgilityPack.HtmlNodeCollection SafeSelectNodes(this HtmlAgilityPack.HtmlNode node, string selector)
    {
        return (node.SelectNodes(selector) ?? new HtmlAgilityPack.HtmlNodeCollection(node));
    }
}

答案 4 :(得分:0)

我已经创建了适用于任何IEnumerable<T>

的通用扩展程序
public static List<TSource> ToListOrEmpty<TSource>(this IEnumerable<TSource> source)
{
    return source == null ? new List<TSource>() : source.ToList();
}

用法是:

var opnodes = bodyNode.Descendants("o:p").ToListOrEmpty();
opnodes.ForEach(x => x.Remove());