Was sind die Unterschiede zwischen "Call-Template" und "Apply-Templates" in XSL?

118

Ich bin neu in XSLT, daher bin ich etwas verwirrt über die beiden Tags.

<xsl:apply-templates name="nodes">

und

<xsl:call-template select="nodes"> 

Können Sie den Unterschied zwischen ihnen auflisten?

Venkat
quelle

Antworten:

166

<xsl:call-template> ist eine enge Entsprechung zum Aufrufen einer Funktion in einer traditionellen Programmiersprache.

Sie können Funktionen in XSLT definieren, wie diese einfache, die eine Zeichenfolge ausgibt.

<xsl:template name="dosomething">
  <xsl:text>A function that does something</xsl:text>
</xsl:template>

Diese Funktion kann über aufgerufen werden <xsl:call-template name="dosomething">.

<xsl:apply-templates>ist ein wenig anders und darin liegt die wahre Stärke von XSLT: Es benötigt eine beliebige Anzahl von XML-Knoten (was auch immer Sie im selectAttribut definieren ), iteriert sie ( dies ist wichtig: apply-templates funktioniert wie eine Schleife! ) und findet passende Vorlagen für Sie:

<!-- 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>

Auf diese Weise geben Sie dem XSLT-Prozessor ein wenig Kontrolle - Sie entscheiden nicht, wohin der Programmablauf geht, sondern der Prozessor findet die am besten geeignete Übereinstimmung für den Knoten, den er gerade verarbeitet.

Wenn mehrere Vorlagen mit einem Knoten übereinstimmen können, gewinnt die mit dem spezifischeren Übereinstimmungsausdruck. Wenn mehr als eine übereinstimmende Vorlage mit derselben Spezifität vorhanden ist, gewinnt die zuletzt deklarierte.

Sie können sich mehr auf die Entwicklung von Vorlagen konzentrieren und benötigen weniger Zeit für die "Installation". Ihre Programme werden leistungsfähiger und modularer, weniger tief verschachtelt und schneller (da XSLT-Prozessoren für den Vorlagenabgleich optimiert sind).

Ein mit XSLT zu verstehendes Konzept ist das des "aktuellen Knotens". Mit <xsl:apply-templates>dem aktuellen Knoten geht es mit jeder Iteration weiter, während <xsl:call-template>sich der aktuelle Knoten nicht ändert. Das heißt, das .innerhalb einer aufgerufenen Vorlage bezieht sich auf denselben Knoten wie das .in der aufrufenden Vorlage. Dies ist bei Apply-Vorlagen nicht der Fall.

Das ist der grundlegende Unterschied. Es gibt einige andere Aspekte von Vorlagen, die sich auf ihr Verhalten auswirken: Ihre modeund prioritydie Tatsache, dass Vorlagen sowohl a nameals auch a haben können match. Es hat auch Auswirkungen darauf, ob die Vorlage importiert wurde ( <xsl:import>) oder nicht. Dies sind fortgeschrittene Verwendungszwecke, mit denen Sie sich befassen können, wenn Sie dort ankommen.

Tomalak
quelle
5
@Tomalak: Gute Antwort! Die Aussage: "xsl: apply-templates is a loop" ist jedoch nicht korrekt. In keiner offiziellen W3C-Spezifikation gibt es Hinweise <xsl:apply-templates>, die als Schleife implementiert werden müssen - im Gegenteil, sie kann parallel implementiert werden, da die verschiedenen Anwendungen auf den verschiedenen Knoten der Knotenliste absolut unabhängig voneinander sind.
Dimitre Novatchev
8
@ Dimitre: Was ich sagen wollte: Verhält sich aus Sicht des Endbenutzers <xsl:apply-templates>wie eine Schleife. Implementierungsunterschiede auf der Seite des XSLT-Prozessors wirken sich nicht auf mich als XSLT-Programmierer aus. Das Ergebnis ist für parallelisierte und iterative Implementierungen absolut gleich. Aber für einen XSLT-Neuling mit einem zwingenden Hintergrund ist es hilfreich, sich <xsl:apply-templates>eine Art für jede Schleife vorzustellen , auch wenn dies technisch nicht der Fall ist.
Tomalak
@Tomalak: Während dies für unerfahrene XSLT-Programmierer nützlich sein kann, denke ich, dass es für sie oft irreführend ist, wenn sie denken, dass sie Statusinformationen, die in der "Ausführung der Schleife" gesammelt wurden, wiederverwenden können.
Dimitre Novatchev
@Tomalak: Aufgrund dieser Tatsachen denke ich, dass es angebracht wäre, "xsl: apply-templates is a loop" mit etwas wie "xsl: apply-templates is like a loop" zu
ändern
@Tomalak: Schleife ist Iteration, etwas apply-templatesund call-templateAnweisungen sind nicht für. Sie sind der Rekursionsmechanismus in XSLT. Und wie Dimitre geantwortet hat, sind Apply-Templates der Polymorphismus oder der datengesteuerte Mechanismus.
15

Um die gute Antwort von @Tomalak zu ergänzen:

Hier sind einige nicht erwähnte und wichtige Unterschiede :

  1. xsl:apply-templatesist viel reicher und tiefer als xsl:call-templatesund sogar von xsl:for-each, einfach weil wir nicht wissen, welcher Code auf die Knoten der Auswahl angewendet wird - im allgemeinen Fall ist dieser Code für verschiedene Knoten der Knotenliste unterschiedlich.

  2. Der Code, der angewendet wird, kann weit nach dem Schreiben des xsl:apply templates und von Personen geschrieben werden, die den ursprünglichen Autor nicht kennen.

Die Implementierung von Funktionen höherer Ordnung (HOF) durch die FXSL-Bibliothek in XSLT wäre nicht möglich, wenn XSLT die <xsl:apply-templates>Anweisung nicht hätte .

Zusammenfassung : Vorlagen und die <xsl:apply-templates>Anleitung zeigen, wie XSLT Polymorphismus implementiert und damit umgeht.

Referenz : Siehe den gesamten Thread: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html

Dimitre Novatchev
quelle
8

xsl:apply-templateswird normalerweise (aber nicht unbedingt) verwendet, um alle oder eine Teilmenge von untergeordneten Elementen des aktuellen Knotens mit allen anwendbaren Vorlagen zu verarbeiten. Dies unterstützt die Rekursivität der XSLT-Anwendung, die der (möglichen) Rekursivität des verarbeiteten XML entspricht.

xsl:call-templateAuf der anderen Seite ähnelt es viel mehr einem normalen Funktionsaufruf. Sie führen genau eine (benannte) Vorlage aus, normalerweise mit einem oder mehreren Parametern.

Also benutze ich, xsl:apply-templateswenn ich die Verarbeitung eines interessanten Knotens abfangen und (normalerweise) etwas in den Ausgabestream einfügen möchte. Ein typisches (vereinfachtes) Beispiel wäre

<xsl:template match="foo">
  <bar>
    <xsl:apply-templates/>
  </bar>
</xsl:template>

Während xsl:call-templateich normalerweise Probleme wie das Hinzufügen des Textes einiger Unterknoten, das Umwandeln ausgewählter Knotensätze in Text oder andere Knotensätze und dergleichen löse, löse ich alles, wofür Sie eine spezielle, wiederverwendbare Funktion schreiben würden.

Bearbeiten:

Als zusätzliche Bemerkung zu Ihrem spezifischen Fragetext:

<xsl:call-template name="nodes"/> 

Dies ruft eine Vorlage mit dem Namen "Knoten" auf:

    <xsl:template name="nodes">...</xsl:template>

Dies ist eine andere Semantik als:

<xsl:apply-templates select="nodes"/>

... wendet alle Vorlagen auf alle untergeordneten Elemente Ihres aktuellen XML-Knotens an, dessen Name "Knoten" lautet.

TToni
quelle
2

Die Funktionalität ist in der Tat ähnlich (abgesehen von der aufrufenden Semantik, für call-templatedie ein nameAttribut und eine entsprechende Namensvorlage erforderlich sind ).

Der Parser wird jedoch nicht auf die gleiche Weise ausgeführt.

Von MSDN :

Im Gegensatz zu <xsl:apply-templates>, <xsl:call-template>ändert nicht die aktuellen Knoten oder die aktuelle Knoten-Liste.

Oded
quelle