- Template XSLT per cicli e come
funzioni ricorsive -
|
|||
COSA SERVE PER QUESTO TUTORIAL | |||
Download | Chiedi sul FORUM | Glossario | Un qualunque editor testuale e Internet Explorer, Opera o Firefox oppure un server che supporti ASP .Net o PHP | ||
Uso avanzato dei template XSLT | |||
USARE I TEMPLATE COME FOSSERO FUNZIONI Gli elementi xsl:call-template, xsl:param e xsl-with-param
Nel precedente articolo su XSLT abbiamo introdotto il concetto di
template, ora ci proponiamo di approfondirlo e di evidenziare
la sua utilità in analogia con quella che in un normale linguaggio di
programmazione sarebbe una funzione. Lavorando in XSLT infatti capiterà
di frequente di avere necessità di utilizzare funzioni non disponibili
in XPath, in quanto fornisce solo alcune basiche funzioni di conversione, di
logica booleana, di elaborazione di numeri e stringhe e altre specifiche
per muoversi nel documento XML di origine. <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:call-template name="scriviCiao" /> <xsl:call-template name="scriviCiao" /> <xsl:call-template name="scriviCiao" /> </xsl:template> <xsl:template name="scriviCiao"> <div>Ciao!</div> </xsl:template> </xsl:stylesheet> In questo codice abbiamo due template, uno principale associato al nodo radice (dal quale dunque inizierà l'elaborazione) e un altro chiamato scriviCiao. Come si può vedere il primo template attraverso l'elemento xsl:call-template richiama l'elaborazione del secondo template (specificandone il nome). In questo semplice esempio dunque l'output sarà come segue: <div>Ciao!</div> <div>Ciao!</div> <div>Ciao!</div> Un template utilizzato in questa maniera, proprio come una funzione di qualsiasi linguaggio di programmazione ordinario, può ricevere anche dei parametri che vanno dichiarati tramite xsl:param all'inizio del template (opzionalmente con valori di default) e passati durante una chiamata tramite elementi xsl:with-param all'interno di xsl:call-template. Ecco un esempio per comprendere meglio: <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:call-template name="saluta"> <xsl:with-param name="soggetto" select="'Carlo'" /> <xsl:with-param name="oggetto">Paolo</xsl:with-param> </xsl:call-template> </xsl:template> <xsl:template name="saluta"> <xsl:param name="soggetto" select="'nessuno'" /> <xsl:param name="oggetto">nessuno</xsl:param> <div><xsl:value-of select="$soggetto" /> saluta <xsl:value-of select="$oggetto" />!</div> </xsl:template> </xsl:stylesheet> Come si può vedere all'inizio del template saluta vi sono due
elementi xsl:param con un attributo name che identifica il nome del
parametro; il primo dei due è dotato anche di un attributo select che
contiene un'espressione XPath , mentre il secondo contiene del testo: si
tratta di due metodi differenti per impostare il valore di default.
Inoltre il template saluta contiene due elementi xsl:value-of
che richiamano l'espressione XPath $soggetto e $oggetto. Da questo si può
intuire che per richiamare il valore di un parametro in XPath basta
utilizzare il suo nome preceduto dal segno del dollaro. Come aggirare le limitazioni di XSLT: estrazione della radice quadrata. Una delle possibilità più utili che servirsi dei template come fossero funzioni offre è effettuare chiamate ricorsive (ovvero far sì che il template richiami se stesso), tecnica che in sostanza supplisce alla mancanza di un ciclo che non sia restrittivo come xsl:for-each. Vediamo un esempio: <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:call-template name="ripeti"> <xsl:with-param name="volte">13</xsl:with-param> <xsl:with-param name="cosa">Ciao a tutti!</xsl:with-param> </xsl:call-template> </xsl:template> <xsl:template name="ripeti"> <xsl:param name="volte" /> <xsl:param name="cosa" /> <xsl:param name="contatore">1</xsl:param> <div><xsl:value-of select="$cosa" /></div> <xsl:if test="$contatore != $volte"> <xsl:call-template name="ripeti"> <xsl:with-param name="volte" select="$volte" /> <xsl:with-param name="cosa" select="$cosa" /> <xsl:with-param name="contatore" select="$contatore + 1" /> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet> Il primo template richiama ripeti (template che,
come intuibile, ripeterà uno stesso testo un dato numero di volte)
specificando come parametro volte 13 e come parametro cosa un testo di
esempio. Si noti che non viene specificato il parametro contatore,
il quale
assumerà dunque il suo valore di default, cioè 1. <!-- Tratto da un template di Nate Austin per l'estrazione della radice quadrata con il metodo di Isaac Newton --> <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:call-template name="radiceQuadrata"> <xsl:with-param name="numero">2</xsl:with-param> <xsl:with-param name="precisione">15</xsl:with-param> </xsl:call-template> </xsl:template> <xsl:template name="radiceQuadrata"> <xsl:param name="numero" /> <xsl:param name="precisione">10</xsl:param> <xsl:param name="risultato">1</xsl:param> <xsl:param name="contatore">1</xsl:param> <xsl:choose> <xsl:when test="$risultato * $risultato = $numero or $contatore > $precisione"> <xsl:value-of select="$risultato " /> </xsl:when> <xsl:otherwise> <xsl:call-template name="radiceQuadrata"> <xsl:with-param name="numero" select="$numero" /> <xsl:with-param name="risultato" select="$risultato - (($risultato * $risultato - $numero) div (2 * $risultato))" /> <xsl:with-param name="contatore" select="$contatore + 1" /> <xsl:with-param name="precisione" select="$precisione" /> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> Il template radiceQuadarta può ricevere 4 parametri di cui
però metà (risultato e contatore) sono solo ad uso
interno, infatti in xsl:call-template vengono passati solamente
il numero di cui estrarre la radice e la precisione con cui calcolarlo.
L'algoritmo in questione è stato studiato da Newton e si basa sul
continuare ad applicare una stessa formula ottenendo così un risultato
man mano sempre più preciso. Il parametro precisione indica il
numero di volte che questa formula deve essere applicata, il parametro
risultato è il numero ottenuto che diviene man mano più preciso e
alla fine stampato e il parametro contatore è quello che viene
incrementato ad ogni chiamata ricorsiva per interrompere l'esecuzione
quando si sta per eccedere la precisione desiderata. In alternativa il
template smette di richiamare se stesso se il risultato moltiplicato per
se stesso dà il numero originale, ovvero se si è giunti al risultato
esatto. Script interni e esterni, librerie dei parser e XPath 2 e XSLT 2. Certamente implementare l'algoritmo di estrazione della radice quadrata in XSLT è dispendioso in risorse (effettuare un grande numero di chiamate ricorsive non è mai una buona idea) e in tempo (dato l'obbligo di utilizzare template che si richiamano ricorsivamente ogni qualvolta è necessario un ciclo), ma d'altro lato le alternative offrono notevoli svantaggi. Alcuni parser permettono di scrivere proprie funzioni XPath sia all'interno che all'esterno del documento XSLT, spesso in JavaScript (anche se con .Net di Microsoft è possibile utilizzare qualsiasi linguaggio della piattaforma), ma in realtà gli script all'interno di XSLT non sono molto supportati, o comunque in quanto non standard sono sempre legati ad una piattaforma (il che comporta la perdita di tutti i vantaggi che offre XML e quindi XSLT). Altra soluzione è utilizzare vere e proprie estensioni per il parser, ma anche in questo si finisce per legarsi ad un solo parser. L'unica vera alternativa è rivolgersi a XPath 2 e XSLT 2.
|
|||
<< INDIETRO | by VeNoM00 |