Paolo Pialorsi

SOA, Workflow Foundation (WF), Windows Communication Foundation (WCF) e le Architetture Distribuite

novembre 2003 - Posts

Costrutti iterativi: for-each

Abbiamo visto cosa sono e come funzionano i template.
A volte però fa anche comodo poter eseguire dei cicli senza richiamare i template, anche perchè ogni volta che invochiamo un template ci tocca eseguire dei salti nella struttura gerarchica del documento XSLT.

Se vogliamo eseguire un set di operazioni prefissate su un gruppo di nodi
possiamo utilizzare l'istruzione for-each. Essa prevede un solo attributo, di
nome select, che rappresenta la regola XPath di selezione dei nodi.

All'interno del blocco for-each dovremo indicare le operazioni da svolgere,
riferendoci ai nodi da cercare con percorsi relativi al nodo di contesto.

Cosa è il "nodo di contesto"? Si tratta del nodo sul quale è posizionato il "puntatore" del processore XSLT. Nel caso di un ciclo for-each si tratterà, passo dopo passo, di ciascuno dei nodi che fanno parte del risultato della regola XPath indicata nell'attributo select.

Quindi partendo dal seguente documento:

<?xml version="1.0"?>
<products>
 <product id="P01" name="Prodotto 01" />
 <product id="P02" name="Prodotto 02" />
 <product id="P03" name="Prodotto 03" />
 <product id="P04" name="Prodotto 04" />
 <product id="P05" name="Prodotto 05" />
</products>

se scriviamo:

<xsl:for-each select="/products/product">
 <!-- qui il nodo di contesto saranno i singoli elementi product -->
</xsl:for-each>

Allora per ottenere il valore dell'attributo @id del prodotto corrente ci basterà scrivere:

<xsl:for-each select="/products/product">
 <xsl:value-of select="@id" />
</xsl:for-each>

Forse non tutti sanno che possiamo combinare diverse regole XPath nel momento in cui eseguiamo una selezione. Per esempio il documento:

<?xml version="1.0"?>
<products>
 <tangible id="T01" deliveryTime="24" name="Prodotto tangibile 01" />
 <service id="S01" name="Servizio non tangibile 01" />
 <tangible id="T02" deliveryTime="36" name="Prodotto tangibile 02" />
 <tangible id="T03" deliveryTime="48" name="Prodotto tangibile 03" />
 <tangible id="T04" deliveryTime="24" name="Prodotto tangibile 04" />
 <service id="S02" name="Servizio non tangibile 02" />
 <service id="S03" name="Servizio non tangibile 03" />
 <service id="S04" name="Servizio non tangibile 04" />
</products>

prevede sia elementi <tangible> che <service>. I prodotti tangibili avranno un tempo di consegna (in ore), mentre i servizi saranno a consegna immediata (scusate la scarsa fantasia!).
Ora, sfruttando una regola XPath composta, potremmo voler scrivere in HTML tutti i servizi e i prodotti consegnabili entro e non oltre 24h:

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

<xsl:template match="/">
<html><body>
 <ul>
 <xsl:for-each select="products/tangible[@deliveryTime &lt;= 24] | products/service">
  <li><xsl:value-of select="@id" /> - <xsl:value-of select="@name" /></li>
 </xsl:for-each>
 </ul>
</body></html>
</xsl:template>

</xsl:transform>

Per ottenere:

<html><body>
<ul>
<li>T01 - Prodotto tangibile 01</li>
<li>S01 - Servizio non tangibile 01</li>
<li>T04 - Prodotto tangibile 04</li>
<li>S02 - Servizio non tangibile 02</li>
<li>S03 - Servizio non tangibile 03</li>
<li>S04 - Servizio non tangibile 04</li>
</ul>
</body></html>

Sui prodotti tangibili è stato applicato un filtro XPath secondo la regola:

axes::nodetest[predicate]

Per ulteriori dettagli su XPath vi rimando alla documentazione di MSXML 4.0 o di .NET Framework, oppure al mio tascabile su XML (http://education.mondadori.it/Libri/SchedaLibro.asp?IdLibro=88-8331-341-0) ... che arriva Natale e ho bisogno di soldi per fare i regali :-D!

La prossima volta vedremo come ordinare i nodi e come lavorare con nodi e percorsi XPath relativi, per esempio per dividere le categorie di prodotti o per mostrare tabelle con righe alternate.

Regole XPath e namespace

Non c'entra nulla con "Un XSLT al giorno" (o almeno è troppo presto per collegare questo discorso ad XSLT) ma visto che due amici/colleghi nel giro di una settimana mi hanno rivolto la stessa domanda, provo a condividere con tutti la risposta.

Domanda: perché se ho un documento XML che ha un namespace di default, per esempio come quello seguente, devo eseguire le ricerche XPath dichiarando il namespace in modo esplicito ?

Documento:

<?xml version="1.0"?>
<documento xmlns="urn:documento">
<titolo>testo del titolo</titolo>
</documento>

Se voglio cercare /documento/titolo e provo con:

XmlDocument src = new XmlDocument();
src.Load("documento.xml");
Console.WriteLine(src.SelectSingleNode("/documento/titolo").InnerText);

ottengo:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.

Mentre se scrivo:

XmlDocument src = new XmlDocument();
src.Load(@"..\..\documento.xml");

XmlNamespaceManager nsManager = new XmlNamespaceManager(src.NameTable);
nsManager.AddNamespace("doc", "urn:documento");

Console.WriteLine(src.SelectSingleNode("/doc:documento/doc:titolo", nsManager).InnerText);

trovo il nodo e riesco a leggere il suo contenuto testuale?

La risposta è legata al fatto che il processore XPath vede dei nodi "qualificati", cioè associati ad un namespace e quindi si aspetta di ricercarli attraverso il loro namespace. Se noi indichiamo solo titolo come nome del nodo, il processore XPath cercherà tale nodo solo tra i nodi che non hanno un namespace associato, escludendo quindi dalla ricerca il nodo al quale siamo effettivamente interessati.

Ecco un esempio più completo:

http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/XPathRules.zip

Provate a leggere bene il codice e i commenti, dovrebbe essere autoesplicativo.

Posted: nov 29 2003, 03.12 by paolo
Filed under:
xsl:output

Ok oggi parliamo di tipologie di Output.

Quando scriviamo dei documenti XSLT i processori, a seconda di come configuriamo le trasformazioni, posso dare diversi output: XML, HTML, TXT.

Abbiamo un tag apposito (output) per comunicare al processore cosa vogliamo ottenere, oppure possiamo lasciare che sia lui a decidere, facendo del suo meglio.

Il comando output ha il seguente aspetto:

<xsl:output
  method="xml|html|text"
  version="1.0" <- versione dell'xml da generare
  encoding="valore" <- tipo di encoding dell'output, per es. UTF-8
  omit-xml-declaration="yes|no" <- indica se vogliamo o meno la PI di prologo
  standalone="yes|no" <- indica se il documento di output dipende da una DTD esterna o meno
  doctype-public="string" <- nome pubblico dell'eventuale DTD dell'output
  doctype-system="string" <- percorso per il download dell'eventuale DTD
  cdata-section-elements="QNames" <- nomi dei tag che conterranno delle CDATA Sections
  indent="yes|no" <- Se l'output deve essere indentato
  media-type="string" <- Indica il MIME type dell'output
  />

A livello di method le differenze sono che:
- HTML: sistema i tag e i valori degli attributi in modo che il risultato sia HTML compatibile. Per esempio <br/> diventerà <br>, <img /> diventerà <img>, <option selected="selected"> sarà convertito in <option selected> e così via.
- XML: sarà un XML well-formed, sta a noi garantire che ciò accada realmente. Se in output generiamo due tag root il processo lo farà, ma poi il nostro risultato non sarà "leggibile".
- TXT: sarà testo semplice.

Gli attributi sui quali vale la pena soffermarsi sono:

- encoding: se usate un motore MSXML e appoggiate il risultato dentro ad una variabile String perderete l'encoding scelto a questo livello e vi troverete uno Unicode (UTF-16). Se dovete rimaneggiare il risultato senza perdere l'encoding usate uno Stream e non una String.
- cdata-section-elements: serve solo se avete delle CDATA (le sezioni <![CDATA[ ... ]]> ) e contiene la lista dei tag, separati da spazio, che dovranno avere il loro contenuto racchiuso in una CDATA.
- indent: usatelo con attenzione. Spesso capita che i grafici o htmllisti ci diano dei layout splendidi, da rendere tramite XSLT. Noi mettiamo indent="yes" e tutto sballa come per incanto, in particolare se vi sono tabelle annidate con gli spazi ben misurati.

Se usiamo il comando output, esso deve comparire come child di transform, allo stesso livello di gerarchia di template, per capirci.

Possiamo averne più di uno e in tal caso il motore di parsing dovrà fare il merge dei vari output. Non dobbiamo avere però due tag output con attributi in comune perché la doppia definizione darebbe errore.

E se non indichiamo un output esplicito?

Il motore XSLT deve lavorare in questo modo: se il tag root di output è HTML (in qualsiasi combinazione di maiuscole/minuscole) allora il risultato sarà html, altrimenti sarà xml.

Se quindi abbiamo:

<?xml version="1.0"?>
<products>
 <product id="P01" name="Prodotto 01" />
 <product id="P02" name="Prodotto 02" />
 <product id="P03" name="Prodotto 03" />
 <product id="P04" name="Prodotto 04" />
 <product id="P05" name="Prodotto 05" />
</products>

e la trasformazione XSLT è:

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

<xsl:template match="/">
 <table>
  <xsl:for-each select="products/product">
   <tr>
    <td><img src="{@id}.gif" /></td>
    <td><xsl:value-of select="@name" /></td>
   </tr>
  </xsl:for-each>
 </table>
</xsl:template>

</xsl:transform>

Ecco che il risultato, visto che non apriamo il documento di output con HTML ma con TABLE, sarà XML. Il tag img sarà quindi implicitamente chiuso e avremo la PI di prologo, solo per fare qualche esempio.

Se invece avessimo scritto:

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

<xsl:template match="/">
<html>
 <body>
 <table>
  <xsl:for-each select="products/product">
   <tr>
    <td><img src="{@id}.gif" /></td>
    <td><xsl:value-of select="@name" /></td>
   </tr>
  </xsl:for-each>
 </table>
 </body>
</html>
</xsl:template>

</xsl:transform>

Il risultato sarebbe stato:

<html>
<body>
<table>
<tr>
<td><img src="P01.gif"></td>
<td>Prodotto 01</td>
</tr>
<tr>
<td><img src="P02.gif"></td>
<td>Prodotto 02</td>
</tr>
<tr>
<td><img src="P03.gif"></td>
<td>Prodotto 03</td>
</tr>
<tr>
<td><img src="P04.gif"></td>
<td>Prodotto 04</td>
</tr>
<tr>
<td><img src="P05.gif"></td>
<td>Prodotto 05</td>
</tr>
</table>
</body>
</html>

cioè HTML indentato.
Ovviamente possiamo forzare questo comportamento proprio utilizzando il comando output:

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

<xsl:output method="html" indent="no"  />

<xsl:template match="/">
 <table>
  <xsl:for-each select="products/product">
   <tr>
    <td><img src="{@id}.gif" /></td>
    <td><xsl:value-of select="@name" /></td>
   </tr>
  </xsl:for-each>
 </table>
</xsl:template>

</xsl:transform>

per ottenere:

<table><tr><td><img src="P01.gif"></td><td>Prodotto 01</td></tr><tr><td><img src="P02.gif"></td><td>Prodotto 02</td></tr><tr><td><img src="P03.gif"></td><td>Prodotto 03</td></tr><tr><td><img src="P04.gif"></td><td>Prodotto 04</td></tr><tr><td><img src="P05.gif"></td><td>Prodotto 05</td></tr></table>

Alla prossima!

Esempi:

http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/products.xml
http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/products.xslt
http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/products-html.xslt
http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/products-html-output.xslt

Posted: nov 28 2003, 01.27 by paolo
Filed under:
XSLT: ancora template

Ok, oggi pago la multa! :-)
Ieri non ho fatto in tempo a scrivere la puntata quotidiana.
Purtroppo ho trascorso la notte a preparare la contabilità per il mio commercialista. Sogno il giorno in cui basterà premere un tasto per registrare le fattura emesse/ricevute e avere il bilancio e la prima nota aggiornate in tempo reale ... !

Intanto, bando alle chiacchere, e continuiamo a parlare di XSLT.

Come abbiamo visto i processori XSLT lavorano in base a dei template.
Bene oggi cerchiamo di approfondire meglio le opzioni che un template ci mette a disposizione.

Innanzitutto occorre dire che i template possono essere invocati o dalle built-in rules, o da apply-templates generici o da apply-templates specifici che siano configurati, tramite l'attributo select, per selezionare dei nodi specifici per i quali è definita un qualche template.

Quando eseguiamo un template possiamo farlo quindi in base al fatto che corrisponde ad un nodo per il quale è stato chiamato il comando apply-templates, ma possiamo anche chiamare dei template direttamente per nome.

Possiamo infatti definire:

<xsl:template name="NomeDelMioTemplate">
 <!-- Fai qualcosa ... -->
</xsl:template>

e richiamare questo template con il comando call-template:

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

In pratica chiamiamo il template come se fosse una procedura. Potremo passargli anche dei parametri, ma ne parleremo in una delle prossime puntate.
Inoltre se utilizziamo apply-templates possiamo definire diversi template per uno stesso nodeset (condizione di selezione XPath) e far sì che a seconda dei casi venga richiamata una o l'altra delle soluzioni previste.
Il comando template infatti prevede oltre a match anche un attributo mode che ci permette di dare delle specializzazioni a template che gestiscono gli stessi nodeset. Per esempio:

<xsl:template match="ordine" mode="primo">
 <!-- Qualcosa di unico per il primo -->
</xsl:template>

<xsl:template match="ordine" mode="secondo">
 <!-- Qualcosa di diverso dal primo -->
</xsl:template>

A questo punto potremo scegliere quale dei due template debba essere invocato, a parità di nodeset come si vede, con:

<xsl:apply-templates select="//ordine" mode="primo" />

oppure:

<xsl:apply-templates select="//ordine" mode="secondo" />

Infine sempre i template hanno una priorità (attributo priority) che serve a decidere quale template applicare in caso di indecisione.
Il valore di priority varia tra -9 e +9. Priorità più alte vincono su priorità più base.

Domani ci occuperemo di tipologie di output.

Posted: nov 27 2003, 12.01 by paolo
Filed under:
Web Service asincroni con .NET: sessione multimediale

Ho preparato un: Articolo DevLeap Multimediale.

Sto facendo un po' di esperimenti! Mi dite (paolo@devleap.com) se lo guardate (basta una email con scritto ... <<l'ho visto, ma dopo 2 minuti mi sono addormentato e non ricordo più come mi chiamo!>> ... o cose simili).

Se devo fare le altre puntate e se devo alzare/abbassare la qualità del video e dell'audio o perchè no :-) dei contenuti.

Grazie.


Link: http://www.devleap.com/SchedaArticolo.aspx?IdArticolo=10580
I Template XSLT

Riprendiamo il discorso iniziato ieri per affrontare per bene la logica di funzionamento di un processore XSLT, così come è definita dalla Raccomandazione del W3C (http://www.w3.org/TR/xslt).

Quando un processore XSLT deve elaborare un documento innanzitutto ne deve eseguire il parsing dell'albero di contenuti, per permettere a noi programmatori XSLT di lavorare non con il documento testuale ma con l'albero di nodi, appunto.

Quindi inizia a scorrere il documento XSLT cercando per ciascun nodo dell'input una regola (un template) di trasformazione e se la trova la applica.

Il primo nodo da cui parte è il nodo root (<xsl:template match="/" />) per il quale viene cercato il template e, qualora esso non sia definito, ne verrà applicato uno di default (5.8 Built-in Template Rules):

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

che andrà alla ricerca di template per i nodi figli di "/" e così via.
Tutte le volte che deve applicare un template, un processore XSLT, può trovarsi nell' "imbarazzo della scelta". Per esempio di fronte ad un documento XML come il seguente:

<?xml version="1.0"?>
<album>
 <titolo>Ma cosa vuoi che sia una canzone</titolo>
 <autore>Vasco Rossi</autore>
 <canzoni>
  <canzone>
   <titolo>La nostra relazione</titolo>
  </canzone>
  <canzone>
   <titolo>...E poi mi parli di una vita insieme</titolo>
  </canzone>
  <canzone>
   <titolo>Silvia</titolo>
  </canzone>
  <!-- e tante altre ... vai Vasco! :-) -->
 </canzoni>
</album>

La trasformazione XSLT di seguito riportata come si dovrebbe comportare?

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

<xsl:template match="/">
 <html>
  <head>
   <title><xsl:value-of select="album/titolo" /></title>
  </head>
 </html>
 <body>
 </body>
</xsl:template>

<xsl:template match="titolo">
 <H1><xsl:value-of select="." /></H1>
</xsl:template>

<xsl:template match="//canzone/titolo">
 <H3><xsl:value-of select="." /></H3>
</xsl:template>

</xsl:transform>

Provate a pensarci prima di eseguirla. Potete scegliere tra:

1) Vedo una lista di H1 con dentro il titolo dell'album e delle singole canzoni
2) Vedo una pagina vuota con il titolo HTML
3) Vedo un H1 per il titolo dell'album e sotto una lista di H3 per ciascuna canzone

Premi qui per vedere la risposta

Perchè?! Perchè il motore XSLT se incontra una regola per il nodo root la applica e non utilizza più le built-in rules. Quindi se non siamo noi a dire al processore di andarsi a cercare esplicitamente i tag titolo da mettere nel body HTML ... nessuno li andrà a prendere per noi.
Allora dovremo dire, per esempio:

<xsl:template match="/">
 <html>
  <head>
   <title><xsl:value-of select="album/titolo" /></title>
  </head>
 </html>
 <body>
  <xsl:apply-templates />
 </body>
</xsl:template>

Ecco un nuovo comando: apply-templates. Senza argomenti (cioè senza attributi) significa: "prendi tutto quello che trovi da qui in giù" e visto che siamo sul nodo root, saranno considerati tutti i discendenti di root.
E adesso quale avremo tra le risposte 1) e 3) ?

Avremo la risposta 4 :-) ! Infatti avremo sì un H1 per il titolo dell'album e degli H3 per i titoli delle canzoni, ma avremo anche il nome dell'autore (forse inaspettatamente!).
Che i titoli siano rappresentati nei giusti H* è perchè un processore XSLT deve sempre applicare la regola più vicina al nodo corrente. "//canzone/titolo" è più restrittiva di "titolo" e quindi nel caso dei titoli delle canzoni vince sulla regola più generica, che sarà invece applicata al tag titolo dell'album.
Ma invocando <xsl:apply-templates /> senza argomenti, andremo anche ad invocare una built-in rule che dice:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

Che prenderà quindi il nodo "album/autore/text()" e lo mostrerà in output.
Infatti se riscriviamo così il nostro XSLT:

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

<xsl:template match="/">
 <html>
  <head>
   <title><xsl:value-of select="album/titolo" /></title>
  </head>
 </html>
 <body>
  <xsl:apply-templates />
 </body>
</xsl:template>

<xsl:template match="titolo">
 <H1><xsl:value-of select="." /></H1>
</xsl:template>

<xsl:template match="//canzone/titolo">
 <H3><xsl:value-of select="." /></H3>
</xsl:template>

<xsl:template match="text()">
  <i><xsl:value-of select="."/></i>
</xsl:template>

</xsl:transform>

Ecco che il risultato sarà simile a prima, ma con il nome dell'autore in italico. Abbiamo cioè fatto un overriding del built-in template per "text()". Fra molte puntate (verso la fine di questa serie, direi, sarà chiaro fino in fondo che cosa stia succedendo in questo particolare case).

Ok. E' mezzanotte ... è ora di andare a letto ....
A domani.

Ecco i sorgenti:
http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/vasco01.xml
http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/vasco.xslt

Posted: nov 25 2003, 12.09 by paolo
Filed under:
Le misure di Marco sono on-line

Questa settimana Marco ci parla delle sue misure :-) non correlate...

 

Un XSLT al giorno ...

Ho deciso che da oggi, compatibilmente con i miei impegni, cercherò di pubblicare un esempio di codice/una mini lezione di XSLT ogni giorni.

Sì perché XSLT è in linguaggio che adoro :-) ma che utilizzano in pochi ... e magari parlandone nel mio blog riesco a fare un po' di proselitismo, o almeno credo di poterlo fare (lasciatemi questa vana illusione!).

Partiamo quindi dalla definizione e da un esempio di base.

XSLT = eXtensible Stylesheet Language for Transformation

In questo momento XSLT è una raccomandazione del W3C (del 16 novembre 1999! - http://www.w3.org/TR/xslt). Si parla da tempo di XSLT 2.0 (http://www.w3.org/TR/2003/WD-xslt20-20031112/ e siamo quasi pronti in effetti a vederlo sorgere ...). Ma cosa è XSLT? XSLT è un linguaggio (una grammatica XML) per trasformare contenuti XML in contenuti: XML, HTML, TXT.

E' pensato per lavorare con uno o più (vedremo più avanti nel tempo come) documenti XML in input per produrre diverse tipologie di output. L'output principe è XML, ma anche HTML e TXT. XSLT rientra nella più ampia famiglia di XSL (http://www.w3.org/Style/XSL/) che comprende: XSLT, XSL-FO (eXtensible Stylesheet Language for Formatting Objects) ed XPath (regole di ricerca di nodi all'interno di documenti XML).

XSLT in sostanza, utilizzando regole XPath, ci consente di cercare delle informazioni nei documenti XML sorgenti e riproporle, eventualmente rielaborate/riorganizzate, in output. E' molto comodo in tutte quelle situazioni in cui dobbiamo scambiare documenti XML con altre realtà e, a parità di contenuto informativo, i dati nei documenti XML hanno una organizzazione e una struttura (probabilmente uno schema XSD) differenti. E' molto comodo anche quando vogliamo presentare a degli utenti finali, sotto forma di HTML, dei documenti XML.

Vediamo un primo esempio

Partiamo dal documento:

<?xml version="1.0"?>
<ordine>
 <cliente codice="C01" piva="01234567890"
  email="paolo@devleap.com" />
 <righe>
  <riga idProdotto="P01" quantita="10" prezzo="20.23" />
  <riga idProdotto="P04" quantita="21" prezzo="11.86" />
  <riga idProdotto="P12" quantita="6" prezzo="42.18" />
 </righe>
</ordine>

Immaginiamo di voler ottenere in output un XML come questo:

<?xml version="1.0"?>
<order customerID="C01" items="3">
 <notifyTo>paolo@devleap.com</notifyTo>
 <item>
  <id>P01</id>
  <quantity>10</quantity>
  <euroPrice>20.23</euroPrice>
 </item>
 <item>
  <id>P04</id>
  <quantity>21</quantity>
  <euroPrice>11.86</euroPrice>
 </item>
 <item>
  <id>P12</id>
  <quantity>6</quantity>
  <euroPrice>42.18</euroPrice>
 </item>
</order>

Con XSLT è abbastanza semplice. Ecco un esempio di codice che fa al caso nostro:

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

 <xsl:template match="/">
  <order customerID="{ordine/cliente/@codice}"
   items="{count(ordine/righe/riga)}">
   <notifyTo><xsl:value-of select="ordine/cliente/@email" /></notifyTo>
   <xsl:for-each select="ordine/righe/riga">
    <item>
     <id><xsl:value-of select="@idProdotto" /></id>
     <quantity><xsl:value-of select="@quantita" /></quantity>
     <euroPrice><xsl:value-of select="@prezzo" /></euroPrice>
    </item>
   </xsl:for-each>
  </order>
 </xsl:template>

</xsl:transform>

I punti chiave di questo documento sono:

  • Si tratta di un documento XML well-formed, d'altra parte XSLT è una grammatica XML, quindi non poteva essere altrimenti.
  • Il nodo root del documento si chiama transform e fa parte del namespace http://www.w3.org/1999/XSL/Transform, al quale generalmente viene associato l'alias xsl. Vi deve essere l'indicazione della versione di XSLT che stiamo usando, per noi è la 1.0.
  • Quindi all'interno del tag transform possiamo trovare diversi child, secondo la grammatica XSLT. Uno di questi (uno dei più utilizzati tra l'altro) è il tag template con attributo match. Ecco che template definisce una regola di trasformazione per il nodo che corrisponde alla regola XPath "/", cioè per il documentElement del documento sorgente. In pratica stiamo dicendo che il documentElement (tag ordine) del documento sorgente deve generare in output il contenuto del tag template. Avremo quindi in output un tag order con all'interno degli attributi e degli altri tag.
  • Il fatto di indicare il valore di alcuni attributi del tag order tra parentesi graffe {XPath} implica che il motore di XSLT interpreti le regole XPath all'interno delle graffe e ne scriva il risultato in output. Quindi scriveremo il valore dell'attributo codice (perchè preceduto da @ secondo le regole XPath) del tag cliente, figlio di ordine: ordine/cliente/@codice.
  • Quindi scriveremo la conteggio count(ordine/righe/riga) dei tag di nome riga figli di righe, figlio di ordine (non fate battute scontate!).
  • Poi all'interno di un tag da generare in output, con nome notifyTo, andremo a scrivere il valore dell'attributo email del tag cliente, figlio di ordine. Per ottenere questo risultato usiamo il comando XSLT value-of che all'iterno del suo attributo select prevede ancora una volta una regola XPath che corrisponde al valore da noi cercato: ordine/cliente/@email
  • Quindi per ogni tag riga, figlio di righe con parent ordine (ordine/righe/riga) andremo a scrivere dei valori in output, ancora utilizzando il comando value-of. E' interessante notare il costrutto iterativo for-each che utilizza un attributo select per sapere su quale lista di nodi deve essere eseguito il ciclo.

Per oggi è tutto. Se avete dubbi, la mia email ce l'avete (paolo@devleap.com). Se ritenete che questa mia idea, di annoiarvi ogni giorno con qualche esempio e comando di XSLT, sia assolutamente inutile ... ditemelo prima che abbia perso un mese a scrivere tutti i post :-) ... ve ne sarò grato! :-)

Qui trovi i file sorgente degli esempi:
http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/ordine.xml
http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/FromOrdineToOrder.XSLT

http://www.devleap.com/Downloads/BLogs/Paolo/TutorialXSLT/order.xml

Posted: nov 23 2003, 03.14 by paolo
Filed under:
XQuery Tutorial

Da una segnalazione di Don Box, che però purtroppo citava una URL non più esistente, ho ritrovato il percorso corretto di un Tutorial su XQuery:

http://homepages.inf.ed.ac.uk/wadler/papers/xquery-tutorial/xquery-tutorial.pdf

Se interessa ad altri...

SharePoint Services FAQ

Sito web interessante: http://www.spsfaq.com/

Si aggiunge a quello già segnalato in passato da Marco.


Link: http://www.spsfaq.com/
WSE2

Da questo post di Christian Weyer si evince che il lancio di WSE2 finale non è così lontano nel tempo!

Bene!


Link: http://weblogs.asp.net/cweyer/posts/38166.aspx
WPC 2003: è già finito :-)

Come sempre il tempo vola. Non fai in tempo a pensare che non hai ancora visto/scritto/provato/testato tutto quello che avresti voluto per la prima sessione ... che ti trovi già a casa, con centinaia di email (molte delle quali spamming!) da leggere e con la WPC alle spalle.

E' stata una bella WPC. Sei sessioni è un numero strano ... non troppo stressante, ma nemmeno troppo rilassante. In generale preferisco il carico psicologico di WPC come quella del 2002 (11 sessioni) perché il fatto di non avere un minuto per respirare ti permette di non perdere mai la concentrazione. E' anche vero però che ogni rilassarsi, davanti ad una birra, non fa male.

A parte questo la conferenza in quanto tale mi è piaciuta. Il clima era piacevole. La closing mi è piaciuta molto, grande GioLib!

Le mie sessioni mi sono piaciute, in generale. Non ho particolari rimpianti, se non il fatto che questo anno ho sforato molto spesso (5 sessioni su 6) sui tempi ... e il bello è che temevo di avere poco materiale :-) ...

Ci terrei molto a dei feedback personali, schietti e costruttivi da chi c'era. La mia email ce l'avete (paolo@devleap.com) fatemi sapere cosa ne pensate, se vi sono piaciute ma soprattutto se non vi sono piaciute (e perché) le mie sessioni ... fa parte anche questo del "customer satisfaction" (sto imparando da Silvano :-) le regole del marketing ...).

Adesso dormo ...


Link: http://wpc.education.mondadori.it
WPC 2003: è arrivato

Ok! Adesso devo solo "impacchettare" i miei 3 PC per le demo, fare la valigia e spostarmi ad Assago.

Per chi è interessato, faccio il riepilogo delle mie sessioni, anche per aiutare chi è indeciso tra i vari titoli a scegliere la sessione per lui più interessante.

  • InfoPath...mai più XML? :-) : Ho preparato una sessione in cui, cercando di vincere i miei istinti :-), spiego come usare InfoPath per sviluppare mini-soluzioni di gestione di documenti ed informazioni, senza doversi sempre preoccupare di come è fatto e come si utilizza XML a basso livello.
    Ho detto che ho "cercato" non che ci sono riuscito :-), quindi vedremo anche come personalizzare i file di InfoPath in termini di contenuto, viste, script, taskpane, come generare aggregazioni di documenti InfoPath tramite XSLT, XSD e viste custom, come lavorare con InfoPath e SharePoint Team Services (sono davvero una bella coppia!), come fare deployment delle soluzioni. Il risultato mi piace ... spero di vedervi martedì (nonostante l'orario della sessione!!!!)
  • XML Web Services Platform Interoperability: Ho concentrato la sessione sulle situazioni tipiche di integrazione, da realizzare quando dobbiamo sviluppare dei Web Service che non servano solo per dire che "la nostra applicazione usa anche i Web Service" :-), ma che siano realmente utili a far dialogare differenti piattaforme. In pratica ci muoveremo dai tipi semplici, ai tipi complessi, alle strutture dati molto complesse come DataSet e typed DataSet e cercheremo di capire come esporre le nostre informazioni e i nostri servizi per renderli utilizzabili agli altri (principalmente Java) e laddove possibile anche compatibili con la specifica WS-I Basic Profile 1.0. Non sempre ci riusciremo o non sempre ci riusciremo in automatico, ma il bello di una sessione come questa, secondo me, è anche proprio capire quando ci si riesce e a quale prezzo, per decidere meglio come e cosa sviluppare in futuro.
  • BizTalk Server 2004 Technical Overview: E' il terzo anno di fila che mi occupo di BizTalk a WPC (no non sono vecchio quanto Marco Russo, io sono solo alla mia 4° WPC di fila) e questo anno potrò mostrarvi le novità della terza e nuova versione del prodotto. In particolare mi sono concentrato su ciò che di maggiormente certo e funzionante vi era nella Beta 2 (ultima versione a disposizione). Vedremo quindi l'integrazione con .NET e Visual Studio .NET, la Orchestration, il design di schema e mappe, il deployment delle soluzioni, daremo uno sguardo a cosa combina "sotto" BizTalk ora che parla .NET, vedremo come si integra con i Web Service e daremo un'occhiata ad un paio di soluzioni che ho preparato come demo che usano alcuni Adapter e un Web Service. Se avremo tempo vorrei anche raccontarvi cosa ho visto di nuovo a PDC, nella versione quasi-RTM del prodotto (che purtroppo però non sono riuscito a "rubare" :-) ...).
  • Securing XML Web Services: Piano piano ci stiamo avvicinando ad un mondo in cui i Web Service saranno sicuri. Come?! Non lo erano già?! Dipende ... In questa sessione, partendo dalle basi di XML Security (perchè è bene costruire su basi solide), vedremo come funziona la sicurezza dei Web Service non tanto e non solo in termini di sicurezza "custom" fatta in casa, ma anche in termini di WS-Security e WSA. Vedremo WS-Security, WS-SecureConversation, WS-Policy, WS-Trust prestando attenzione sia alla teoria (struttura dei messaggi SOAP ottenuti) che alla pratica (con WSE 1.0/2.0) e vedremo se e come sia possibile (magari passandoci le notti :-) ...) integrare Java e .NET in un contesto di sicurezza reale, basato su WS-Security.
  • Architecting ASP.NET Web Services: Le sessioni teoriche a me non piaccino molto. Io mi spiego meglio con il codice davanti e la tastiera in mano. Ho provato a costruire una sessione in cui, trattando a
Christian Weyer ci regala un bel tool!

Non è indispensabile, ma è carino:

http://weblogs.asp.net/cweyer/posts/35978.aspx


Link: http://weblogs.asp.net/cweyer/posts/35978.aspx
WPC2003 che fatica ... ma ci siamo quasi ! :-)

Ok. Le demo sono pronte (vorrei preparare ancora un paio di cosette :-)... ma già così vanno bene, almeno spero!). Devo solo spostarle con calma e attenzione sulle macchine demo finali.

Mi piacciono in particolare:

  • SoapExtension di autenticazione e validazione XSD per la sessione sul disegno e l'architettura di Web Service.
  • Le demo sull'integrazione tra InfoPath e SharePoint (ho fatto un paio di demo che mi piacciono parecchio sul merge dei documenti sia semplice che custom con XSLT - su stimolo di Gab che ci teneva tanto :-)!) per la sessione su InfoPath.
  • Le demo WS-Security per mostrare come usare WSE2 per ottenere autenticazione, firma digitale ed encryption con certificati X.509, per la sessione di WS-Security appunto.

Questa volta ho deciso di fare tutto (o quasi) su VmWare, voglio evitare situazioni spiacevoli come quella dello scorso anno (il lunedì sera, con la sessione il martedì, mi si era rotto l'hard disk del server BizTalk!).
Con VmWare (spero che non serva!!!) se dovesse accadere una cosa simile mi basterà avviare l'immagine da uno degli altri PC demo.

Ovviamente le immagini sono tutte su un bel DVD :-).

Ci vediamo domenica sera al Centro Congressi Milanofiori!

More Posts Next page »