XSL:递归与迭代

时间:2011-10-16 14:12:17

标签: xslt xslt-2.0 xpath-2.0

我正在尝试理解XSL对for-each的处理。最初我写了一个递归的选择值函数(过滤掉所有与正则表达式模式不匹配的字符串),如下所示:

<!-- Ver.1 -->
<xsl:function name="choose-values">
  <xsl:param name="values" />
  <xsl:param name="pattern" as="xs:string" />

  <xsl:choose>
    <xsl:when test="count($values) = 0" >
      <xsl:sequence select="()" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="tail"
                    select="choose-values(subsequence($values, 2), $pattern)" />
      <xsl:variable name="value" select="$values[1]" />
      <xsl:sequence select="if (matches($value, $pattern))
                            then ($value, $tail)
                            else $tail" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

然后我遇到了<xsl:for-each>并重新编写如下:

<!-- Ver.2 -->
<xsl:function name="choose-values">
  <xsl:param name="values" />
  <xsl:param name="pattern" as="xs:string" />

  <xsl:for-each select="$values">
      <xsl:if test="matches(., $pattern)">
        <xsl:sequence select="." />
      </xsl:if>
  </xsl:for-each>
</xsl:function>

这两个版本是否相同? (我的测试表明如此)。我在Ver.2中遗漏了一些边缘案例吗?

为了说清楚,这不是一个功课问题。我只是想通过一个简单的例子来理解差异(如果有的话)。

2 个答案:

答案 0 :(得分:4)

是的,这两个标本似乎相同。通常,您不需要在XSLT中进行递归,除非序列中的一个项目的处理在某种程度上取决于先前项目的处理。如果每个项目都独立于其他项目进行处理,那么您可以使用过滤器表达式或映射表达式,其中xsl:for-each是一个示例。以这种方式执行此操作(除了代码的可读性之外)的一个优点是,您不会强制执行处理顺序,这使优化器可以更自由地发挥其魔力。

答案 1 :(得分:1)

  

这两个版本是否相同? (我的测试表明如此)。我   在Ver.2中遗漏了一些边缘案例?

他们似乎产生相同的结果 - 很难说,因为两个代码段都不必要地复杂。

这可以通过

完成
<xsl:sequence select="$values[matches(., $pattern)]"/>