XPath:选择所有以下兄弟姐妹,直到另一个兄弟姐妹

时间:2010-01-29 12:11:38

标签: xpath

以下是我的xml的摘录:

<node/>
<node/>
<node id="1">content</node>
<node/>
<node/>
<node/>
<node id="2">content</node>
<node/>
<node/>

我位于node[@id='1']。我需要一个Xpath来匹配所有<node/>元素,直到下一个非空节点(此处为node[@id='2'])。


修改 @id属性只是为了更清楚地解释我的问题,但不是我原来的XML。我需要一个不使用@id属性的解决方案。


希望在node[@id='2']之后匹配空的兄弟姐妹,所以我不能使用天真的following-sibling::node[text()='']

我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:21)

可以这样做:

../node[not(text()) and preceding-sibling::node[@id][1][@id='1']]

其中'1'是当前节点的id(动态生成表达式)。

表达说:

  • 从当前上下文转到父
  • 选择那些
  • 的子节点
  • 没有文字和
  • 来自所有“具有id的兄弟节点”,第一个必须具有1
  • 的id

如果您在XSLT中,可以从以下兄弟轴中进行选择,因为您可以使用current()函数:

<!-- the for-each is merely to switch the current node -->
<xsl:for-each select="node[@id='1']">
  <xsl:copy-of select="
    following-sibling::node[
      not(text()) and
      generate-id(preceding-sibling::node[@id][1])
      =
      generate-id(current())
    ]
  " />
</xsl:for-each>
使用密钥

或更简单(也更高效):

<xsl:key 
  name="kNode" 
  match="node[not(text())]" 
  use="generate-id(preceding-sibling::node[@id][1])"
/>

<xsl:copy-of select="key('kNode', generate-id(node[@id='1']))" />

答案 1 :(得分:9)

比接受的答案简单:

//node[@id='1']/following-sibling::node[following::node[@id='2']]
  • 在ID为“1”
  • 的任何位置查找节点
  • 现在找到以下所有兄弟node元素
  • ...但只有当这些元素在其后面某处有node id="2"之后。

使用更清晰的测试文档(以及合法的id值)显示在行动中:

xml = '<root>
<node id="a"/><node id="b"/>
<node id="c">content</node>
<node id="d"/><node id="e"/><node id="f"/>
<node id="g">content</node>
<node id="h"/><node id="i"/>
</root>'

# A Ruby library that uses libxml2; http://nokogiri.org
require 'nokogiri'; doc = Nokogiri::XML(xml)

expression = "//node[@id='c']/following-sibling::node[following::node[@id='g']]"
puts doc.xpath(expression)
#=> <node id="d"/>
#=> <node id="e"/>
#=> <node id="f"/>

答案 2 :(得分:8)

XPath 2.0具有运算符'&lt;&lt;'和'&gt;&gt;'如果node1以文档顺序位于node2之前,则node1 << node2为真。 所以基于XSLT 2.0样式表中的XPath 2.0,当前节点是节点[@id ='1']你可以使用

  following-sibling::node[not(text()) and . << current()/following-sibling::node[@od][1]]

这也需要来自XSLT的current()函数,所以这就是为什么我说“在XSLT 2.0样式表中使用XPath 2.0”。上面的语法是纯XPath,在XSLT样式表中你需要转义'&lt;&lt;' as'&amp; lt;&amp; lt;'。