在XSLT 1.0中模仿位置(节点集)?

时间:2012-02-22 15:21:42

标签: xml xslt position xslt-2.0 xslt-1.0

XSLT 2.0提供了将节点集参数作为position()函数的一部分传递的好处。不幸的是,这在XSLT 1.0中不可用。有没有办法模仿这种行为?

例如,给定这个XML:

<wishlists>
  <wishlist name="Games">
    <product name="Crash Bandicoot"/>
    <product name="Super Mario Brothers"/>
    <product name="Sonic the Hedgehog"/>
  </wishlist>
  <wishlist name="Movies">
    <product name="Back to the Future"/>
  </wishlist>
</wishlists>

和这个XSLT 2.0:

<xsl:value-of select="position(/wishlists/wishlist/product)"/>

处理最终的“回到未来”节点时将返回值“4”。

不幸的是,我似乎能够使用XSLT 1.0获得的最接近的内容如下:

<xsl:template match="product">
  <xsl:value-of select="position()"/>
</xsl:template>

但是,我会在相同的“回到未来”节点中获得值“1”,而不是我真正想要的“4”值。

2 个答案:

答案 0 :(得分:4)

您可以使用preceding axis

这个XSLT 1.0样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="product">
    <product position="{count(preceding::product) + 1}">
      <xsl:apply-templates select="@*"/>
    </product>    
  </xsl:template>

</xsl:stylesheet>

应用于您的XML输入产生:

<wishlists>
   <wishlist name="Games">
      <product position="1" name="Crash Bandicoot"/>
      <product position="2" name="Super Mario Brothers"/>
      <product position="3" name="Sonic the Hedgehog"/>
   </wishlist>
   <wishlist name="Movies">
      <product position="4" name="Back to the Future"/>
   </wishlist>
</wishlists>

答案 1 :(得分:2)

  

XSLT 2.0提供了传递节点集参数作为其中一部分的好处   position()函数。

这种说法是错误的。 position()函数没有参数 - 无论是在XPath 1.0中还是在XPath 2.0中,XSLT 2.0都使用它。

你想要的是

count(preceding::product) +1

或者,可以使用xsl:number指令。

以下是这两种方法的演示

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:variable name="vLastProd" select=
  "//product[@name='Back to the Future']"/>

 <xsl:template match="/">
     <xsl:value-of select="count($vLastProd/preceding::product) +1"/>
=========
<xsl:text/>
   <xsl:apply-templates select="$vLastProd"/>
 </xsl:template>

 <xsl:template match="product">
   <xsl:number level="any" count="product"/>    
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时

<wishlists>
    <wishlist name="Games">
        <product name="Crash Bandicoot"/>
        <product name="Super Mario Brothers"/>
        <product name="Sonic the Hedgehog"/>
    </wishlist>
    <wishlist name="Movies">
        <product name="Back to the Future"/>
    </wishlist>
</wishlists>

使用两种方法获得所需的正确结果 - 并输出

4
=========
4

注意:如果不能直接输出xsl:number,则需要在变量体内捕获{{1}}的结果。