通过使用XPath对相邻的表行进行分组来选择表行

本文关键字:选择 XPath | 更新日期: 2023-09-27 18:18:29

我不清楚如何在问题中正确表达我的问题,所以如果我不能正确表达我的问题,请原谅我。我有以下数据:

<tr class="header">Random Value 1</tr>
<tr class="item">1</tr>
<tr class="item">2</tr>
<tr class="item">3</tr>
<tr class="header">Random Value 2</tr>
<tr class="item">4</tr>
<tr class="item">5</tr>
<tr class="item">6</tr>
<tr class="header">Random Value 3</tr>
<tr class="item">7</tr>
<tr class="item">8</tr>
<tr class="item">9</tr>

我想要实现的是,我想要选择与类头。我通过使用以下代码行

实现了这一点
HtmlNodeCollection headerNodes = doc.DocumentNode.SelectNodes("//tr[@class='header']");

现在我有了集合中的所有标题行。现在我循环遍历所有的header节点,并且我想获得与各自的header行相邻的表行。

foreach (HtmlNode node in headerNodes)
{
     HtmlNodeCollection itemNodes = ???
}

我的问题是,我应该在这里写什么,以便为标题行文本"随机值1",我得到项目行1,2和3。类似地,对于带有文本"随机值2"的标题行,我得到第4,5和6行,等等。

通过使用XPath对相邻的表行进行分组来选择表行

我不太确定HtmlNodeCollection是什么,但是如果您使用正常的XPath并做SelectNodes(这会返回XmlNodeCollection),那么您会发现您正在寻找与node.NextSibling的元素。那么,你的循环应该是这样的:

   foreach (XmlNode node in headerNodes)
   {
        string entry = node.NextSibling.InnerXml;
   }

经过大量的搜索和使用不同的选项后,我找到了解决问题的方法。诀窍是通过检查前面的标题行来选择类为"item"的行。因此,您可以在XPath表达式中看到,我正在选择具有类"item"的tr,并且我还检查其前面的tr应该具有类"header"必须具有当前头部HtmlNode的innerText值。

foreach (HtmlNode header in headerNodes)
{
   string xPath = "following-sibling::tr[contains(@class, 'item') and preceding-sibling::tr[@class='header'][1]='{0}']";
   HtmlNodeCollection itemRows = header.SelectNodes(String.Format(xPath, header.InnerText));
}