计数器在for-each中,position()没用

use*_*554 2 xml xslt

如何在XSLT中使用不使用position()的计数器?例如:XML

<product type="A" name="pepe"/>
<product type="B" name="paco"/>
<product type="A" name="Juan"/>
<product type="B" name="Edu"/>
<product type="A" name="Lauren"/>
Run Code Online (Sandbox Code Playgroud)

我想按顺序显示所有类型"A":

1.pepe
2.Juan
3.Lauren
Run Code Online (Sandbox Code Playgroud)

xsl就是这样的

<xsl:for-each select="./products">
<xsl:if test="./products/product/@type="A"">
                    <tr>
<xsl:value-of select="position()"/>
<xsl:value-of select="./product/@name"/>  
                    </tr> 
</xsl:if>  
</xsl:for-each>
Run Code Online (Sandbox Code Playgroud)

Ian*_*rts 6

position()函数是上下文相关的 - 它为您提供当前节点在"当前节点列表"中的位置,即通过select当前for-each或表达式提取的节点列表apply-templates.所以,如果你做的事情

<xsl:for-each select="product">
  <xsl:if test="@type = 'A'">
    <li><xsl:value-of select="position()"/>: <xsl:value-of select="@name" /></li>
  </xsl:if>
</xsl:for-each>
Run Code Online (Sandbox Code Playgroud)

那么你将获得position()1,3和5的值,因为它select选择了所有五个产品元素.但是如果你把@type测试放在select表达式中:

<xsl:for-each select="product[@type = 'A']">
  <li><xsl:value-of select="position()"/>: <xsl:value-of select="@name" /></li>
</xsl:for-each>
Run Code Online (Sandbox Code Playgroud)

那么你将获得第1,2和3位,因为for-each它只处理三个产品元素@type,而不是全部五个.


在更复杂的情况下,你真的需要处理所有product元素(例如,如果你正在做与A型的人与事与B型的人不同的东西,但需要保持文档顺序),那么你需要用preceding-sibling::轴做技巧,例如

<xsl:if test="@type = 'A'">
  <xsl:value-of select="count(preceding-sibling::product[@type = 'A']) + 1" />
</xsl:if>
Run Code Online (Sandbox Code Playgroud)

显式计算前面product元素的数量与此相同@type.