XSL: Recursion vs. Iteration
I'm trying to understand XSL's handling of for-each. Initially I wrote a recursive choose-values function (filters out all strings that do not match a regexp pattern) as follows:
<!-- 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" >
开发者_Go百科 <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>
Then I came across <xsl:for-each>
and rewrote it as follows:
<!-- 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>
Are these two versions equivalent? (my tests indicate so). Am I missing some edge-cases in Ver.2?
Just to make things clear, this is not a homework question. I'm just trying to understand the differences (if any) by using a simple example.
Yes, the two specimens appear to be equivalent. Generally, you don't need recursion in XSLT unless the processing of one item in the sequence depends in some way on the processing of previous items. If each item is processed independently of the others, then you can use filter expressions or mapping expressions, of which xsl:for-each is one example. An advantage of doing it this way (apart from readability of the code) is that you don't impose an order of processing, which gives the optimiser more freedom to work its magic.
Are these two versions equivalent? (my tests indicate so). Am I missing some edge-cases in Ver.2?
They seem to produce the same results -- it is difficult to say, because both code snippets are unnecessarily complicated.
This can be done simply by:
<xsl:sequence select="$values[matches(., $pattern)]"/>
精彩评论