2012-05-14 112 views
15

爲什麼選擇我的文檔中的所有<li>元素?Html Agility Pack,節點中的SelectNodes

HtmlWeb web = new HtmlWeb(); 
HtmlDocument doc = web.Load(url); 

var travelList = new List<Page>(); 
var liOfTravels = doc.DocumentNode.SelectSingleNode("//div[@id='myTrips']") 
        .SelectNodes("//li"); 

我要的是讓在<div>所有<li>元素與「myTrips」的id

回答

15

這有點令人困惑,因爲你期望它只對id爲「myTrips」的div做selectnodes,但是如果你做了另一個SelectNodes(「// li」),它將執行從頂部的另一個搜索的文件。

我通過將語句合併爲一個來解決此問題,但這隻適用於您只有一個ID爲「mytrips」的div的網頁。查詢將如下所示:

doc.DocumentNode.SelectNodes(「// div [@ id ='myTrips'] // li」);

4

你可以用LINQ查詢做到這一點:

HtmlWeb web = new HtmlWeb(); 
HtmlDocument doc = web.Load(url); 

var travelList = new List<HtmlNode>(); 
foreach (var matchingDiv in doc.DocumentNode.DescendantNodes().Where(n=>n.Name == "div" && n.Id == "myTrips")) 
{ 
    travelList.AddRange(matchingDiv.DescendantNodes().Where(n=> n.Name == "li")); 
} 

我希望它能幫助

1

這似乎直覺上我藏漢,如果你跑我想到了一個特定節點上的SelectNodes方法它只會搜索該節點下的東西,而不是一般的文檔。如果你改變這一行: var liOfTravels = doc.DocumentNode.SelectSingleNode(「// div [@ id ='myTrips']」)。

TO: var liOfTravels = doc.DocumentNode.SelectSingleNode(「// div [@ id ='myTrips']」)。SelectNodes(「li」);

我認爲你會沒事的,我剛剛有同樣的問題,併爲我解決了它。林不知道,如果李將不得不成爲你有節點的直接孩子。

12
var liOfTravels = doc.DocumentNode.SelectSingleNode("//div[@id='myTrips']") 
       .SelectNodes(".//li"); 

注意第二行中的點。基本上,在這方面HTMLAgitilityPack完全依賴於XPath語法,但是結果是不直觀的,因爲這些查詢實際上是相同的:

doc.DocumentNode.SelectNodes("//li"); 
some_deeper_node.SelectNodes("//li"); 
+0

我不認爲查詢是一樣的。實際上,當他做第一個選擇「//div [@ id ='myTrips']」當前節點改變。這就是爲什麼第二個選擇應該是「.//li」(來自當前節點的任何地方)而不是「// li」(從根節點的任何地方)。敏捷性的確如預期的那樣。 – derloopkat

+0

@derloopkat,他們**是相同的(這裏沒有恕我直言;如果他們不是,你可以在解決方案查詢中刪除點,但你不能,你能嗎?)。不幸的是,HTMLAgilityPack從根目錄搜索,無論你在哪個節點。恕我直言部分是這樣的 - 通常關注給定節點的重點是,您繼續從該節點搜索**,而不是從根節點再次搜索。在第二個子查詢中沒有添加點的解決方案查詢根本沒有意義,因此問題爲什麼支持它們? – greenoldman

+0

我們正在談論不同的事情。當我說查詢不一樣時,我正在談論「// li」和「。//li」。通過「那些查詢」你可以參考下面的查詢。 – derloopkat

5

創建一個新的節點可以在某些情況下有益的,讓您使用的XPath更直觀。我發現這在幾個地方很有用。

var myTripsDiv = doc.DocumentNode.SelectSingleNode("//div[@id='myTrips']"); 
var myTripsNode = HtmlNode.CreateNode(myTripsDiv.InnerHtml); 
var liOfTravels = myTripsNode.SelectNodes("//li");