【问题标题】:XSLT : Looping from 1 to 60XSLT:从 1 到 60 循环
【发布时间】:2012-01-31 08:12:06
【问题描述】:

在 XSLT 中从 1 循环到 60 的最佳方法是什么? 我在网上研究,有一些模板可以做到这一点,有没有其他方法,例如内置函数?

【问题讨论】:

    标签: xslt


    【解决方案1】:

    在 XSLT 2.0 中,

    <xsl:for-each select="1 to 60">...</xsl:for-each>
    

    但我猜你一定在使用 XSLT 1.0,否则你不会问。

    在 XSLT 1.0 中,您应该使用递归:一个模板调用自身,计数器在每次调用时递增,当达到所需值时递归终止。

    XSLT 1.0 中也有一个解决方法:只要您的源文档包含至少 60 个节点,您就可以这样做

    <xsl:for-each select="(//node())[60 >= position()]">...</xsl:for-each>
    

    【讨论】:

    • 请问您如何访问当前值? (在您的第一个 sn-p 中的三个点中)尝试使用 &lt;xsl:variable name="currentCount" select="." /&gt; 但没有成功。
    • 使用position()
    【解决方案2】:

    简单递归在处理长序列时的问题是调用堆栈的空间经常变得不足,并且由于堆栈溢出而结束处理。这通常发生在序列长度 >= 1000 时。

    避免这种情况的一般技术(可用于任何 XSLT 处理器,即使它不识别尾递归)是 DVC(分而治之)样式递归

    这是一个成功打印从 1 到 1000000 (1M) 的数字的转换示例:

    <xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:output method="text"/>
    
         <xsl:template match="/">
          <xsl:call-template name="displayNumbers">
            <xsl:with-param name="pStart" select="1"/>
            <xsl:with-param name="pEnd" select="1000000"/>
          </xsl:call-template>
         </xsl:template>
    
         <xsl:template name="displayNumbers">
          <xsl:param name="pStart"/>
          <xsl:param name="pEnd"/>
    
          <xsl:if test="not($pStart > $pEnd)">
           <xsl:choose>
            <xsl:when test="$pStart = $pEnd">
              <xsl:value-of select="$pStart"/>
              <xsl:text>&#xA;</xsl:text>
            </xsl:when>
            <xsl:otherwise>
              <xsl:variable name="vMid" select=
               "floor(($pStart + $pEnd) div 2)"/>
              <xsl:call-template name="displayNumbers">
               <xsl:with-param name="pStart" select="$pStart"/>
               <xsl:with-param name="pEnd" select="$vMid"/>
              </xsl:call-template>
              <xsl:call-template name="displayNumbers">
               <xsl:with-param name="pStart" select="$vMid+1"/>
               <xsl:with-param name="pEnd" select="$pEnd"/>
              </xsl:call-template>
            </xsl:otherwise>
           </xsl:choose>
          </xsl:if>
         </xsl:template>
    </xsl:stylesheet>
    

    当应用于任何 XML 文档(未使用)时,此转换会产生所需的结果——从 1 到 1000000 的所有数字。

    您可以将此转换用于需要“做 N 次”的任何任务。

    【讨论】:

    • 您是 XSLT 大师!我不得不降级我的 XSLT 2.0 模板,而您的回答是救命稻草!
    【解决方案3】:

    foreach 循环内部非常简单的检查

    <xsl:if test="$maxItems > position()">
        do something
    </xsl:if>
    

    基于Dimitre Novatchev's 的回答。

    示例:

    <xsl:variable name="maxItems" select="10" />
    <xsl:variable name="sequence" select="any-sequence"/>
    
    <xsl:for-each select="$sequence">
    
        <!-- Maybe sort first -->
        <xsl:sort select="@sort-by" order="descending" />
    
        <!-- where the magic happens -->
        <xsl:if test="$maxItems > position()">
            do something
        </xsl:if>
    </xsl:for-each>
    

    【讨论】:

      【解决方案4】:

      V1.0 使用递归的基本示例是这样的:

      <xsl:template match="/">
      <Root>
            <!-- Main Call to MyTemplate -->
           <xsl:call-template name="MyTemplate" />
      </Root>
      </xsl:template>
      
      <xsl:template name="MyTemplate">
        <xsl:param name="index" select="1" />
        <xsl:param name="maxValue" select="60" />
      
        <MyCodeHere>
           <xsl:value-of select="$index"/>
        </MyCodeHere>
      
        <!-- &lt; represents "<" for html entities -->
        <xsl:if test="$index &lt; $maxValue">
          <xsl:call-template name="MyTemplate">
              <xsl:with-param name="index" select="$index + 1" />
              <xsl:with-param name="total" select="$maxValue" />
          </xsl:call-template>
        </xsl:if>
      </xsl:template>
      

      【讨论】:

      • 只使用一个参数并倒数会简单得多。
      • @Alejandro 你是对的。我更改了该验证。
      【解决方案5】:

      XSLT 基于模板工作,您需要一个模板来运行该循环。

      您需要构建一个接收开始值和结束值的模板,并在其中使用 start + 1 进行递归调用计算。当 $start 等于 $end 时,您会返回您的模板,而无需再次调用。

      在实践中:http://www.ibm.com/developerworks/xml/library/x-tiploop/index.html

      【讨论】:

        猜你喜欢
        • 2013-12-24
        • 1970-01-01
        • 1970-01-01
        • 2017-07-05
        • 1970-01-01
        • 2011-05-26
        • 1970-01-01
        • 1970-01-01
        • 2012-09-15
        相关资源
        最近更新 更多