2012-11-05 29 views
6

Tôi đang cố gắng chọn các nút ngoại trừ các nút tập lệnh và một ul có một lớp được gọi là 'relativeNav'. Ai đó có thể xin hãy dẫn tôi đến con đường đúng không? Tôi đã tìm kiếm điều này trong một tuần và tôi không thể tìm thấy nó ở bất cứ đâu. Hiện tại tôi có điều này nhưng rõ ràng là chọn // ul [@ class = 'relativeNav']. Có anyway để đặt một biểu hiện NOT của nó để SelectNode sẽ bỏ qua một trong những?HtmlAgilityPack SelectNodes biểu thức để bỏ qua một phần tử với một thuộc tính nhất định

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

Trả lời

4

Với một tài liệu với một cấu trúc tương tự như 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> 

Biểu thức XPath sau sẽ chọn tất cả các nút mà không phải là phần tử tập lệnh không bao gồm tất cả trẻ em của các phần tử UL có lớp 'relativeNav':

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

Cập nhật: quên đề cập đến rằng nếu bạn cần phải loại trừ bất kỳ trẻ em của ul [class = 'relativeNav'] không phụ thuộc vào độ sâu của họ, bạn nên sử dụng:

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

Nếu bạn muốn loại trừ các yếu tố ul cũng (phần nào không có liên quan trong ví dụ trên vì phần tử không chứa văn bản) bạn nên chỉ định:

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

Câu trả lời của bạn chính xác là những gì tôi đang tìm kiếm. Cảm ơn bạn đã tiết lộ một số ánh sáng trên XPath. – thaky

2

Tôi hy vọng đây là những gì bạn cần:

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

Nó đưa ra một "XPathException: Expression phải đánh giá một bộ nút" khi tôi sử dụng "var requiredNodes = doc. DocumentNode.SelectNodes ("//") Ở đâu (node ​​=>! NodesToExclude.Contains (nút)); ". Thêm vào đó, tôi có hai yêu cầu khác chỉ để chọn "// body" và không chọn tập lệnh "// * [not (self :: script)]/text()". Nó đã cho tôi một đối tượng null Ngoại lệ khi tôi đặt chúng dưới SelectNodes của requireNodes. "var requiredNodes = doc.DocumentNode.SelectNodes (" // body // * [không (self :: script)]/text() "). Ở đâu (node ​​=>! nodesToExclude.Contains (node));" – thaky

+0

Xem câu trả lời đã chỉnh sửa của tôi. –

+0

Cảm ơn. Biểu thức LINQ sẽ có ích cho tôi trong tương lai. – thaky

Các vấn đề liên quan