簡體   English   中英

HtmlAgilityPack 並選擇節點和子節點

[英]HtmlAgilityPack and selecting Nodes and Subnodes

希望有人可以幫助我。

假設我有一個包含多個divshtml文檔,如下例所示:

<div class="search_hit">
    <span prop="name">Richard Winchester</span>
    <span prop="company">Kodak</span>
    <span prop="street">Arlington Road 1</span>
</div>
<div class="search_hit">
    <span prop="name">Ted Mosby</span>
    <span prop="company">HP</span>
    <span prop="street">Arlington Road 2</span>
</div>

我正在使用HtmlAgilityPack來獲取html文檔。 我需要知道的是如何獲得每個search_hit-div的跨度?

我的第一個想法是這樣的:

foreach (HtmlAgilityPack.HtmlNode node in
    doc.DocumentNode.SelectNodes("//div[@class='search_hit']"))
{
     foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("//span[@prop]"))
     {
     }
}

每個div應該是一個對象,其中包含的跨度作為屬性:

public class Record
{
    public string Name { get; set; }
    public string company { get; set; }
    public string street { get; set; }
}

然后應填寫此列表:

public List<Record> Results = new List<Record>();

但是我使用的XPATH並沒有像它應該做的那樣在子節點中進行搜索。 它接縫一次又一次地搜索整個文檔。

我的意思是我已經讓它以這種方式工作,我只是得到整個頁面的跨度,但是我在spansdivs之間沒有關系。 意思是,我不再知道哪個span與哪個div相關。

有人知道解決方案嗎? 我已經玩了那么多,我現在完全糊塗了。 :)

任何幫助表示贊賞!

如果您使用// ,它將從文檔開始搜索。

使用.//從當前節點搜索所有

 foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes(".//span[@prop]"))

或者完全刪除前綴以僅搜索直接子項:

 foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("span[@prop]"))

以下對我有用。 重要的一點正如 BeniBela 指出的那樣,在第二次調用“SelectNodes”時添加一個點。

List<Record> lstRecords=new List<Record>();
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']"))
{
  Record record=new Record();
  foreach (HtmlNode node2 in node.SelectNodes(".//span[@prop]"))
  {
    string attributeValue = node2.GetAttributeValue("prop", "");
    if (attributeValue == "name")
    {
      record.Name = node2.InnerText;
    }
    else if (attributeValue == "company")
    {
      record.company = node2.InnerText;
    }
    else if (attributeValue == "street")
    {
      record.street = node2.InnerText;
    }
  }
  lstRecords.Add(record);
}

首先看看這個: Html Agility Pack - Problem selection subnode

這是您問題的完整工作解決方案:

IList<Record> results = new List<Record>();
foreach (var node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']")) {
    var record = new Record();
    record.Name = node.SelectSingleNode(".//span[@prop='name']").InnerText;
    record.company = node.SelectSingleNode(".//span[@prop='company']").InnerText;
    record.street = node.SelectSingleNode(".//span[@prop='street']").InnerText;
    results.Add(record);
}

如果您閱讀我指出的問題,您會發現執行./span[@prop='name']是完全相同的,因為這些span節點是div節點的(直接)子節點。


如果span節點沒有這些prop屬性,並且您想根據它們出現的順序分配它們,您可以執行以下操作:

foreach (var node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']")) {
    var spanNodes = node.SelectNodes("./span");
    var record = new Record();
    record.Name = spanNodes[0].InnerText;
    record.company = spanNodes[1].InnerText;
    record.street = spanNodes[2].InnerText;
    results.Add(record);
}

為我感到羞恥:)

你們都是對的。

我發現了問題。 這個 NullReferenceException 一直困擾着我,所以我花了更多的時間來詳細研究它。 在所有這些 div 之間,有一個 div 具有相同的“class='search-hit'”屬性,但內部沒有跨度。 這就是為什么它在第二個循環中出現錯誤的原因。

foreach (HtmlAgilityPack.HtmlNode node in doc.DocumentNode.SelectNodes("//span[@prop]/ancestor::div[@class='search_hit']"))
   {
        Record rec = new Record();
        foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes(".//span[@prop]"))
           {
           }
           rList.Results.Add(rec);
   }

上面的代碼正在工作。

謝謝你們的時間和幫助!

我用過那個。 類轉換id

  HtmlNodeCollection nodes = dokuman.DocumentNode.SelectNodes("//div[@id='search_hit']//span[@prop]");


            for (int i = 0; i < nodes .Count; i++)
        {
            var record = new Record();


                record.Name = links[i].InnerText;   results.Add(record);  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM