Quali sono le differenze tra "modello di chiamata" e "modelli di applicazione" in XSL?


119

Sono nuovo in XSLT, quindi sono un po 'confuso sui due tag,

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

e

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

Quindi puoi elencare la differenza tra loro?

Risposte:


167

<xsl:call-template> è un equivalente vicino alla chiamata di una funzione in un linguaggio di programmazione tradizionale.

Puoi definire funzioni in XSLT, come questa semplice che restituisce una stringa.

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

Questa funzione può essere chiamata tramite <xsl:call-template name="dosomething"> .

<xsl:apply-templates>è un po 'diverso e in esso è il vero potere di XSLT: prende un numero qualsiasi di nodi XML (qualunque cosa tu definisca selectnell'attributo), li itera ( questo è importante: apply-templates funziona come un ciclo! ) e trova i modelli corrispondenti per loro:

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

In questo modo si rinuncia a un piccolo controllo al processore XSLT - non si decide dove va il flusso del programma, ma il processore lo fa trovando la corrispondenza più appropriata per il nodo che sta attualmente elaborando.

Se più modelli possono abbinare un nodo, vince quello con l'espressione di corrispondenza più specifica. Se esistono più modelli di corrispondenza con la stessa specificità, vince quello dichiarato per ultimo.

Puoi concentrarti di più sullo sviluppo di modelli e impiegare meno tempo per eseguire gli "impianti idraulici". I tuoi programmi diventeranno più potenti e modularizzati, meno profondamente annidati e più veloci (poiché i processori XSLT sono ottimizzati per la corrispondenza dei modelli).

Un concetto da comprendere con XSLT è quello del "nodo corrente". Con <xsl:apply-templates>il nodo corrente avanza ad ogni iterazione, mentre <xsl:call-template>non cambia il nodo corrente. Ad esempio, .all'interno di un modello chiamato si riferisce allo stesso nodo .del modello chiamante. Questo non è il caso dei modelli di applicazione.

Questa è la differenza fondamentale. Ci sono altri aspetti dei modelli che influenzano il loro comportamento: il loro modee priority, il fatto che i modelli possono avere sia a nameche a match. Ha anche un impatto se il modello è stato importato ( <xsl:import>) o meno. Questi sono usi avanzati e puoi affrontarli quando arrivi.


5
@Tomalak: buona risposta! Tuttavia, l'affermazione: "xsl: apply-templates is a loop" non è corretta. Non vi è alcuna indicazione in nessuna specifica W3C ufficiale che <xsl:apply-templates>debba essere implementata come un loop - al contrario, può essere implementata in parallelo, perché le diverse applicazioni sui diversi nodi della lista dei nodi sono assolutamente indipendenti l'una dall'altra.
Dimitre Novatchev

8
@ Dimitre: Cosa intendevo dire: dal punto di vista dell'utente finale, <xsl:apply-templates>si comporta come un loop. Le differenze di implementazione sull'estremità del processore XSLT non mi influenzeranno come programmatore XSLT, il risultato è assolutamente lo stesso per le implementazioni parallelizzate e iterative allo stesso modo. Ma per un principiante XSLT con uno sfondo imperativo, aiuta a immaginare <xsl:apply-templates>come una sorta di ciclo for-each, anche se - tecnicamente - non lo è.
Tomalak

@Tomalak: Anche se questo può essere utile per i programmatori XSLT alle prime armi, penso che sia spesso fuorviante per loro poiché pensano di poter riutilizzare le informazioni di stato accumulate nell '"esecuzione del ciclo".
Dimitre Novatchev

@Tomalak: A causa di questi fatti, penso che sarebbe opportuno modificare "xsl: apply-templates is a loop" con qualcosa del tipo: "xsl: apply-templates is like a loop"
Dimitre Novatchev

@Tomalak: Loop è l'iterazione, qualcosa apply-templatese le call-templateistruzioni non servono. Sono il meccanismo di ricorsione in XSLT. E come ha risposto Dimitre, apply-templates è il polimorfismo o meccanismo basato sui dati.

15

Da aggiungere alla buona risposta di @Tomalak:

Ecco alcune differenze non menzionate e importanti :

  1. xsl:apply-templatesè molto più ricco e profondo di xsl:call-templatese persino da xsl:for-each, semplicemente perché non sappiamo quale codice verrà applicato ai nodi della selezione - nel caso generale questo codice sarà diverso per i diversi nodi della lista dei nodi.

  2. Il codice che verrà applicato può essere scritto molto dopo che la xsl:apply templates è stata scritta e da persone che non conoscono l'autore originale.

L' implementazione delle funzioni di ordine superiore (HOF) della libreria FXSL in XSLT non sarebbe possibile se XSLT non avesse l' <xsl:apply-templates>istruzione.

Riepilogo : i modelli e le <xsl:apply-templates>istruzioni sono il modo in cui XSLT implementa e gestisce il polimorfismo.

Riferimento : vedi l'intero thread: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html


8

xsl:apply-templatesdi solito (ma non necessariamente) viene utilizzato per elaborare tutti o un sottoinsieme di elementi figlio del nodo corrente con tutti i modelli applicabili. Questo supporta la ricorsività dell'applicazione XSLT che corrisponde alla (possibile) ricorsività dell'XML elaborato.

xsl:call-templated'altra parte è molto più simile a una normale chiamata di funzione. Esegui esattamente un modello (denominato), solitamente con uno o più parametri.

Quindi uso xsl:apply-templatesse voglio intercettare l'elaborazione di un nodo interessante e (di solito) iniettare qualcosa nel flusso di output. Un tipico esempio (semplificato) sarebbe

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

mentre xsl:call-templateio in genere risolvo problemi come l'aggiunta del testo di alcuni sottonodi insieme, la trasformazione di gruppi di nodi selezionati in testo o altri insiemi di nodi e simili, qualsiasi cosa per cui scriverebbe una funzione specializzata e riutilizzabile.

Modificare:

Come ulteriore osservazione al testo della tua domanda specifica:

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

Questo chiama un modello che si chiama 'nodi':

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

Questa è una semantica diversa da:

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

... che applica tutti i modelli a tutti i figli del tuo nodo XML corrente il cui nome è 'nodi'.


2

La funzionalità è davvero simile (a parte la semantica chiamante, dove call-templaterichiede un nameattributo e un modello di nomi corrispondente).

Tuttavia, il parser non verrà eseguito allo stesso modo.

Da MSDN :

Diversamente <xsl:apply-templates>, <xsl:call-template>non cambia il nodo corrente o l'attuale elenco dei nodi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.