Выражение HtmlAgilityPack SelectNodes для игнорирования элемента с определенным атрибутом

c# html-agility-pack selectnodes xpath

Вопрос

Я пытаюсь выбрать узлы, кроме узлов сценария, и ul, который имеет класс с именем relativeNav. Может кто-нибудь, пожалуйста, направить меня на правильный путь? Я искал это в течение недели, и я не могу найти его нигде. В настоящее время у меня есть это, но он явно выбирает // ul [@ class = 'relativeNav]. Есть ли какой-либо смысл для выражения NOT, чтобы SelectNode игнорировал это?

        foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//body//*[not(self::script)]/text()"))
        {
            Console.WriteLine("Node: " + node);
            singleString += node.InnerText.Trim() + "\n";
        }

Принятый ответ

Учитывая документ Html со структурой, подобной:

<html>
<head><title>HtmlDocument</title>
</head>
<body>
<div>
<span>Hello Span World</span>
<script>
Script Text
</script>
</div>
<ul class='relativeNav'>
<li>Hello </li>
<li>Li</li>
<li>World</li>
</ul>
</body>
</html>

Следующее выражение XPath выберет все узлы, которые не являются элементами скрипта, исключая всех дочерних элементов UL с классом «relativeNav»:

var nodes = htmlDoc.DocumentNode.SelectNodes("//body//*[not(parent::ul[@class='relativeNav']) and not(self::script)]/text()");

Обновление: забыл упомянуть, что если вам нужно исключить любых дочерних элементов ul [class = 'relativeNav] независимо от их глубины, вы должны использовать:

"//body//*[not(ancestor::ul[@class='relativeNav']) and not(self::script)]/text()"

Если вы хотите также исключить элемент ul (несколько неактуальный в приведенном выше примере, поскольку элемент не содержит текста), вы должны указать:

"//body//*[not(ancestor-or-self::ul[@class='relativeNav']) and not(self::script)]"

Популярные ответы

Надеюсь, это то, что вам нужно:

HtmlDocument doc = new HtmlDocument();
var nodesToExclude1 = doc.DocumentNode.SelectNodes("//ul[@class='relativeNav']");
var nodesToExclude2 = doc.DocumentNode.SelectNodes("//body//script");
var requiredNodes = doc.DocumentNode.SelectNodes("//")
                       .Where(node => !nodesToExclude1.Contains(node) &&
                                      !nodesToExclude2.Contains(node));

foreach (HtmlNode node in requiredNodes)
{
    Console.WriteLine("Node: " + node);
    singleString += node.InnerText.Trim() + "\n";
}


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow