0

我有以下xml:

<root>
    <a>value1</a>
    <b>value2</b>
    <c>value3</c>
    <a>value5</a>
    <d>value4</d>
    <b>value2</b>
    <b>value3</b>
    <a>value7</a>
</root>

a如果节点后面没有其他 b 节点,我想选择第一个兄弟//b[text()='value2']节点(在这种情况下,它将是<a>value5</a><a>value7</a>不应该选择)。

这样做的xpath是什么?

我正在使用 .net 4 和 xpath 1.0

更新

这就是我的出发点:我正在解析的文档有一个非常愚蠢的结构,可以这样描述

<root>
    <key>key-value</key>
    <some-other-nodes>some other values</some-other-nodes>
    <key>an other key value</key>
    <value>the value</value>
</root>

我描述的文档包含以下键值对:key-value->{null} an other key value->{the value}

如果键节点重复,则重置该key值。我需要一个 xpath 来选择特定键的值。因为在上面的示例中,第二个匹配的//b[text()='value2']后面是<b>value3</b>,所以键被重置为value3

4

2 回答 2

3

使用

   //b[text()='value2']
          /following-sibling::b[last()]
                 /following-sibling::a[1]
  |
   //b[text()='value2']
        [not(following-sibling::b)]
             /following-sibling::a[1]

这可以选择:

  1. 初始元素a的最后一个后续兄弟的第一个后续兄弟,或:bb

  2. 初始元素的第一个后续兄弟b,如果它没有任何其他后续兄弟b

这可以进一步简化为

  //b[text()='value2']/../b[last()]/following-sibling::a[1]

更新

当从提供的 XML 文档中//b[text()='value2']选择两个元素时,OP 还必须在 XPath 表达式的第一个位置步骤中指定他希望选择这两个元素中的哪一个。

这是一个更精确的 XPath 表达式$k在这种情况下,所选元素的数字(1 或 2)是b[. = 'value2']

  (//b[text()='value2'])[$k]/../b[last()]/following-sibling::a[1]

基于 XSLT 的验证

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

 <xsl:param name="k" select="1"/>

 <xsl:template match="/">
  <xsl:copy-of select=
  "(//b[text()='value2'])[$k]
      /../b[last()]
         /following-sibling::a[1]"/>
 </xsl:template>
</xsl:stylesheet>

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

<root>
    <a>value1</a>
    <b>value2</b>
    <c>value3</c>
    <a>value5</a>
    <d>value4</d>
    <b>value2</b>
    <b>value3</b>
    <a>value7</a>
</root>

对 XPath 表达式求值,并将由此求值选择的元素复制到输出

<a>value7</a>
于 2012-09-08T21:12:17.527 回答
2

这是应该工作的一个:

//b[.='value2']/following-sibling::a[preceding-sibling::b[1][.='value2']]

简而言之,它选择任何具有 value 的元素a之后的元素,其中最近的元素具有 value 。b'value2'b'value2'

编辑:现在我想一想,我什至不确定你是否需要第一部分。尝试这个:

//a[preceding-sibling::b[1][.='value2']]
于 2012-09-08T23:19:51.257 回答