2012-11-05 10 views
6

Ich versuche, Knoten außer Skriptknoten und eine UL auszuwählen, die eine Klasse namens 'relativeNav' hat. Kann mir bitte jemand den richtigen Weg weisen? Ich habe seit einer Woche nach diesem gesucht und ich kann es nirgendwo finden. Momentan habe ich das aber natürlich auch die // ul [@ class = 'relativeNav'] ausgewählt. Gibt es einen NOT-Ausdruck, um SelectNode zu ignorieren?HtmlAgilityPack SelectNodes-Ausdruck, um ein Element mit einem bestimmten Attribut zu ignorieren

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

Antwort

4

ein HTML-Dokument mit einer Struktur gegeben ähnelt:

<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> 

Die folgenden XPath-Ausdruck werden alle Knoten auszuwählen, die nicht sind Skriptelemente, die alle untergeordneten Elemente von UL-Elementen mit der Klasse 'relativeNav' ausschließen:

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

Update: vergessen zu erwähnen, dass, wenn Sie irgendwelche Kinder von ul [class = ‚relativeNav‘] ausschließen müssen unabhängig von ihrer Tiefe sollten Sie verwenden:

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

Wenn Sie auch das ul-Element ausschließen wollte (etwas irrelevant in dem obigen Beispiel, da das Element Text enthält nicht) sollten Sie Folgendes an:

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

Ihre Antwort war genau das, was ich suchte. Vielen Dank, dass Sie sich für XPath interessieren. – thaky

2

ich diese Hoffnung ist das, was Sie brauchen:

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"; 
} 
+0

Es gab eine „XPathException: Expression zu einem Knotenmenge auswerten muss“ wenn ich dieses „var requiredNodes = doc. DocumentNode.SelectNodes ("//"). Wobei (node ​​=>! NodesToExclude.Contains (node)); ". Außerdem habe ich zwei weitere Voraussetzungen, nur den "// body" auszuwählen und das Skript "// * [not (self :: script)]/text()" ebenfalls nicht auszuwählen. Es gab mir eine Null-Objekt-Ausnahme, wenn ich sie unter die SelectNodes von requiredNodes legte. "var requiredNodes = doc.DocumentNode.SelectNodes (" // body // * [nicht (self :: script)]/text() "). Wo (node ​​=>! nodesToExclude.Contains (node));" – thaky

+0

Siehe meine bearbeitete Antwort. –

+0

Danke. Linq Ausdruck wird für mich in der Zukunft nützlich sein. – thaky