Respostas:
<xsl:call-template>
é quase o equivalente a chamar uma função em uma linguagem de programação tradicional.
Você pode definir funções em XSLT, como este simples que produz uma string.
<xsl:template name="dosomething">
<xsl:text>A function that does something</xsl:text>
</xsl:template>
Esta função pode ser chamada via <xsl:call-template name="dosomething">
.
<xsl:apply-templates>
é um pouco diferente e nele está o verdadeiro poder do XSLT: ele pega qualquer número de nós XML (o que quer que você defina no select
atributo), os itera ( isso é importante: o apply-templates funciona como um loop! ) e encontra os modelos correspondentes para eles:
<!-- sample XML snippet -->
<xml>
<foo /><bar /><baz />
</xml>
<!-- sample XSLT snippet -->
<xsl:template match="xml">
<xsl:apply-templates select="*" /> <!-- three nodes selected here -->
</xsl:template>
<xsl:template match="foo"> <!-- will be called once -->
<xsl:text>foo element encountered</xsl:text>
</xsl:template>
<xsl:template match="*"> <!-- will be called twice -->
<xsl:text>other element countered</xsl:text>
</xsl:template>
Dessa forma, você cede um pouco de controle ao processador XSLT - não você decide para onde o fluxo do programa vai, mas o processador o faz encontrando a correspondência mais apropriada para o nó que está processando no momento.
Se vários modelos podem corresponder a um nó, aquele com a expressão de correspondência mais específica vence. Se houver mais de um modelo correspondente com a mesma especificidade, o declarado por último vence.
Você pode se concentrar mais no desenvolvimento de modelos e precisa de menos tempo para fazer o "encanamento". Seus programas se tornarão mais poderosos e modularizados, menos profundamente aninhados e mais rápidos (pois os processadores XSLT são otimizados para correspondência de modelos).
Um conceito a ser entendido com XSLT é o de "nó atual". Com <xsl:apply-templates>
o nó atual, segue em frente com cada iteração, enquanto <xsl:call-template>
não muda o nó atual. Ou seja, .
dentro de um modelo chamado refere-se ao mesmo nó .
do modelo de chamada. Este não é o caso com os modelos de aplicação.
Essa é a diferença básica. Existem alguns outros aspectos dos modelos que afetam seu comportamento: Seu mode
e priority
, o fato de que os modelos podem ter tanto a name
quanto a match
. Também tem um impacto se o modelo foi importado ( <xsl:import>
) ou não. Esses são usos avançados e você poderá lidar com eles quando chegar lá.
<xsl:apply-templates>
se comporta como um loop. As diferenças de implementação na extremidade do processador XSLT não me afetarão como um programador XSLT, o resultado é absolutamente o mesmo para implementações paralelizadas e iterativas. Mas, para um novato em XSLT com um histórico imperativo, é útil imaginar <xsl:apply-templates>
como uma espécie de loop for-each, mesmo que - tecnicamente - não seja.
Para adicionar à boa resposta de @Tomalak:
Aqui estão algumas diferenças importantes e não mencionadas :
xsl:apply-templates
é muito mais rico e profundo do que xsl:call-templates
e até mesmo de xsl:for-each
, simplesmente porque não sabemos qual código será aplicado nos nós da seleção - no caso geral, esse código será diferente para nós diferentes da lista de nós.
O código que será aplicado pode ser escrito bem depois que o xsl:apply template
s foi escrito e por pessoas que não conhecem o autor original.
A implementação da biblioteca FXSL de funções de ordem superior (HOF) em XSLT não seria possível se XSLT não tivesse a <xsl:apply-templates>
instrução.
Resumo : os modelos e a <xsl:apply-templates>
instrução são como o XSLT implementa e lida com o polimorfismo.
Referência : Veja este tópico completo: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html
xsl:apply-templates
é geralmente (mas não necessariamente) usado para processar todos ou um subconjunto de filhos do nó atual com todos os modelos aplicáveis. Isso suporta a recursividade do aplicativo XSLT que está correspondendo à (possível) recursividade do XML processado.
xsl:call-template
por outro lado, é muito mais parecido com uma chamada de função normal. Você executa exatamente um modelo (nomeado), geralmente com um ou mais parâmetros.
Então, eu uso xsl:apply-templates
se quero interceptar o processamento de um nó interessante e (geralmente) injetar algo no fluxo de saída. Um exemplo típico (simplificado) seria
<xsl:template match="foo">
<bar>
<xsl:apply-templates/>
</bar>
</xsl:template>
enquanto com xsl:call-template
eu normalmente resolvo problemas como adicionar o texto de alguns subnós juntos, transformar conjuntos de nós selecionados em texto ou outros conjuntos de nós e semelhantes - qualquer coisa para a qual você escreveria uma função especializada reutilizável.
Como uma observação adicional ao texto de sua pergunta específica:
<xsl:call-template name="nodes"/>
Isso chama um modelo chamado 'nós':
<xsl:template name="nodes">...</xsl:template>
Esta é uma semântica diferente de:
<xsl:apply-templates select="nodes"/>
... que aplica todos os modelos a todos os filhos de seu nó XML atual cujo nome é 'nós'.
A funcionalidade é de fato semelhante (além da semântica de chamada, onde call-template
requer um name
atributo e um modelo de nomes correspondente).
No entanto, o analisador não será executado da mesma maneira.
Do MSDN :
Ao contrário
<xsl:apply-templates>
,<xsl:call-template>
não altera o nó atual ou a lista de nós atual.
<xsl:apply-templates>
deva ser implementada como um loop - pelo contrário, ela pode ser implementada em paralelo, porque as diferentes aplicações nos diferentes nós da lista de nós são absolutamente independentes umas das outras.