Reputation: 209
I've got some trouble with the HTML Agility Pack.
I get a null reference exception when I use this method on HTML not containing the specific node. It worked at first, but then it stopped working. This is only a snippet and there are about 10 more foreach loops that selects different nodes.
What am I doing wrong?
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();
}
Upvotes: 15
Views: 17401
Reputation: 377
This has been updated, and you can now prevent SelectNodes from returning null by setting doc.OptionEmptyCollection = true
, as detailed in this github issue.
This will make it return an empty collection instead of null if there are no nodes which match the query (I'm not sure why this wasn't the default behaviour to begin with, though)
Upvotes: 13
Reputation: 326
I've created universal extension which would work with any IEnumerable<T>
public static List<TSource> ToListOrEmpty<TSource>(this IEnumerable<TSource> source)
{
return source == null ? new List<TSource>() : source.ToList();
}
And usage is:
var opnodes = bodyNode.Descendants("o:p").ToListOrEmpty();
opnodes.ForEach(x => x.Remove());
Upvotes: 1
Reputation: 31
You add simple ?
before every .
example are given blow:
var titleTag = htdoc?.DocumentNode?.Descendants("title")?.FirstOrDefault()?.InnerText;
Upvotes: 3
Reputation: 6225
As per Alex's answer, but I solved it like this:
public static class HtmlAgilityPackExtensions
{
public static HtmlAgilityPack.HtmlNodeCollection SafeSelectNodes(this HtmlAgilityPack.HtmlNode node, string selector)
{
return (node.SelectNodes(selector) ?? new HtmlAgilityPack.HtmlNodeCollection(node));
}
}
Upvotes: 3
Reputation: 32323
AFAIK, DocumentNode.SelectNodes
could return null
if no nodes found.
This is default behaviour, see a discussion thread on codeplex: Why DocumentNode.SelectNodes returns null
So the workaround could be in rewriting the foreach
block:
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();
}
}
}
Upvotes: 32