Odpowiedzi:
<xsl:call-template> jest bliskim odpowiednikiem wywołania funkcji w tradycyjnym języku programowania.
Możesz definiować funkcje w XSLT, takie jak ta prosta, która generuje ciąg.
<xsl:template name="dosomething">
<xsl:text>A function that does something</xsl:text>
</xsl:template>
Tę funkcję można wywołać za pomocą <xsl:call-template name="dosomething">.
<xsl:apply-templates>jest trochę inny iw tym tkwi prawdziwa moc XSLT: Pobiera dowolną liczbę węzłów XML (cokolwiek zdefiniujesz w selectatrybucie), iteruje je ( jest to ważne: szablony stosowania działają jak pętla! ) i znajduje pasujące szablony dla nich:
<!-- 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>
W ten sposób oddajesz trochę kontroli procesorowi XSLT - nie decydujesz, dokąd idzie przepływ programu, ale procesor robi to, znajdując najbardziej odpowiednie dopasowanie do węzła, który aktualnie przetwarza.
Jeśli do węzła można dopasować wiele szablonów, wygrywa ten z bardziej szczegółowym wyrażeniem dopasowania. Jeśli istnieje więcej niż jeden pasujący szablon o tej samej specyficzności, wygrywa ten zadeklarowany jako ostatni.
Możesz bardziej skoncentrować się na opracowywaniu szablonów i potrzebować mniej czasu na „hydraulikę”. Twoje programy staną się bardziej wydajne i zmodularyzowane, mniej zagnieżdżone i szybsze (ponieważ procesory XSLT są zoptymalizowane pod kątem dopasowywania szablonów).
Pojęciem, które należy zrozumieć w przypadku XSLT, jest „bieżący węzeł”. Z <xsl:apply-templates>bieżącym węzłem przesuwa się z każdą iteracją, natomiast <xsl:call-template>nie zmienia bieżącego węzła. To znaczy .wewnątrz wywoływanego szablonu odnosi się do tego samego węzła, co .w szablonie wywołującym. Nie dotyczy to szablonów aplikacji.
To podstawowa różnica. Istnieje kilka innych aspektów szablonów, które wpływają na ich zachowanie: swoje modei priorityfakt, że szablony mogą mieć zarówno namea match. Ma również wpływ na to, czy szablon został zaimportowany ( <xsl:import>), czy nie. Są to zaawansowane zastosowania i możesz sobie z nimi poradzić, gdy tam dotrzesz.
<xsl:apply-templates>zachowuje się jak pętla. Różnice implementacyjne po stronie procesora XSLT nie wpłyną na mnie jako programistę XSLT, wynik jest absolutnie taki sam dla implementacji równoległych i iteracyjnych. Ale nowicjuszowi XSLT z imperatywnym doświadczeniem pomaga wyobrazić sobie <xsl:apply-templates>rodzaj pętli for-each, nawet jeśli - technicznie - tak nie jest.
Aby dodać do dobrej odpowiedzi @Tomalak:
Oto kilka niewymienionych i ważnych różnic :
xsl:apply-templatesjest znacznie bogatszy i głębszy niż, xsl:call-templatesa nawet z xsl:for-each, po prostu dlatego, że nie wiemy, jaki kod zostanie zastosowany na węzłach selekcji - w ogólnym przypadku ten kod będzie inny dla różnych węzłów listy węzłów.
Kod, który zostanie zastosowany, może zostać napisany po napisaniu xsl:apply templates i przez osoby, które nie znają oryginalnego autora.
Biblioteka FXSL „s implementacja funkcji wyższego rzędu (Hof) w XSLT nie byłoby możliwe, gdyby XSLT nie ma <xsl:apply-templates>instrukcji.
Podsumowanie : Szablony i <xsl:apply-templates>instrukcja pokazują, jak XSLT implementuje polimorfizm i radzi sobie z nim.
Źródła : Zobacz cały wątek: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html
xsl:apply-templatesjest zwykle (ale niekoniecznie) używany do przetwarzania wszystkich lub podzbioru elementów podrzędnych bieżącego węzła ze wszystkimi odpowiednimi szablonami. Obsługuje to rekurencyjność aplikacji XSLT, która jest zgodna z (możliwą) rekurencyjnością przetworzonego XML.
xsl:call-templatez drugiej strony bardziej przypomina normalne wywołanie funkcji. Wykonujesz dokładnie jeden (nazwany) szablon, zwykle z co najmniej jednym parametrem.
Więc używam, xsl:apply-templatesjeśli chcę przechwycić przetwarzanie interesującego węzła i (zwykle) wstrzyknąć coś do strumienia wyjściowego. Typowy (uproszczony) przykład to
<xsl:template match="foo">
<bar>
<xsl:apply-templates/>
</bar>
</xsl:template>
podczas gdy xsl:call-templateja zazwyczaj rozwiązuję problemy, takie jak dodawanie tekstu niektórych podwęzłów do siebie, przekształcanie wybranych zestawów węzłów w tekst lub inne zestawy węzłów i tym podobne - wszystko, dla czego napisałbyś wyspecjalizowaną funkcję wielokrotnego użytku.
Jako dodatkowa uwaga do konkretnego tekstu pytania:
<xsl:call-template name="nodes"/>
Wywołuje to szablon o nazwie „węzły”:
<xsl:template name="nodes">...</xsl:template>
To jest inna semantyczna niż:
<xsl:apply-templates select="nodes"/>
... który stosuje wszystkie szablony do wszystkich elementów podrzędnych twojego obecnego węzła XML, którego nazwa to „węzły”.
Funkcjonalność jest rzeczywiście podobna (poza semantyką wywoływania, gdzie call-templatewymaga nameatrybutu i odpowiedniego szablonu nazw).
Jednak parser nie wykona tego samego sposobu.
Z MSDN :
W przeciwieństwie do
<xsl:apply-templates>,<xsl:call-template>nie zmienia bieżącego węzła ani bieżącej listy węzłów.
<xsl:apply-templates>musi być implementowana jako pętla - wręcz przeciwnie, może być implementowana równolegle, ponieważ różne aplikacje na różnych węzłach listy węzłów są od siebie całkowicie niezależne.