这是我之前主题的后续问题:
Please help me on understanding this XPath
我有一个XPath:
<xsl:value-of select="position()+count(preceding-sibling::*)-18"/>
目前我只能理解它的部分,比如position()。另外,我知道previous-sibling是在当前节点之前选择所有兄弟节点,但我不知道当它们如上所述组合时语句的意思。
有没有人可以帮助理解这个XPath?提前谢谢。
答案 0 :(得分:5)
你的表达是使用静态位置(来自输入源)和动态位置(来自当前节点列表)进行一些计算。
让我们看一些例子。假设这个样式表和这个输入:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="list">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:value-of select="concat(position(),' + ',
count(preceding-sibling::*),' = ',
position() +
count(preceding-sibling::*))"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<list>
<a/>
<b/>
<a/>
<b/>
</list>
输出:
<list>
<a>1 + 0 = 1</a>
<b>2 + 1 = 3</b>
<a>3 + 2 = 5</a>
<b>4 + 3 = 7</b>
</list>
现在,将第二条规则更改为match="a"
:
<list>
<a>1 + 0 = 1</a>
<a>3 + 2 = 5</a>
</list>
因此,模式不会更改当前节点列表
如果position()
处于模式中会怎样?让我们将规则更改为match="a[position()=2]"
:
<list>
<a>3 + 2 = 5</a>
</list>
奇怪?否。在XPath模式中,position()
针对其自己的上下文节点列表和轴方向。这种情况:child::a[position()=2]
表示第二个a
孩子。
这表明模式中的position()
使用的内容与内容模板中的position()
不同。
那么,如何更改当前上下文节点列表?好吧,apply-templates
和for-each
说明。
立即在apply-templates
指令添加一些select
属性,如select="a"
:
<list>
<a>2 + 2 = 4</a>
</list>
答案 1 :(得分:2)
position()
返回当前正在迭代的节点集中当前节点的位置。假设有四个<foo>
元素:
<xml>
<foo /><foo /><foo /><foo />
</xml>
并通过<xsl:apply-templates>
:
<xsl:template match="/xml">
<!-- this selects four nodes -->
<xsl:apply-templates select="foo" />
</xsl:template>
<!-- this runs four times -->
<xsl:template match="foo">
<xsl:value-of select="position()" />
</xsl:template>
然后输出"1234"
。
count()
计算节点集中的节点。
preceding-sibling::*
选择preceding-sibling
轴上的所有元素,如当前节点所示(除非当前节点是属性,因为属性在技术上没有前面的兄弟节点)
<xsl:value-of select="position()+count(preceding-sibling::*)-18"/>
现在应该是不言自明的。您可能缺少的XSLT概念是“当前节点”。当前节点是XSLT程序的执行上下文。始终有一个节点是当前节点,并且大多数XSLT / XPath操作隐式地在当前节点上工作。
答案 2 :(得分:2)
@Alejandro除外的所有答案都有相同的常见错误:
:
并非如此preceding-sibling::*
选择所有前兄弟节点。
它只选择所有前面的兄弟元素。
要选择所有在前兄弟节点,请使用:
preceding-sibling::node()
XPath中有这类节点:
根节点(表示为/
),在XPath 2.0中也表示为document-node()
元素节点。例如<a/>
文字节点。在<a> Hello </a>
中,文本节点是a
的唯一子节点,字符串值为“Hello”
评论节点。 <!-- This is a comment-->
处理指令节点。 <?someName I am a PI ?>
属性节点。在<a x="1"/>
x
是a
的唯一属性。
命名空间节点。 <a xmlns:my="my:namespace"/>
a
的命名空间节点的值为“my:namespace”,名称(前缀)为my
可以使用preceding-sibling::
轴选择前5种节点:
preceding-sibling::node()
选择1到5类的所有兄弟节点。
preceding-sibling::*
选择兄弟姐妹之前的所有元素
preceding-sibling::someName
选择兄弟姐妹之前名为“someName”的所有元素
preceding-sibling::text()
选择兄弟姐妹之前的所有文本节点(在混合内容中有用)
preceding-sibling::comment()
选择兄弟姐妹之前的所有评论节点。
preceding-sibling::processing-instruction()
选择所有前面的PI兄弟姐妹
preceding-sibling::processing-instruction('someName')
选择所有前面作为PI的兄弟姐妹并命名为“someName”。
答案 3 :(得分:1)
preceding-sibling::
是返回节点集的轴。在这种情况下,*
告诉所有前面的兄弟姐妹。 count()
计算节点集中的节点数。因此,表达式的这一部分为我们提供了与文档中显示的当前节点具有相同父节点的节点总数。
答案 4 :(得分:0)
position()
将计算一个数字,该数字表示正在评估的1个索引节点数组中的当前节点位置。称之为 n 。
preceding-sibling::*
将在当前节点之前评估兄弟节点的数量,并且计数就像它听起来的那样(并且很可能在此处等于 n -1)。
-18应该是不言而喻的:)所以你剩下的就是计算位置+前面兄弟姐妹的数量 - 18.这对于你想要的商业问题非常具体那个计算,但这就是你所拥有的。
答案 5 :(得分:0)
您的代码将生成一个等于的数字:
当前节点列表中的位置减去任何前一个兄弟节点的数量减去18。
一般来说,在您的示例中演示时,可以将不同的运算符组合成表达式。
注意:谨慎使用position()
,因为有时候当前的节点列表不容易看到。