使用:
($yourNode/preceding::Q | $yourNode/ancestor::Q)/@id
基于 XSLT 的验证:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vQg" select="(//Q[@id='g'])[1]"/>
<xsl:variable name="vQf" select="(//Q[@id='f'])[1]"/>
<xsl:template match="/">
"Preceding" $vQg:
<xsl:for-each select=
"($vQg/preceding::Q | $vQg/ancestor::Q)/@id">
<xsl:value-of select="concat(., ' ')"/>
</xsl:for-each>
=====================
"Preceding" $vQf:
<xsl:for-each select=
"($vQf/preceding::Q | $vQf/ancestor::Q)/@id">
<xsl:value-of select="concat(., ' ')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<root>
<Q id="a">1</Q>
<Q id="b">2</Q>
<Q id="c">3</Q>
<x>
<Q id="d">3.1</Q>
<Q id="e">3.2</Q>
<Q id="f">3.3</Q>
</x>
<Q id="g">4</Q>
<Q id="h">5</Q>
</root>
XPath 表达式被评估两次(对于Q
您问题中的两个元素),结果的字符串值以空格分隔输出:
"Preceding" $vQg:
a b c d e f
=====================
"Preceding" $vQf:
a b c d e
说明:
preceding::
轴不会按文档顺序选择所有前面的节点——要做到这一点还需要使用轴ancestor::
。
来自W3C XPath 1.0 规范:
"•前轴包含与上下文节点在同一文档中按文档顺序位于上下文节点之前的所有节点,不包括任何祖先,不包括属性节点和命名空间节点"