2009-12-29 19 views
21

Sono confuso sull'istruzione XSLT apply-template. Ad esempio, qui in w3school.Domanda modello XSLT domanda

http://www.w3schools.com/xsl/xsl_apply_templates.asp

Per le dichiarazioni,

<xsl:template match="/"> 
    <html> 
    <body> 
    <h2>My CD Collection</h2> 
    <xsl:apply-templates/> 
    </body> 
    </html> 
</xsl:template> 

mie confusioni sono,

(1) qual è la funzione di <xsl:apply-templates/>? Non contiene alcun modello specifico da chiamare. Penso che corrisponderà (restituirà) tutto direttamente figlio dell'elemento corrente (figlio non diretto del nodo corrente non verrà restituito, nodo corrente è nodo radice), non sono sicuro che io sia corretto?

(2) dopo che tutti i nodi corrispondenti sono stati restituiti in (1), quale sarà il prossimo passo che farà il processore XSLT?

(3) in questo esempio specifico, il nodo radice è catalogo o un altro livello superiore di root? e perché?

grazie in anticipo, George

risposta

47

Alcune cose che renderanno la comprensione delle risposte che diventa più facile:

In primo luogo, nodi e gli elementi non sono la stessa cosa. Gli elementi sono nodi, ma i nodi non sono necessariamente elementi. Spesso si trovano persone che usano i termini in modo intercambiabile. Esistono in realtà quattro tipi di nodi in XML: elementi, nodi di testo, istruzioni di elaborazione e commenti. (Gli attributi non sono in realtà nodi, che verranno visualizzati in un secondo.)

In XSLT, la radice di un documento XML non è il suo elemento di livello superiore; la radice è un'astrazione che in realtà non esiste. L'elemento di livello superiore è figlio della radice.Per esempio, ecco un documento XML ben formato la cui radice ha cinque nodi secondari, tra cui l'elemento di livello superiore:

<?xml-stylesheet href="mystyle.css" type="text/css"?> 
<!-- this is a perfectly legitimate XML document --> 
<top_level_element/> 

Five? Sembra che ce ne siano solo tre. Penso che ti permetterò di capire cosa sono gli altri due. Suggerimento: in questo esempio potrebbero esserci in realtà sette nodi.

L'espressione XPath / trova la radice del documento, non l'elemento di livello superiore. Nel caso precedente, per trovare l'elemento di livello superiore, devi utilizzare /top_level_element o /*. (E 'sempre sicuro da usare /* di trovare l'elemento di livello superiore, dal momento che la radice del documento deve avere un unico elemento figlio.)

Quindi armati di questa conoscenza, diamo un'occhiata a ciò che apply-templates fa. Fondamentalmente esegue un processo in due fasi: in primo luogo, costruisce un insieme di nodi. Quindi, e per ognuno, trova un modello corrispondente (tra i modelli nel file XSLT) e applica il modello ad esso. Come hai osservato in uno dei tuoi commenti, è concettualmente molto simile a un ciclo.

L'attributo select viene utilizzato nel primo passaggio. Fornisce un'espressione XPath che viene utilizzata per creare il set di nodi a cui applicherà i modelli. Se non viene fornito alcun attributo select, l'elenco che crea è tutto figlio del nodo contesto. (Il "nodo contesto" è il nodo a cui viene applicato il modello corrente.)

L'attributo match sugli elementi template viene utilizzato nel secondo passaggio. Il processore del foglio di stile trova tutti i modelli il cui attributo match corrisponde al nodo al quale sta tentando di applicare i modelli. Se ne trova più di uno, seleziona il più specifico possibile, ad es. dato questi modelli:

<xsl:template match="*"/> 
<xsl:template match="foo"/> 
<xsl:template match="foo[bar]"/> 

un elemento foo con un elemento bar bambino sarà compensato dal terzo, un elemento foo senza bar sarà compensato dal secondo, e un elemento di baz sarà accompagnata da prima. (Il metodo effettivo che utilizza XSLT è definito here, in pratica, ho usato XSLT per quasi un decennio e non ho mai una volta bisogno di sapere precisamente come funziona, anche se è interessante.)

Se non trovare una corrispondenza, verrà utilizzato il modello predefinito built-in per il tipo di nodo - in fondo, si può presumere che qualsiasi trasformazione XSLT implicitamente contiene questi modelli:

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

<xsl:template match="text()"> 
    <xsl:copy/> 
</xsl:template> 

<xsl:template match="processing-instruction() | comment() | @*"/> 

armati di tutte queste conoscenze, ora puoi capire la trasformazione dell'identità:

<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node() | @*"/> 
    </xsl:copy> 
</xsl:template> 

Corrisponde a qualsiasi nodo o attributo (si noti che gli attributi non sono nodi, motivo per cui è necessario @*), lo copia e quindi applica i modelli a tutti i relativi nodi figlio e attributi. (Solo la radice e gli elementi del documento avranno nodi figli, e solo gli elementi avranno attributi.) Poiché è l'unico modello nella trasformazione e soddisfa tutti i nodi e gli attributi, si applica a tutti i nodi e gli attributi figlio. Pertanto, copia tutto nell'albero dei sorgenti nell'albero di output.

Se si aggiunge questo modello per l'identificazione di trasformare:

<xsl:template match="foo"/> 

ora avete una trasformazione che le copie ogni nodo nell'albero dei sorgenti trannefoo elementi - che secondo modello corrisponde foo elementi (il primo fa anche questo, ma poiché l'attributo match del secondo è più specifico, è quello che XSLT sceglie) e non fa nulla con loro.

Considerato tutto questo, le risposte alle tue domande specifiche:

  1. <xsl:apply-templates> applica i modelli per i figli del nodo di contesto.

  2. I nodi corrispondenti non vengono "restituiti" nel passaggio 1; il processore XSLT trova un modello per ciascuno e lo applica.

  3. In questo esempio, il nodo di contesto è la radice del documento, un nodo astratto di cui sono figli l'elemento di livello superiore e eventuali commenti o istruzioni di elaborazione al di fuori di esso.

+0

L'istruzione "Gli attributi non sono realmente nodi" non è corretta. Gli attributi sono nodi, ma gli attributi non sono figli dell'elemento. Per maggiori dettagli, vedi la mia risposta qui sotto. esegue solo modelli per i bambini (asse child: :) ma non per attributi (attributo asse: :) –

1

xsl: apply-templates dirige il motore XSLT per abbinare i sottonodi documento di origine in corso contro i modelli di fogli di stile per ulteriori elaborazioni.

+0

"corrisponde ai sottonodi del documento sorgente corrente" - nell'esempio w3school, quali sono i "sottonodi del documento sorgente corrente"? E quali modelli definiti nel file xslt verranno cercati per trovare la corrispondenza per "sottonodi del documento sorgente corrente"? – George2

+1

Poiché solo la radice è stata abbinata finora, sarebbero tutti i nodi cd. E tutti i modelli nell'esempio sarebbero candidati per la corrispondenza. –

1

1) <xsl:apply-templates/> chiama gli attraversamenti attraverso tutti i sottonodi (figli) e chiama il modello corrispondente se presente.

2) Dopo che tutti i nodi sono abbinate le linee seguenti sono uscita che in questo caso sono

</body> 
</html> 

3) Nel catalogo esempio è il nodo radice.

+0

1.Per 1, posso capire che è implementato in un ciclo a due strati (anello esterno + anello interno)? Il ciclo esterno è foreach sottonodi, e il ciclo interno è per ogni modello definito nel file xslt corrente (vale a dire per ogni sottonodi, motore di elaborazione cercherà di trovare il modello corrispondente definito nel file xslt corrente)? 2. Se viene trovato più di un modello, cosa succederà? – George2

+1

Puoi dare un esempio in cui più di un modello può corrispondere a un nodo? Per quanto ne so, sarebbe un errore xslt e il tuo xslt non verrà compilato in quel caso. –

3
  1. <xsl:apply-templates /> proverà a trovare un modello che corrisponde al nodo corrente e ai suoi figli.
  2. Dopo che tutti i nodi corrispondenti vengono restituiti, processore XSL mandano in uscita tali tag di chiusura (cioè </body> e </html>)
  3. C'è un nodo radice, poco prima catalogo, accompagnata da "/"

EDIT: An esempio per chiarire 1.; considerano your provided sample:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/"> 
     Here we're at "root" node, just before "catalog" element.<br /> 
     Let's enumerate this child nodes: 
     <ul> 
     <xsl:for-each select="*"> 
      <li><xsl:value-of select="name()" /></li> 
     </xsl:for-each> 
     </ul> 
     <!-- Now, process "catalog" and ALL his child nodes --> 
     <xsl:apply-templates/> 
    </xsl:template> 

    <xsl:template match="cd"> 
     <p> 
     <!-- Find a template ONLY for title element --> 
     <xsl:apply-templates select="title"/> 
     <xsl:apply-templates select="artist"/> 
     </p> 
    </xsl:template> 
</xsl:stylesheet> 
+0

"cercherà di trovare un modello che corrisponda ai nodi correnti" - nodo corrente o nodi correnti? E quali modelli verranno cercati per la corrispondenza? Tutto nel file xslt o? – George2

+0

"tag di chiusura" - cos'è il tag di chiusura? Potresti descrivere in altre parole per favore? – George2

0
  • elemento XML ha bambini o attributi. Per l'XML in basso, elemento libro ha bambino :: autore (poco autore) e l'attributo :: primo (poco @first)

    <?xml version="1.0" encoding="UTF-8"?> <book> <author first="tom">Smith</author> </book>

  • xsl: applicare -templates significa eseguire modelli per tutti i figli del nodo corrispondente, quindi per il modello sottostante, eseguire il modello per autore, ma non per @firs t.

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

  • testo() nodo Smith è un figlio di elemento autore, così xsl: apply-templates chiamerà modello per il testo () node:

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