XSLT 1.0:用call-template还是apply-templates?

本文探讨了XSLT中apply-templates与call-template的使用区别,apply-templates允许通过select属性选择特定节点集进行转换,而call-template则适合于递归调用等复杂操作。

在五一放假前和Mike讨论到这个问题,之前我用了比较多的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.

我觉得概括的不错,言简意赅,就以此作为结尾吧。

帮我简化这段代码:<xsl:template match="*[contains(@class,' topic/li ')]" name="topic.li"> <xsl:variable name="flagrules"> <xsl:call-template name="getrules"/> </xsl:variable> <xsl:variable name="conflictexist"> <xsl:call-template name="conflict-check"> <xsl:with-param name="flagrules" select="$flagrules"/> </xsl:call-template> </xsl:variable> <li> <xsl:choose> <xsl:when test="$styleSheet ='12' or $styleSheet ='13' or $styleSheet='14' or $styleSheet ='15' or $styleSheet ='16'"> <div> <xsl:variable name="lowerCaseLang"> <xsl:call-template name="getLowerCaseLang"/> </xsl:variable> <xsl:if test="parent::*[contains(@class,' topic/ol ')] and $styleSheet='1' and ($lowerCaseLang='ar-eg' or $lowerCaseLang='ar-sa')"> <span class="arLiNumber"><xsl:number value="count(preceding-sibling::*[contains(@class,' topic/li ')]) + 1" format="١.  "></xsl:number></span> </xsl:if> <!-- handle non-compact list items --> <xsl:if test="parent::*/@compact='no'"> <xsl:attribute name="class">liexpand</xsl:attribute> </xsl:if> <xsl:call-template name="commonattributes"/> <xsl:call-template name="setidaname"/> <xsl:call-template name="gen-style"> <xsl:with-param name="conflictexist" select="$conflictexist"></xsl:with-param> <xsl:with-param name="flagrules" select="$flagrules"></xsl:with-param> </xsl:call-template> <xsl:call-template name="start-flagit"> <xsl:with-param name="flagrules" select="$flagrules"></xsl:with-param> </xsl:call-template> <xsl:call-template name="revblock"> <xsl:with-param name="flagrules" select="$flagrules"></xsl:with-param> </xsl:call-template> <xsl:call-template name="end-flagit"> <xsl:with-param name="flagrules" select="$flagrules"></xsl:with-param> </xsl:call-template> </div> </xsl:when> <xsl:otherwise> <xsl:variable name="lowerCaseLang"> <xsl:call-template name="getLowerCaseLang"/> </xsl:variable> <xsl:if test="parent::*[contains(@class,' topic/ol ')] and $styleSheet='1' and ($lowerCaseLang='ar-eg' or $lowerCaseLang='ar-sa')"> <span class="arLiNumber"><xsl:number value="count(preceding-sibling::*[contains(@class,' topic/li ')]) + 1" format="١.  "></xsl:number></span> </xsl:if> <!-- handle non-compact list items --> <xsl:if test="parent::*/@compact='no'"> <xsl:attribute name="class">liexpand</xsl:attribute> </xsl:if> <xsl:call-template name="commonattributes"/> <xsl:call-template name="setidaname"/> <xsl:call-template name="gen-style"> <xsl:with-param name="conflictexist" select="$conflictexist"></xsl:with-param> <xsl:with-param name="flagrules" select="$flagrules"></xsl:with-param> </xsl:call-template> <xsl:call-template name="start-flagit"> <xsl:with-param name="flagrules" select="$flagrules"></xsl:with-param> </xsl:call-template> <xsl:call-template name="revblock"> <xsl:with-param name="flagrules" select="$flagrules"></xsl:with-param> </xsl:call-template> <xsl:call-template name="end-flagit"> <xsl:with-param name="flagrules" select="$flagrules"></xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </li><xsl:value-of select="$newline"/> </xsl:template>
08-14
这个也是公式的xsl<?xml version='1.0' encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://www.w3.org/1998/Math/MathML" version='1.0'> <!-- ====================================================================== --> <!-- $Id: tokens.xsl,v 1.7 2003/06/10 12:24:05 shade33 Exp $ This file is part of the XSLT MathML Library distribution. See ./README or http://www.raleigh.ru/MathML/mmltex for copyright and other information --> <!-- ====================================================================== --> <xsl:template match="m:mi|m:mn|m:mo|m:mtext|m:ms"> <xsl:call-template name="CommonTokenAtr"/> </xsl:template> <!-- 3.2.9 mglyph --> <xsl:template match="m:mglyph"> <xsl:text>\textcolor{red}{</xsl:text> <xsl:value-of select="@alt"/> <xsl:text>}</xsl:text> </xsl:template> <xsl:template name="mi"> <xsl:choose> <xsl:when test="string-length(normalize-space(.))>1 and not(@mathvariant)"> <xsl:text>\mathrm{</xsl:text> <xsl:apply-templates/> <xsl:text>}</xsl:text> </xsl:when> <xsl:otherwise> <xsl:apply-templates/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="mn"> <xsl:choose> <xsl:when test="string(number(.))='NaN' and not(@mathvariant)"> <xsl:text>\mathrm{</xsl:text> <xsl:apply-templates/> <xsl:text>}</xsl:text> </xsl:when> <xsl:otherwise> <xsl:apply-templates/> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- 3.2.5 Math Operator --> <xsl:template name="mo"> <xsl:if test="translate(normalize-space(.),'()[]}|','{{{{{{')='{'"> <xsl:choose> <xsl:when test="not(@stretchy='false') and count(preceding-sibling::m:mo[translate(normalize-space(.),'()[]}|','{{{{{{')='{'])mod 2=0 and following-sibling::m:mo[1][not(@stretchy='false')][translate(normalize-space(.),'()[]}|','{{{{{{')='{']"> <xsl:text>\left</xsl:text> </xsl:when> <xsl:when test="not(@stretchy='false') and count(preceding-sibling::m:mo[translate(normalize-space(.),'()[]}|','{{{{{{')='{'])mod 2=1 and preceding-sibling::m:mo[1][not(@stretchy='false')][translate(normalize-space(.),'()[]}|','{{{{{{')='{']"> <xsl:text>\right</xsl:text> </xsl:when> </xsl:choose> </xsl:if> <xsl:apply-templates/> </xsl:template> <xsl:template name="mtext"> <xsl:variable name="content"> <xsl:call-template name="replaceMtextEntities"> <xsl:with-param name="content" select="normalize-space(.)"/> </xsl:call-template> </xsl:variable> <xsl:text>\text{</xsl:text> <xsl:value-of select="$content"/> <xsl:text>}</xsl:text> </xsl:template> <xsl:template match="m:mspace"> <xsl:text>\phantom{\rule</xsl:text> <xsl:if test="@depth"> <xsl:text>[-</xsl:text> <xsl:value-of select="@depth"/> <xsl:text>]</xsl:text> </xsl:if> <xsl:text>{</xsl:text> <xsl:if test="not(@width)"> <xsl:text>0ex</xsl:text> </xsl:if> <xsl:value-of select="@width"/> <xsl:text>}{</xsl:text> <xsl:if test="not(@height)"> <xsl:text>0ex</xsl:text> </xsl:if> <xsl:value-of select="@height"/> <xsl:text>}}</xsl:text> </xsl:template> <xsl:template name="ms"> <xsl:choose> <xsl:when test="@lquote"><xsl:value-of select="@lquote"/></xsl:when> <xsl:otherwise><xsl:text>''</xsl:text></xsl:otherwise> </xsl:choose><xsl:apply-templates/><xsl:choose> <xsl:when test="@rquote"><xsl:value-of select="@rquote"/></xsl:when> <xsl:otherwise><xsl:text>''</xsl:text></xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="CommonTokenAtr"> <xsl:if test="@mathbackground"> <xsl:text>\colorbox[rgb]{</xsl:text> <xsl:call-template name="color"> <xsl:with-param name="color" select="@mathbackground"/> </xsl:call-template> <xsl:text>}{$</xsl:text> </xsl:if> <xsl:if test="@color[not(@mathcolor)] or @mathcolor"> <!-- Note: @color is deprecated in MathML 2.0 --> <xsl:text>\textcolor[rgb]{</xsl:text> <xsl:call-template name="color"> <xsl:with-param name="color" select="@color|@mathcolor"/> </xsl:call-template> <xsl:text>}{</xsl:text> </xsl:if> <xsl:if test="@mathvariant"> <xsl:choose> <xsl:when test="@mathvariant='normal'"> <xsl:text>\mathrm{</xsl:text> </xsl:when> <xsl:when test="@mathvariant='bold'"> <xsl:text>\mathbf{</xsl:text> </xsl:when> <xsl:when test="@mathvariant='italic'"> <xsl:text>\mathit{</xsl:text> </xsl:when> <xsl:when test="@mathvariant='bold-italic'"> <!-- not supported --> <xsl:text>\mathit{</xsl:text> <xsl:message>The value bold-italic for mathvariant is not supported</xsl:message> </xsl:when> <xsl:when test="@mathvariant='double-struck'"> <!-- Required amsfonts --> <xsl:text>\mathbb{</xsl:text> </xsl:when> <xsl:when test="@mathvariant='bold-fraktur'"> <!-- not supported --> <xsl:text>\mathfrak{</xsl:text> <xsl:message>The value bold-fraktur for mathvariant is not supported</xsl:message> </xsl:when> <xsl:when test="@mathvariant='script'"> <xsl:text>\mathcal{</xsl:text> </xsl:when> <xsl:when test="@mathvariant='bold-script'"> <!-- not supported --> <xsl:text>\mathcal{</xsl:text> <xsl:message>The value bold-script for mathvariant is not supported</xsl:message> </xsl:when> <xsl:when test="@mathvariant='fraktur'"> <!-- Required amsfonts --> <xsl:text>\mathfrak{</xsl:text> </xsl:when> <xsl:when test="@mathvariant='sans-serif'"> <xsl:text>\mathsf{</xsl:text> </xsl:when> <xsl:when test="@mathvariant='bold-sans-serif'"> <!-- not supported --> <xsl:text>\mathsf{</xsl:text> <xsl:message>The value bold-sans-serif for mathvariant is not supported</xsl:message> </xsl:when> <xsl:when test="@mathvariant='sans-serif-italic'"> <!-- not supported --> <xsl:text>\mathsf{</xsl:text> <xsl:message>The value sans-serif-italic for mathvariant is not supported</xsl:message> </xsl:when> <xsl:when test="@mathvariant='sans-serif-bold-italic'"> <!-- not supported --> <xsl:text>\mathsf{</xsl:text> <xsl:message>The value sans-serif-bold-italic for mathvariant is not supported</xsl:message> </xsl:when> <xsl:when test="@mathvariant='monospace'"> <xsl:text>\mathtt{</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>{</xsl:text> <xsl:message>Error at mathvariant attribute</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:if> <xsl:call-template name="selectTemplate"/> <xsl:if test="@mathvariant"> <xsl:text>}</xsl:text> </xsl:if> <xsl:if test="@color or @mathcolor"> <xsl:text>}</xsl:text> </xsl:if> <xsl:if test="@mathbackground"> <xsl:text>$}</xsl:text> </xsl:if> </xsl:template> <xsl:template name="selectTemplate"> <xsl:choose> <xsl:when test="local-name(.)='mi'"> <xsl:call-template name="mi"/> </xsl:when> <xsl:when test="local-name(.)='mn'"> <xsl:call-template name="mn"/> </xsl:when> <xsl:when test="local-name(.)='mo'"> <xsl:call-template name="mo"/> </xsl:when> <xsl:when test="local-name(.)='mtext'"> <xsl:call-template name="mtext"/> </xsl:when> <xsl:when test="local-name(.)='ms'"> <xsl:call-template name="ms"/> </xsl:when> </xsl:choose> </xsl:template> <xsl:template name="color"> <!-- NB: Variables colora and valueColor{n} only for Sablotron --> <xsl:param name="color"/> <xsl:variable name="colora" select="translate($color,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')"/> <xsl:choose> <xsl:when test="starts-with($colora,'#') and string-length($colora)=4"> <xsl:variable name="valueColor"> <xsl:call-template name="Hex2Decimal"> <xsl:with-param name="arg" select="substring($colora,2,1)"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="$valueColor div 15"/><xsl:text>,</xsl:text> <xsl:variable name="valueColor1"> <xsl:call-template name="Hex2Decimal"> <xsl:with-param name="arg" select="substring($colora,3,1)"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="$valueColor1 div 15"/><xsl:text>,</xsl:text> <xsl:variable name="valueColor2"> <xsl:call-template name="Hex2Decimal"> <xsl:with-param name="arg" select="substring($colora,4,1)"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="$valueColor2 div 15"/> </xsl:when> <xsl:when test="starts-with($colora,'#') and string-length($colora)=7"> <xsl:variable name="valueColor1"> <xsl:call-template name="Hex2Decimal"> <xsl:with-param name="arg" select="substring($colora,2,1)"/> </xsl:call-template> </xsl:variable> <xsl:variable name="valueColor2"> <xsl:call-template name="Hex2Decimal"> <xsl:with-param name="arg" select="substring($colora,3,1)"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="($valueColor1*16 + $valueColor2) div 255"/><xsl:text>,</xsl:text> <xsl:variable name="valueColor1a"> <xsl:call-template name="Hex2Decimal"> <xsl:with-param name="arg" select="substring($colora,4,1)"/> </xsl:call-template> </xsl:variable> <xsl:variable name="valueColor2a"> <xsl:call-template name="Hex2Decimal"> <xsl:with-param name="arg" select="substring($colora,5,1)"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="($valueColor1a*16 + $valueColor2a) div 255"/><xsl:text>,</xsl:text> <xsl:variable name="valueColor1b"> <xsl:call-template name="Hex2Decimal"> <xsl:with-param name="arg" select="substring($colora,6,1)"/> </xsl:call-template> </xsl:variable> <xsl:variable name="valueColor2b"> <xsl:call-template name="Hex2Decimal"> <xsl:with-param name="arg" select="substring($colora,7,1)"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="($valueColor1b*16 + $valueColor2b) div 255"/> </xsl:when> <!-- ======================= if color specifed as an html-color-name ========================================== --> <xsl:when test="$colora='aqua'"><xsl:text>0,1,1</xsl:text></xsl:when> <xsl:when test="$colora='black'"><xsl:text>0,0,0</xsl:text></xsl:when> <xsl:when test="$colora='blue'"><xsl:text>0,0,1</xsl:text></xsl:when> <xsl:when test="$colora='fuchsia'"><xsl:text>1,0,1</xsl:text></xsl:when> <xsl:when test="$colora='gray'"><xsl:text>.5,.5,.5</xsl:text></xsl:when> <xsl:when test="$colora='green'"><xsl:text>0,.5,0</xsl:text></xsl:when> <xsl:when test="$colora='lime'"><xsl:text>0,1,0</xsl:text></xsl:when> <xsl:when test="$colora='maroon'"><xsl:text>.5,0,0</xsl:text></xsl:when> <xsl:when test="$colora='navy'"><xsl:text>0,0,.5</xsl:text></xsl:when> <xsl:when test="$colora='olive'"><xsl:text>.5,.5,0</xsl:text></xsl:when> <xsl:when test="$colora='purple'"><xsl:text>.5,0,.5</xsl:text></xsl:when> <xsl:when test="$colora='red'"><xsl:text>1,0,0</xsl:text></xsl:when> <xsl:when test="$colora='silver'"><xsl:text>.75,.75,.75</xsl:text></xsl:when> <xsl:when test="$colora='teal'"><xsl:text>0,.5,.5</xsl:text></xsl:when> <xsl:when test="$colora='white'"><xsl:text>1,1,1</xsl:text></xsl:when> <xsl:when test="$colora='yellow'"><xsl:text>1,1,0</xsl:text></xsl:when> <xsl:otherwise> <xsl:message>Exception at color template</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="Hex2Decimal"> <xsl:param name="arg"/> <xsl:choose> <xsl:when test="$arg='f'"> <xsl:value-of select="15"/> </xsl:when> <xsl:when test="$arg='e'"> <xsl:value-of select="14"/> </xsl:when> <xsl:when test="$arg='d'"> <xsl:value-of select="13"/> </xsl:when> <xsl:when test="$arg='c'"> <xsl:value-of select="12"/> </xsl:when> <xsl:when test="$arg='b'"> <xsl:value-of select="11"/> </xsl:when> <xsl:when test="$arg='a'"> <xsl:value-of select="10"/> </xsl:when> <xsl:when test="translate($arg, '0123456789', '9999999999')='9'"> <!-- if $arg is number --> <xsl:value-of select="$arg"/> </xsl:when> <xsl:otherwise> <xsl:message>Exception at Hex2Decimal template</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="m:*/text()"> <xsl:call-template name="replaceEntities"> <xsl:with-param name="content" select="normalize-space()"/> </xsl:call-template> </xsl:template> </xsl:stylesheet>
10-21
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值