以下是我的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()='']
。
我怎样才能做到这一点?
答案 0 :(得分:21)
你可以这样做:
../node[not(text()) and preceding-sibling::node[@id][1][@id='1']]
其中'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']]
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;'。