Ссылка на пустой пакет HTML Agility Pack - PullRequest
9 голосов
/ 27 апреля 2011

У меня возникли некоторые проблемы с пакетом 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 ]

25 голосов
/ 27 апреля 2011

AFAIK, DocumentNode.SelectNodes может вернуть null, если не найдено ни одного узла.

Это поведение по умолчанию, см. Ветку обсуждения в codeplex: Почему DocumentNode.SelectNodes возвращает ноль

Таким образом, обходной путь может заключаться в переписывании блока 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();
        }
    }
}
5 голосов
/ 19 февраля 2018

Это было обновлено, и теперь вы можете запретить SelectNodes возвращать ноль, установив doc.OptionEmptyCollection = true, как подробно описано в этой проблеме github .

Это заставит его возвращать пустую коллекцию вместо нуля, если нет узлов, соответствующих запросу (хотя я не уверен, почему это не было поведением по умолчанию для начала)

2 голосов
/ 07 января 2018

Вы добавляете простые ? перед каждым . примером удара:

var titleTag = htdoc?.DocumentNode?.Descendants("title")?.FirstOrDefault()?.InnerText;
2 голосов
/ 13 июня 2014

Согласно ответу Алекса, но я решил это так:

public static class HtmlAgilityPackExtensions
{
    public static HtmlAgilityPack.HtmlNodeCollection SafeSelectNodes(this HtmlAgilityPack.HtmlNode node, string selector)
    {
        return (node.SelectNodes(selector) ?? new HtmlAgilityPack.HtmlNodeCollection(node));
    }
}
0 голосов
/ 23 марта 2015

Я создал универсальное расширение, которое будет работать с любым 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());
...