之前我用了比较多的call-template,后来说着说着,突然发现apply-templates在大部分的场景下比call-template好用,也更安全一些。
比如,apply-templates可以通过select属性来选择具体要匹配的node-set,如果不存在这样的node-set,就不进行转换,这就比call-template安全了一些,因为后者是直接调用,不管存不存在某些节点;其次,apply-templates和call-template一样,可以通过<xsl:param/>接受参数;此外,当我们定义多个template时,这些templates不可以有重复的name,但可以有重复的match,重复的template通过priority来确定该用哪个template来进行转换,如果多个template有相同的priority的话,则选择最后出现的那个。
似乎apply-templates功能比call-template强。就目前我所用到的普通转换来说,用apply-templates是比较安全的,并且可读性也会高一些。但是在XSLT 1.0中,如果想要实现像XSLT 2.0中function一样的功能的话,用call-template就比较方便了,比如递归调用(Recursive function)。下面是一个例子:
<xsl:template name=”longest-speech” as=”element(SPEECH)?”>
<xsl:param name=”list” as=”element(SPEECH)*”/>
<xsl:choose>
<xsl:when test=”$list”>
<xsl:variable name=”first” select=”count($list[1]/LINE)” as=”xs:integer”/>
<xsl:variable name=”longest-of-rest” as=”element(SPEECH)?”>
<xsl:call-template name=”longest-speech”>
<xsl:with-param name=”list” select=”$list[position()!=1]“/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test=”$first gt count($longest-of-rest/LINE)”>
<xsl:value-of select=”$list[1]“/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select=”$longest-of-rest”/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match=”/”>
<longest-speech>
<xsl:call-template name=”longest-speech”>
<xsl:with-param name=”list” select=”//SPEECH”/>
</xsl:call-template>
</longest-speech>
</xsl:template>
待转换的xml是:
<?xml version=”1.0″?>
<SCENE><TITLE>SCENE I. Venice. A street.</TITLE>
<STAGEDIR>Enter RODERIGO and IAGO</STAGEDIR>
<SPEECH>
<SPEAKER>RODERIGO</SPEAKER>
<LINE>Tush! never tell me; I take it much unkindly</LINE>
<LINE>That thou, Iago, who hast had my purse</LINE>
<LINE>As if the strings were thine, shouldst know of this.</LINE>
</SPEECH>
<SPEECH>
<SPEAKER>IAGO</SPEAKER>
<LINE>’Sblood, but you will not hear me:</LINE>
<LINE>If ever I did dream of such a matter, Abhor me.</LINE>
</SPEECH>
etc.
</SCENE>
在关于使用call-template和apply-templates的性能差别上,Sam Judson (Wrox 技术编辑)有言:
In terms of raw performance xsl:call-template is likely to be faster, as you are calling a specific named template, rather than telling the XSLT processor to pick the template which best matches.
There are certainly things you can do with xsl:call-template that you can’t do with xsl:apply-templates, such as recursive templates which are very powerful.
xsl:apply-templates is however the more flexible and extensible, due to its combined use of the match patterns, modes and priorities.
我觉得概括的不错,言简意赅,就以此作为结尾吧。