使用HTML Agility Pack和Linq解析html

Tim*_*sen 12 c# linq html-parsing html-agility-pack

我有以下HTML

(..)
<tbody>
 <tr>
  <td class="name"> Test1 </td>
  <td class="data"> Data </td>
  <td class="data2"> Data 2 </td>
 </tr>
 <tr>
  <td class="name"> Test2 </td>
  <td class="data"> Data2 </td>
  <td class="data2"> Data 2 </td>
 </tr>
</tbody>
(..)
Run Code Online (Sandbox Code Playgroud)

我的信息是name => so"Test1"和"Test2".我想知道的是如何根据我拥有的名称获取"data"和"data2"中的数据.

目前我正在使用:

var data =
    from
        tr in doc.DocumentNode.Descendants("tr")
    from   
        td in tr.ChildNodes.Where(x => x.Attributes["class"].Value == "name")
    where
        td.InnerText == "Test1"
    select tr;
Run Code Online (Sandbox Code Playgroud)

但是{"Object reference not set to an instance of an object."}当我试着去看时,我得到 了data

Kob*_*obi 15

至于您的尝试,您的代码有两个问题:

  1. ChildNodes很奇怪 - 它还返回空白文本节点,它们没有class属性(当然不能有属性).
  2. 正如詹姆斯沃尔福德评论的那样,文本周围的空间很重要,你可能想要修剪它们.

通过这两个更正,以下工作:

var data =
      from tr in doc.DocumentNode.Descendants("tr")
      from td in tr.Descendants("td").Where(x => x.Attributes["class"].Value == "name")
     where td.InnerText.Trim() == "Test1"
    select tr;
Run Code Online (Sandbox Code Playgroud)


Sim*_*ier 5

这是XPATH方式-嗯...这些天,每个人似乎都已经忘记了XPATH的强大功能,而只专注于C#XLinq :-)

此函数获取与名称关联的所有数据值:

public static IEnumerable<string> GetData(HtmlDocument document, string name)
{
    return from HtmlNode node in
        document.DocumentNode.SelectNodes("//td[@class='name' and contains(text(), '" + name + "')]/following-sibling::td")
        select node.InnerText.Trim();
}
Run Code Online (Sandbox Code Playgroud)

例如,此代码将转储所有“ Test2”数据:

    HtmlDocument doc = new HtmlDocument();
    doc.Load(yourHtml);

    foreach (string data in GetData(doc, "Test2"))
    {
        Console.WriteLine(data);
    }
Run Code Online (Sandbox Code Playgroud)

  • 我选择Linq答案而不是XPath的原因是因为后者很难阅读和理解。前者非常清楚其意图,如果有必要,您可以将查询分解为子查询以对其进行调试。XPath是钝器,无法调试。如果没有大量测试数据,很难验证它在做正确的事情。仅仅搜索有关XPath语法的权威页面是一件令人讨厌的事情。我仍然喜欢HAP,但是每次看到XPath语句时,我都会畏缩。 (2认同)
  • 当您不知道时,一切都会变得很困难。我认为XPATH在查询XML集时更容易使用和理解。它还可以优雅地处理null(与Linq不同)。唯一的(大)缺点是,对于不区分大小写的比较而言,它并不酷。另一个问题是XPATH不可移植(例如,在WinRT上不存在)。无论如何,请使用您喜欢的库:-) (2认同)