Jakie są różnice między „szablonami połączeń” i „szablonami stosowania” w XSL?

119

Jestem nowy w XSLT, więc jestem trochę zdezorientowany co do dwóch tagów,

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

i

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

Czy możesz więc wymienić różnice między nimi?

Venkat
źródło

Odpowiedzi:

167

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

Tomalak
źródło
5
@Tomalak: Dobra odpowiedź! Jednak stwierdzenie: „xsl: Apply-templates to pętla” nie jest poprawne. W żadnej oficjalnej specyfikacji W3C nie ma żadnej wskazówki, która <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.
Dimitre Novatchev
8
@Dimitre: Co chciałem powiedzieć: z perspektywy użytkownika końcowego <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.
Tomalak
@Tomalak: Chociaż może to być przydatne dla początkujących programistów XSLT, myślę, że często wprowadza ich w błąd, ponieważ myślą, że mogą ponownie wykorzystać informacje o stanie zgromadzone podczas „wykonywania pętli”.
Dimitre Novatchev
@Tomalak: Ze względu na te fakty myślę, że należałoby zmodyfikować „xsl: apply-templates to pętla” z czymś w rodzaju: „xsl: apply-templates jest jak pętla”
Dimitre Novatchev
@Tomalak: Pętla to iteracja, coś apply-templatesi call-templateinstrukcje nie są potrzebne. Są mechanizmem rekursji w XSLT. Jak odpowiedział Dimitre, szablony aplikacji to mechanizm polimorfizmu lub oparty na danych.
15

Aby dodać do dobrej odpowiedzi @Tomalak:

Oto kilka niewymienionych i ważnych różnic :

  1. 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.

  2. 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

Dimitre Novatchev
źródło
8

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.

Edytować:

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”.

TToni
źródło
2

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.

Oded
źródło