【问题标题】:'HTML Agility Pack' XPath query with logical AND带有逻辑 AND 的“HTML 敏捷包”XPath 查询
【发布时间】:2012-08-09 03:38:14
【问题描述】:

我正在尝试在 HTML 文档中查找表,其中前 2 行包含 3 列,其中包含文本。

我尝试使用以下查询,我想返回表的前 2 行在第一列中包含文本的节点:

string xpath = @"//table//table[//tr[1]//td[1]//*[contains(text(), *)] and //tr[2]//td[1]//*[contains(text(), *)]]";
HtmlNode temp = doc.DocumentNode.SelectSingleNode(xpath);

它不能正常工作,亲爱的。

这是一些示例 HTML,这是我要匹配的表格:

    <table width="100%" cellpadding="0" border="0">
       <tbody>
       <tr>
          <td width="27%" valign="center"><b><font size="1" face="Helvetica">SOME TEXT<br></font></b></td>
          <td width="1%"></td>
          <td width="9%" valign="center"><font size="1" face="Helvetica">SOME TEXT<br></font></td>
          <td width="1%"></td>
          <td width="25%" valign="center"><font size="1" face="Helvetica">SOME TEXT<br></font></td>
          <td width="37%"></td>
       </tr>
       <tr>
          <td valign="center"><font size="1" face="Helvetica">SOME TEXT<br></font></td>
          <td></td>
          <td valign="center"><font size="1" face="Helvetica">1<br></font></td>
          <td></td>
          <td valign="center"><font size="1" face="Helvetica">SOME TEXT<br></font></td>
          <td></td>
       </tr>
       </tbody>
</table>

您注意到第 1、3、5 列的前 2 行中有文本。这就是我想要匹配的。

【问题讨论】:

  • 如果您编辑您的问题并插入 HTML,会很有帮助。

标签: c# xpath html-agility-pack


【解决方案1】:
//table//table[//tr[1]//td[1]//*[contains(text(), *)] and //tr[2]//td[1]//*[contains(text(), *)]]

这个 XPath 表达式存在很多问题

  1. //table//table 选择作为table 后代的任何table。但是,在提供的 XML 文档中没有嵌套表。

  2. table[//tr[1]//td[1]//*[contains(text(), *)]。谓词中的//tr 是一个absolute Xpath 表达式——它选择整个文档 中的所有tr 元素——不仅是在以这个@ 为根的子树中987654328@ 元素。很可能您想要.//tr 而不是//tr

  3. //td[1] 选择任何td 元素,它是其父元素的第一个td 子元素——但很可能您只需要第一个后代td 元素。如果是这样,您需要使用这个 XPath 表达式:(//td)[1]

  4. //*[contains(text(), *)] 这将选择其第一个文本节点子节点包含第一个元素子节点的字符串值的任何元素——但您只是想验证 td 是否具有后代文本子节点——这可以正确选择:td[.//text()]

结合所有这些问题的更正,您可能想要的是

  //table
     [(.//tr)[1]/td[1][.//text()]
    and
      (.//tr)[2]/td[1][.//text()]
     ]

或者,可以编写一个等效但更易于理解且不易出错的表达式,如下所示:

//table
  [descendant::tr[1]/td[1][descendant::text()]
 and
   descendant::tr[1]/td[1][descendant::text()]
  ]

【讨论】:

  • string xpath = @"//table[(.//tr)[1]/td[1][.//text()] and (.//tr[2]/td[1][.//text()]]"; HtmlNodeCollection collection = doc.DocumentNode.SelectNodes(xpath); 这会引发“无效令牌”异常。我不知道“HTML Agility Pack”中使用的 XPath 语法是否略有不同,因为我注意到在我遵循的一些 XPath 教程中发生了类似的事情。它也会抛出同样的异常,只是string xpath = @"//table//table//(.//tr)
  • @xM00x,HAP 很可能没有实现标准的 XPath 语言。第二个表达式计算成功了吗?
  • 像魅力一样工作。我吻了你的照片。
  • *当然,我的意思是:string xpath = @"//table//table(.//tr)".
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-01
  • 1970-01-01
  • 2015-02-16
  • 1970-01-01
  • 2010-12-19
  • 2012-07-18
  • 2011-12-28
相关资源
最近更新 更多