2012-11-05 1 views
6

J'essaie de sélectionner des noeuds à l'exception des noeuds de script et un ul qui a une classe appelée 'relativeNav'. Quelqu'un peut-il me diriger vers le bon chemin? J'ai cherché cela pendant une semaine et je ne le trouve nulle part. Actuellement, j'ai ceci mais évidemment, je sélectionne aussi // ul [@ class = 'relativeNav']. Y at-il de toute façon à mettre une expression NOT de sorte que SelectNode ignorera celui-là?HtmlAgilityPack SelectNodes expression pour ignorer un élément avec un certain attribut

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

Répondre

4

Compte tenu d'un document Html avec une structure similaire à:

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

L'expression XPath suivante sélectionne tous les nœuds qui ne sont pas éléments de script excluant tous les enfants des éléments UL avec la classe 'relativeNav':

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

Mise à jour: a oublié de mentionner que si vous avez besoin d'exclure les enfants de ul [class = « relativeNav »] quelle que soit leur profondeur, vous devez utiliser:

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

Si vous voulez exclure l'élément ul et (un peu hors de propos dans l'exemple ci-dessus étant donné que l'élément ne contient pas de texte), vous devez spécifier:

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

Votre réponse était exactement ce que je cherchais. Merci d'avoir fait la lumière sur XPath. – thaky

2

J'espère que c'est ce que vous avez besoin:

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

Il a donné un « XPathException: l'expression doit évaluer un ensemble de nœuds » quand j'utilise cette « var requiredNodes = doc. DocumentNode.SelectNodes ("//"). Où (node ​​=>! NodesToExclude.Contains (node)); ". Plus j'ai deux autres exigences de seulement pour sélectionner le "corps" et ne pas sélectionner le script "// * [not (self :: script)]/text()" aussi bien. Il m'a donné une exception d'objet nul quand je les ai placés sous les SelectNodes de requiredNodes. "var requiredNodes = doc.DocumentNode.SelectNodes (" // corps // * [not (self :: script)]/text() "). Où (node ​​=>! nodesToExclude.Contains (node));" – thaky

+0

Voir ma réponse modifiée. –

+0

Merci. L'expression de Linq me sera utile à l'avenir. – thaky

Questions connexes