gpt4 book ai didi

c# - XPath - 选择两个节点之间的第一组兄弟节点

转载 作者:数据小太阳 更新时间:2023-10-29 02:51:50 25 4
gpt4 key购买 nike

我在 C# 中使用 XPath 查询一些 HTML 文件时遇到了一个小问题。

好的,首先这是一个示例 HTML:

<table id="theTable">
<tbody>
<tr class="theClass">A</tr>
<tr class="theClass">B</tr>
<tr>1</tr>
<tr>2</tr>
<tr>3</tr>
<tr>4</tr>
<tr>5</tr>
<tr class="theClass">C</tr>
<tr class="theClass">D</tr>
<tr>6</tr>
<tr>7</tr>
<tr>8</tr>
<tr>9</tr>
<tr>10</tr>
<tr>11</tr>
<tr>12</tr>
<tr>13</tr>
<tr>14</tr>
<tr>15</tr>
<tr class="theClass">E</tr>
<tr class="theClass">F</tr>
<tr>16</tr>
<tr>17</tr>
<tr>18</tr>
<tr>19</tr>
<tr>20</tr>
<tr>21</tr>
<tr>22</tr>
</tbody>
</table>

现在,我要做的是仅获取 B 和 C 节点 (1,2,3,4,5,) 之间的那些元素。

到目前为止,这是我尝试过的:

using System;
using System.Xml.XPath;

namespace Test
{
class Test
{
static void Main(string[] args)
{
XPathDocument doc = new XPathDocument("Test.xml");
XPathNavigator nav = doc.CreateNavigator();

Console.WriteLine(nav.Select("//table[@id='theTable']/tbody/tr[preceding-sibling::tr[@class='theClass'] and following-sibling::tr[@class='theClass']]").Count);
Console.WriteLine(nav.Select("//table[@id='theTable']/tbody/tr[preceding-sibling::tr[@class='theClass'][2] and following-sibling::tr[@class='theClass'][4]]").Count);

Console.ReadKey(true);
}
}
}

此代码运行上述 HTML,输出 19 和 5。所以只有第二个 XPath 表达式有效,但这只是因为它搜索具有两个元素的元素 class=theClass在他们之前和他们之后 4 个。

我的问题现在开始了。我想编写一个表达式,它只返回 <td class="theClass"></td> 之后的第一组元素。标签,无论有多少组在关注它。

如果我在这个 HTML 上运行我的代码

<table id="theTable">
<tbody>
<tr class="theClass">A</tr>
<tr class="theClass">B</tr>
<tr>1</tr>
<tr>2</tr>
<tr>3</tr>
<tr>4</tr>
<tr>5</tr>
<tr>6</tr>
</tbody>
</table>

它会输出0和0。

所以这是不好的。

有没有人有什么想法?

谢谢!

最佳答案

Now, what I'm trying to do is to get only those elements that are between the B and C nodes

使用这个单一的 XPath 表达式:

   /*/*/tr[.='B']
/following-sibling::*
[count(.|/*/*/tr[. ='C']/preceding-sibling::*)
=
count(/*/*/tr[. ='C']/preceding-sibling::*)
]

这是一个基于 XSLT 的验证:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">
<xsl:copy-of select=
"/*/*/tr[.='B']
/following-sibling::*
[count(.|/*/*/tr[. ='C']/preceding-sibling::*)
=
count(/*/*/tr[. ='C']/preceding-sibling::*)
]
"/>
</xsl:template>
</xsl:stylesheet>

当此转换应用于第一个提供的 XML 文档时:

<table id="theTable">
<tbody>
<tr class="theClass">A</tr>
<tr class="theClass">B</tr>
<tr>1</tr>
<tr>2</tr>
<tr>3</tr>
<tr>4</tr>
<tr>5</tr>
<tr class="theClass">C</tr>
<tr class="theClass">D</tr>
<tr>6</tr>
<tr>7</tr>
<tr>8</tr>
<tr>9</tr>
<tr>10</tr>
<tr>11</tr>
<tr>12</tr>
<tr>13</tr>
<tr>14</tr>
<tr>15</tr>
<tr class="theClass">E</tr>
<tr class="theClass">F</tr>
<tr>16</tr>
<tr>17</tr>
<tr>18</tr>
<tr>19</tr>
<tr>20</tr>
<tr>21</tr>
<tr>22</tr>
</tbody>
</table>

计算 XPath 表达式并将所选节点复制到输出:

<tr>1</tr>
<tr>2</tr>
<tr>3</tr>
<tr>4</tr>
<tr>5</tr>

解释:

这里我们简单地使用Kayessian 公式求节点集交集:

$ns1[count(.|$ns2) = count($ns2)]

我们在这里替换了 $ns1与:

 /*/*/tr[.='B']
/following-sibling::*

我们用 $ns2 代替了与:

/*/*/tr[. ='C']/preceding-sibling::*

第二个问题:

My problem starts now. I want to write a single expression that will return only the first group of elements that come after a <td
class="theClass"></td>
tag, no matter how many more groups are following it.

再次存在选择这些元素的单个 XPath 表达式:

   /*/*/tr[@class='theClass'
and
following-sibling::*[1][self::tr[not(@*)] ]
][1]
/following-sibling::tr
[not(@*)
and
count(preceding-sibling::tr
[@class='theClass'
and
following-sibling::*[1][self::tr[not(@*)] ]
]
)
= 1
]

解释:

这将选择以下所有 sibling tr第一个 */*/tr 的元素(满足多个条件) class 的元素属性具有字符串值 "theClass"并且其第一个后续元素兄弟是 tr没有属性。

这些选择的条件tr元素还满足两个:1)它们没有任何属性;和 2) 他们只有一个前 sibling tr元素,其class属性具有字符串值 "theClass" .

这是基于 XSLT 的验证:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">
<xsl:copy-of select=
"/*/*/tr[@class='theClass'
and
following-sibling::*[1][self::tr[not(@*)] ]
][1]
/following-sibling::tr
[not(@*)
and
count(preceding-sibling::tr
[@class='theClass'
and
following-sibling::*[1][self::tr[not(@*)] ]
]
)
= 1
]
"/>
</xsl:template>
</xsl:stylesheet>

应用于第二个提供的 XML 文档时:

<table id="theTable">
<tbody>
<tr class="theClass">A</tr>
<tr class="theClass">B</tr>
<tr>1</tr>
<tr>2</tr>
<tr>3</tr>
<tr>4</tr>
<tr>5</tr>
<tr>6</tr>
</tbody>
</table>

再次输出想要的和正确选择的元素:

<tr>1</tr>
<tr>2</tr>
<tr>3</tr>
<tr>4</tr>
<tr>5</tr>
<tr>6</tr>

关于c# - XPath - 选择两个节点之间的第一组兄弟节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10808550/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com