2011-04-27 127 views
6

我在HTML敏捷包中遇到了一些麻烦。HTML敏捷包空参考

当我在不包含特定节点的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(); 
} 
+0

在哪里异常抛出? – 2011-04-27 09:23:44

+0

对不起,忘了提。它被抛在这一行上:“foreach(doc.DocumentNode.SelectNodes(”// table [@ class ='mceRepeater']“))中的var repeater)” – tohereknowswhen 2011-04-27 10:07:18

回答

21

据我所知,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

这是有效的。感谢一堆! – tohereknowswhen 2011-04-27 10:45:16

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)); 
    } 
} 
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()); 
+2

我喜欢这个解决方案背后的想法,但使用Enumerable.Empty而不是ToList。这样你就不会迭代转换成List。 – brianfeucht 2016-03-21 23:16:07

1

你每天.例如之前添加简单?给出的打击:

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

他为什么要这样做? – 2018-01-07 16:29:47

0

这已经更新了,你现在可以防止的SelectNodes从返回通过设置doc.OptionEmptyCollection = true为空,详见this github issue

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