Réponses:
<xsl:call-template>
est un équivalent proche de l'appel d'une fonction dans un langage de programmation traditionnel.
Vous pouvez définir des fonctions dans XSLT, comme celle-ci simple qui génère une chaîne.
<xsl:template name="dosomething">
<xsl:text>A function that does something</xsl:text>
</xsl:template>
Cette fonction peut être appelée via <xsl:call-template name="dosomething">
.
<xsl:apply-templates>
est un peu différent et c'est la vraie puissance de XSLT: il prend n'importe quel nombre de nœuds XML (quoi que vous définissiez dans l' select
attribut), les itère ( c'est important: apply-templates fonctionne comme une boucle! ) et trouve les modèles correspondants pour eux:
<!-- 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>
De cette façon, vous abandonnez un peu de contrôle au processeur XSLT - ce n'est pas vous qui décidez où va le flux du programme, mais le processeur le fait en trouvant la correspondance la plus appropriée pour le nœud qu'il traite actuellement.
Si plusieurs modèles peuvent correspondre à un nœud, celui avec l'expression de correspondance la plus spécifique l'emporte. S'il existe plus d'un modèle correspondant avec la même spécificité, celui déclaré en dernier l'emporte.
Vous pouvez vous concentrer davantage sur le développement de modèles et avoir besoin de moins de temps pour faire de la «plomberie». Vos programmes deviendront plus puissants et modulaires, moins profondément imbriqués et plus rapides (car les processeurs XSLT sont optimisés pour la correspondance de modèles).
Un concept à comprendre avec XSLT est celui du "nœud actuel". Avec <xsl:apply-templates>
le noeud courant se déplace à chaque itération, alors que <xsl:call-template>
ne change pas le noeud courant. C'est-à-dire que le .
dans un modèle appelé fait référence au même nœud que le .
dans le modèle appelant. Ce n'est pas le cas avec apply-templates.
C'est la différence fondamentale. Il y a d'autres aspects des modèles qui affectent leur comportement: Leur mode
et priority
, le fait que les modèles peuvent avoir à la fois un name
et un match
. Cela a également un impact si le modèle a été importé ( <xsl:import>
) ou non. Ce sont des utilisations avancées et vous pouvez les gérer lorsque vous y arrivez.
<xsl:apply-templates>
se comporte comme une boucle. Les différences d'implémentation du côté du processeur XSLT ne m'affecteront pas en tant que programmeur XSLT, le résultat est absolument le même pour les implémentations parallélisées et itératives. Mais pour un débutant XSLT avec un fond impératif, cela aide à envisager <xsl:apply-templates>
comme une sorte de boucle for-each, même si - techniquement - ce n'est pas le cas.
Pour ajouter à la bonne réponse de @Tomalak:
Voici quelques différences importantes et non mentionnées :
xsl:apply-templates
est beaucoup plus riche et plus profond que xsl:call-templates
et même à partir de xsl:for-each
, simplement parce que nous ne savons pas quel code sera appliqué sur les nœuds de la sélection - dans le cas général, ce code sera différent pour différents nœuds de la liste de nœuds.
Le code qui sera appliqué peut être écrit bien après l'écriture du xsl:apply template
s et par des personnes qui ne connaissent pas l'auteur original.
L' implémentation par la bibliothèque FXSL des fonctions d'ordre supérieur (HOF) dans XSLT ne serait pas possible si XSLT n'avait pas l' <xsl:apply-templates>
instruction.
Résumé : Les modèles et les <xsl:apply-templates>
instructions expliquent comment XSLT implémente et traite le polymorphisme.
Référence : Voir l'intégralité de ce fil: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html
xsl:apply-templates
est généralement (mais pas nécessairement) utilisé pour traiter tout ou un sous-ensemble des enfants du nœud actuel avec tous les modèles applicables. Cela prend en charge la récursivité de l'application XSLT qui correspond à la (possible) récursivité du XML traité.
xsl:call-template
d'autre part, cela ressemble beaucoup plus à un appel de fonction normal. Vous exécutez exactement un modèle (nommé), généralement avec un ou plusieurs paramètres.
J'utilise donc xsl:apply-templates
si je veux intercepter le traitement d'un nœud intéressant et (généralement) injecter quelque chose dans le flux de sortie. Un exemple typique (simplifié) serait
<xsl:template match="foo">
<bar>
<xsl:apply-templates/>
</bar>
</xsl:template>
alors que xsl:call-template
je résous généralement des problèmes tels que l'ajout du texte de certains sous-nœuds ensemble, la transformation de certains ensembles de nœuds en texte ou d'autres ensembles de nœuds, etc. - tout ce pour quoi vous écririez une fonction spécialisée et réutilisable.
Comme remarque supplémentaire au texte de votre question spécifique:
<xsl:call-template name="nodes"/>
Cela appelle un modèle qui est nommé «nœuds»:
<xsl:template name="nodes">...</xsl:template>
C'est une sémantique différente de:
<xsl:apply-templates select="nodes"/>
... qui applique tous les modèles à tous les enfants de votre nœud XML actuel dont le nom est «nœuds».
La fonctionnalité est en effet similaire (en dehors de la sémantique d'appel, où call-template
nécessite un name
attribut et un modèle de noms correspondant).
Cependant, l'analyseur ne s'exécutera pas de la même manière.
Depuis MSDN :
Contrairement à
<xsl:apply-templates>
,<xsl:call-template>
ne modifie pas le nœud actuel ou la liste de nœuds actuelle.
<xsl:apply-templates>
doit être implémentée en boucle - au contraire, elle peut être implémentée en parallèle, car les différentes applications sur les différents nœuds de la liste de nœuds sont absolument indépendantes les unes des autres.