Elaborazione condizionale con più opzioni
Pensiamo per un attimo a cosa accadrebbe se avessimo un documento XML con molti blocchi di codice e solo uno di essi deve essere eseguito, in base ad una certa condizione. Si dovrebbe creare una serie di xsl:if, ognuno dei quali verifica, appunto, una determinata condizione. Se più di un elemento ha una espressione il cui test è positivo, verrebbe eseguito il codice all'interno di ogni elemento. Se abbiamo deciso di eseguirlo tutto allora va bene ma, se per caso, volessimo eseguire solo unoi dei blocchi... ci troveremmo dinanzi un bel problema.
Per fortuna XSLT ci viene in aiuto anche per questa cosa; possiamo utilizzare una struttura di elementi per ovviare a quanto abbiamo appena letto. L'elemento principale è xsl:choose il quale ha due possibili elementi figli: xsl:when e xsl:otherwise.
Il primo elemento (xsl:when) e simile all'elemento xsl:if in quanto contiene codice da eseguire se l'espressione nell'attributo test dà true.
xsl:when può presentarsi più di una volta all'interno di xsl:choose, ma è eseguito una volta sola. Non appena un elemento restituisce true, viene eseguito. Tutti gli altri presenti, invece, verranno ignorati. Se nessun elemento xsl:when viene eseguito, entra in azione l'elemento xsl:otherwise. Qualsiasi codice in esso presente viene mostrato in output se qualcuno di quelli precedenti verrà eseguito.
Dopo questa corposa introduzione per questi nuovi elementi, vediamo l'applicazione di un foglio di stile ad un documento XML. Come spiegato in precedenza, il sorgente è quello che già conosciamo.
<xsl:for-each select="persone/persona">
<h2><xsl:value-of select="@nome" /></h2>
<xsl:for-each select="telefono">
<xsl:choose>
<xsl:when test="@tipo='casa'">
<p>Telefono casa: <xsl:value-of select="." /></p>
</xsl:when>
<xsl:when test="@tipo='fax'">
<p>Fax: <xsl:value-of select="." /></p>
</xsl:when>
<xsl:when test="@tipo='cellulare'">
<p>Cellulare: <xsl:value-of select="." /></p>
</xsl:when>
<xsl:otherwise>
Telefono: <xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
In tutto questo codice appena scritto, quello che è più importante vedere è l'elemento xsl:choose aon all'interno elementi figlio xsl:when ed un elemento xsl:otherwise. Gli elementi xsl:when controllano se l'attributo tipo ha un certo valore. In caso positivo, il codice al suo interno viene elaborato. Se gli elementi xsl:when non soddisfano la condizione dell'attributo test, entra in azione xsl:otherwise.
Da notare, in questo esempio, che xsl:choose è figlio e figlio dell'elemento xsl:for-each. Non è obbligatorio utilizzarlo in questo modo. Può benissimo essere elemento figlio di un modello. Tra tutti gli elementi che abbiamo visto fin qui, solo xsl:stylesheet e xsl:template hanno delle regole molto rigide. Gli altri elementi possono trovarsi all'interno di un altro elemento. Possiamo affermare, dunque, che un elemento xsl:choose può trovarsi all'interno di xsl:for-each il quale, a sua volta, è figlio di un elemento xsl:if.
Il risultato di questa elaborazione condizionale più complessa mostra quanto abbiamo ottenuto con il sorgente XML.
Da quanto possiamo vedere, vengono mandati in output tutti i nodi telefono, e relativi tipi. Siccome avevamo nel sorgente XML 3 tipi di telefono per il primo nodo persona e 2 tipi di telefono per il secondo nodo, la trasformazione ci ha dato effettivamente quello che ci si aspettava. In questo esempio l'elemento xsl:otherwise non è stato chiamato in causa in quanto avevamo una corrisposndenza sul tipo dei telefoni, comune ai due nodi persona.
Poniamo il caso, adesso, che nel foglio di trasformazione venga omesso un tipo di telefono, per far entrare in gioco l'elemento xsl:otherwise. Il nuovo codice XSLT è il seguente:
<xsl:for-each select="persone/persona">
<h2><xsl:value-of select="@nome" /></h2>
<xsl:for-each select="telefono">
<xsl:choose>
<xsl:when test="@tipo='casa'">
<p>Telefono casa: <xsl:value-of select="." /></p>
</xsl:when>
<xsl:when test="@tipo='fax'">
<p>Fax: <xsl:value-of select="." /></p>
</xsl:when>
<xsl:otherwise>
Telefono: <xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
Quello che è stato eliminato, rispetto al primo blocco di codice, è:
<p>Cellulare: <xsl:value-of select="." /></p>
</xsl:when>
Cosa dovrebbe succedere? Quando un valore dell'attributo tipo non è stato inserito, noi abbiamo volutamente omesso "@tipo='cellulare'", viene chiamato l'elemento xsl:otherwise. Tale elemento manda in output il testo Telefono: ed il suo numero. Rivedendo un attimo il sorgente XML, accanto al testo "Telefono:", quale valore ci sarà? Se si è pensato al valore dell'attributo "@tipo='cellulare'", allora abbiamo fatto centro, in quanto viene scritto come se fosse un normale numero di telefono.
Vediamo il risultato di questa trasformazione.
Il testo in grassetto l'ho scritto per far vedere che il valore associato è quello appartenente al nodo telefono, con tipo = cellulare. Ci si potrebbe chiedere, allora, come mai è stato inserito nel primo esempio l'elemento xsl:otherwise se non è stato innescato. Effettivamente lo si può anche tralasciare se siamo sicuri che in output riceveremo i nodi presenti nell'albero sorgente. In altri termini xsl:otherwise è utile per trattare i casi che non sono gestiti da nessun elemento xsl:when.
| < Prec. | Succ. > |
|---|

