是否可以在xslt中的for-each循环中保持计数

时间:2010-09-17 11:06:48

标签: .net xslt

我需要使用for-each循环遍历节点列表时保留与条件匹配的项目数。

我正在使用position(),但这是不正确的,因为我需要保持一个运行总计。

任何帮助都会非常感激。

3 个答案:

答案 0 :(得分:2)

我认为你必须将循环重写为递归。然后你可以将各种变量作为参数传递给下一个迭代。

答案 1 :(得分:1)

两种选择。有了这个输入:

<root>
    <number>1</number>
    <number>2</number>
    <number>3</number>
    <number>4</number>
    <number>5</number>
</root>

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="root">
        <result>
            <xsl:apply-templates/>
        </result>
    </xsl:template>
    <xsl:template match="number">
        <sum>
            <xsl:value-of select="sum(.|preceding-sibling::number)"/>
        </sum>
    </xsl:template>
</xsl:stylesheet>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="root">
        <result>
            <xsl:apply-templates select="*[1]"/>
        </result>
    </xsl:template>
    <xsl:template match="number">
        <xsl:param name="pCount" select="0"/>
        <sum>
            <xsl:value-of select="$pCount + ."/>
        </sum>
        <xsl:apply-templates select="following-sibling::*[1]">
            <xsl:with-param name="pCount" select="$pCount + ."/>
        </xsl:apply-templates>
    </xsl:template>
</xsl:stylesheet>

输出:

<result>
    <sum>1</sum>
    <sum>3</sum>
    <sum>6</sum>
    <sum>10</sum>
    <sum>15</sum>
</result>

注意:第一个带有'前置'轴。第二个通过节点处理在节点中传递param。

答案 2 :(得分:1)

  

我需要保留一些项目   循环时匹配条件   通过使用for-each的节点列表。

     

我正在使用position(),但这是   不正确,因为我需要保持运行   总

     

任何帮助都会非常感激。

在XSLT中,通常可以使用递归来完成。

FXSL提供了一种简单的方法来生成计算步骤的快照。

使用FXSL的scanlscanl1模板/功能

在XSLT 1.0中这个转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:myAdd="f:myAdd"
xmlns:myParam="f:myParam"
>
  <xsl:import href="scanl.xsl"/>
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <!-- To be applied on: numList.xml -->
  <myAdd:myAdd/>

  <myParam:myParam>0</myParam:myParam>

  <xsl:template match="/">
    <xsl:variable name="vFun" select="document('')/*/myAdd:*[1]"/>
    <xsl:variable name="vZero" select="document('')/*/myParam:*[1]"/>


    <xsl:call-template name="scanl">
      <xsl:with-param name="pFun" select="$vFun"/>
      <xsl:with-param name="pQ0" select="$vZero" />
      <xsl:with-param name="pList" select="/*/num"/>
    </xsl:call-template>

    - - - - - - - - - - -

     <xsl:call-template name="scanl1">
      <xsl:with-param name="pFun" select="$vFun"/>
      <xsl:with-param name="pList" select="/*/num"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template match="myAdd:*" mode="f:FXSL">
    <xsl:param name="pArg1" select="0"/>
    <xsl:param name="pArg2" select="0"/>

    <xsl:value-of select="$pArg1 + $pArg2"/>
  </xsl:template>
</xsl:stylesheet>

应用于此XML文档时

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

生成运行总和(sum()计算的中间结果):

<el>0</el>
<el>1</el>
<el>3</el>
<el>6</el>
<el>10</el>
<el>15</el>
<el>21</el>
<el>28</el>
<el>36</el>
<el>45</el>
<el>55</el>

    - - - - - - - - - - -

<el>01</el>
<el>3</el>
<el>6</el>
<el>10</el>
<el>15</el>
<el>21</el>
<el>28</el>
<el>36</el>
<el>45</el>
<el>55</el>

相应的XSLT 2.0转换,产生相同的结果,是

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
exclude-result-prefixes="f">
  <xsl:import href="../f/func-scanl.xsl"/>
  <xsl:import href="../f/func-Operators.xsl"/>

  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="/">
    <xsl:value-of separator=", " select="f:scanl(f:add(), 0, /*/*)"/>
     <xsl:text>&#xA;- - - - - - - - - - -&#xA;</xsl:text>
     <xsl:value-of separator=", "  select="f:scanl1(f:add(), /*/*)"/>
  </xsl:template>
</xsl:stylesheet>

您可以将具有两个参数的任何函数作为参数传递给f:scanl(),第一个是当前累积的结果,第二个是序列的当前项,作为最后一个传递给f:scanl()论点。 f:scanl()的第二个参数是初始累加器值。通常情况下,汇总0和计算产品1

f:scanl1()f:scan()几乎相同,但它要求其sequence参数为非空,并使用其第一项作为初始累加器值。