C# XPath-选择两个节点之间的第一组同级

C# XPath-选择两个节点之间的第一组同级,c#,xml,xpath,siblings,C#,Xml,Xpath,Siblings,我在使用XPath查询C#中的一些HTML文件时遇到了一个小问题 好的,首先是一个示例HTML: <table id="theTable"> <tbody> <tr class="theClass">A</tr> <tr class="theClass">B</tr> <tr>1</tr> <tr>2</tr&g

我在使用XPath查询C#中的一些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>
这段代码在上面的HTML上运行,输出19和5。 因此,只有第二个XPath表达式可以工作,但这仅仅是因为它搜索的元素前面有两个
class=theClass
,后面有4个

我的问题现在开始了。我想编写一个表达式,只返回
标记后面的第一组元素,不管后面还有多少组

如果我在这个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>

A.
B
1.
2.
3.
4.
5.
6.
它将输出0和0

所以这不好

有人有什么想法吗


谢谢大家!

如果您不必使用XPath,某些LINQ可能更容易获得正确的结果,并且更具可读性

在您的情况下,Skip和类似于以下伪代码的组合可能会起作用:

nav.Select("//table[@id='theTable']/tbody/tr") // whatever to get list of all TR
   .Skip("theClass is B") // some condition to skip up to first node
   .TakeWhile("theClass is C"); // some condition to take upto second node.
现在,我要做的是只获取那些 在
B
C
节点之间

使用这个XPath表达式

   /*/*/tr[.='B']
           /following-sibling::*
             [count(.|/*/*/tr[. ='C']/preceding-sibling::*)
             =
              count(/*/*/tr[. ='C']/preceding-sibling::*)
             ]
<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>
   /*/*/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: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>
<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>
这里是一个基于XSLT的验证

   /*/*/tr[.='B']
           /following-sibling::*
             [count(.|/*/*/tr[. ='C']/preceding-sibling::*)
             =
              count(/*/*/tr[. ='C']/preceding-sibling::*)
             ]
<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>
   /*/*/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: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>
<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>
其中,我们将
$ns1
替换为:

 /*/*/tr[.='B']
               /following-sibling::*
/*/*/tr[. ='C']/preceding-sibling::*
我们将$ns2替换为:

 /*/*/tr[.='B']
               /following-sibling::*
/*/*/tr[. ='C']/preceding-sibling::*
第二个问题

   /*/*/tr[.='B']
           /following-sibling::*
             [count(.|/*/*/tr[. ='C']/preceding-sibling::*)
             =
              count(/*/*/tr[. ='C']/preceding-sibling::*)
             ]
<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>
   /*/*/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: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>
<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>
我的问题现在开始了。我想写一个表达式,它将 只返回
标记后面的第一组元素,不管还有多少组 跟着它

同样存在一个选择这些元素的XPath表达式

   /*/*/tr[.='B']
           /following-sibling::*
             [count(.|/*/*/tr[. ='C']/preceding-sibling::*)
             =
              count(/*/*/tr[. ='C']/preceding-sibling::*)
             ]
<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>
   /*/*/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: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>
<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[.='B']
           /following-sibling::*
             [count(.|/*/*/tr[. ='C']/preceding-sibling::*)
             =
              count(/*/*/tr[. ='C']/preceding-sibling::*)
             ]
<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>
   /*/*/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: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>
<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
元素的所有后续同级
tr
元素(满足许多条件),该元素的
属性具有字符串值
“类”
,并且其第一个后续元素同级是没有属性的
tr

这些选定的
tr
元素也满足两个条件:1)它们没有任何属性;2)它们只有一个前面的同级
tr
元素,其
class
属性具有字符串值
“theClass”

下面是基于XSLT的验证:

   /*/*/tr[.='B']
           /following-sibling::*
             [count(.|/*/*/tr[. ='C']/preceding-sibling::*)
             =
              count(/*/*/tr[. ='C']/preceding-sibling::*)
             ]
<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>
   /*/*/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: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>
<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>

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

   /*/*/tr[.='B']
           /following-sibling::*
             [count(.|/*/*/tr[. ='C']/preceding-sibling::*)
             =
              count(/*/*/tr[. ='C']/preceding-sibling::*)
             ]
<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>
   /*/*/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: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>
<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>

A.
B
1.
2.
3.
4.
5.
6.
再次输出所需和正确选择的元素:

<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>
<tr>1</tr>
<tr>2</tr>
<tr>3</tr>
<tr>4</tr>
<tr>5</tr>
<tr>1</tr>
<tr>2</tr>
<tr>3</tr>
<tr>4</tr>
<tr>5</tr>
<tr>6</tr>
1
2.
3.
4.
5.
6.

我不明白你的意思。预期的结果是什么?@ChuckSavage我希望第一个HTML返回元素1,2,3,4,5,第二个HTML返回元素elemenets 1,2,3,4,5,6。非常感谢,它很有效。你能解释一下最后的表达方式吗?我不确定我是否理解它。谢谢大家!@不客气。我编辑了答案,并为这两种表达添加了解释。