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

glm*_*ndr 36 xpath

这是我的xml的摘录:

<node/>
<node/>
<node id="1">content</node>
<node/>
<node/>
<node/>
<node id="2">content</node>
<node/>
<node/>
Run Code Online (Sandbox Code Playgroud)

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


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


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

我怎样才能做到这一点?

Tom*_*lak 21

可以这样做:

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

where '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>
Run Code Online (Sandbox Code Playgroud)

或者使用密钥更简单(也更有效):

<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']))" />
Run Code Online (Sandbox Code Playgroud)

  • @subtenante:这就是为什么当你想要解决真正的问题时,你永远不应该编写你的代码示例. (10认同)

Phr*_*ogz 10

比接受的答案简单:

//node[@id='1']/following-sibling::node[following::node[@id='2']]
Run Code Online (Sandbox Code Playgroud)
  • 找到ID为"1"的任何位置的节点
  • 现在找到以下所有兄弟node元素
  • ......但只有当这些元素也有一个nodeid="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"/>
Run Code Online (Sandbox Code Playgroud)


Mar*_*nen 8

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

  following-sibling::node[not(text()) and . << current()/following-sibling::node[@od][1]]
Run Code Online (Sandbox Code Playgroud)

这也需要来自XSLT的current()函数,所以这就是为什么我说"在XSLT 2.0样式表中使用XPath 2.0".上面的语法是纯XPath,在XSLT样式表中,您需要将'<<'转换为'<<'.