Difference between revisions of "XSLT"
(→Com crear una estructura HTML) |
(→Estructura iterativa) |
||
| (28 intermediate revisions by the same user not shown) | |||
| Line 98: | Line 98: | ||
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||
<?xml-stylesheet type="text/xsl" href="fitxerXSL.xsl"?> | <?xml-stylesheet type="text/xsl" href="fitxerXSL.xsl"?> | ||
| − | < | + | <CATALOG> |
| − | < | + | <CD> |
| − | + | <TITLE>Empire Burlesque</TITLE> | |
| − | + | <ARTIST>Bob Dylan</ARTIST> | |
| − | + | <COUNTRY>USA</COUNTRY> | |
| − | + | <COMPANY>Columbia</COMPANY> | |
| − | + | <PRICE>10.90</PRICE> | |
| − | + | <YEAR>1985</YEAR> | |
| − | + | </CD> | |
| − | + | <CD> | |
| − | + | <TITLE>Hide your heart</TITLE> | |
| − | + | <ARTIST>Bonnie Tyler</ARTIST> | |
| − | + | <COUNTRY>UK</COUNTRY> | |
| − | + | <COMPANY>CBS Records</COMPANY> | |
| − | + | <PRICE>9.90</PRICE> | |
| − | + | <YEAR>1988</YEAR> | |
| − | + | </CD> | |
| − | + | </CATALOG> | |
| − | </ | ||
| − | </ | ||
</syntaxhighlight> | </syntaxhighlight> | ||
====Funcionament XSLT==== | ====Funcionament XSLT==== | ||
| Line 248: | Line 246: | ||
</xsl:template> | </xsl:template> | ||
</xsl:stylesheet> | </xsl:stylesheet> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | Pero veurem que en aquest cas ens torna a mostrar exactament la manteixa pàgina HTML que en cas anterior. No ha implementat la plantilla de l'etiqueta <code>YEAR</code>. | ||
| + | |||
| + | Per què no ha interpretat la plantilla? | ||
| + | |||
| + | No ho ha fet per que totes les etiquetes ja han estat incloses i per tant suposadament transformades dins la plantilla arrel (/), i per tant ja no s'han executat les altres plantilles. | ||
| + | |||
| + | En aquest cas tindriem dues solucions: | ||
| + | * Tractar totes les etiquetes dins la plantilla de l'arrel. | ||
| + | * Incloure una línia de codi que faci interpretar les altres plantilles. | ||
| + | |||
| + | Tractar totes les etiquetes dins l'arrel és possible, i de fet molts desenvolupadors treballen així. Però el codi resultant és molt llarg i brut i costa realitzar modificacions. Quan es comencen amb les transformacions és més senzill i net utilitzar la segona opció. | ||
| + | |||
| + | La línia a incloure per tal que la resta de plantilles siguin interpretades és: | ||
| + | <code><xsl:apply-templates></xsl:apply-templates></code> | ||
| + | I la inclourem dins l'etiqueta <code>body</code> de la plantilla de l'arrel: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <?xml version="1.0" encoding="UTF-8"?> | ||
| + | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> | ||
| + | <xsl:template match="/"> | ||
| + | <html> | ||
| + | <head> | ||
| + | <title>Títol de la pàgina</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | <xsl:apply-templates></xsl:apply-templates> | ||
| + | </body> | ||
| + | </html> | ||
| + | </xsl:template> | ||
| + | |||
| + | <xsl:template match="//YEAR"> | ||
| + | <p><b>Aqui hi haurà el valor de l'any</b></p> | ||
| + | </xsl:template> | ||
| + | |||
| + | </xsl:stylesheet> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | Si ara executem el següent codi, tindriem: | ||
| + | [[File:XSLHTML2.png|700px|thumb|centre|Resultat de XML + XSLT]] | ||
| + | Veiem que tornen a aparèixer els nodes que no tenen una plantilla definida, això és a causa de la instrucció <code><xsl:apply-templates></xsl:apply-templates></code> que fa que es tornin a interpretar les etiquetes i per tant les que no tenen plantilla tornen a executar-se pel mètode per defecte comentat anteriorment. | ||
| + | ====Aplicar plantilles==== | ||
| + | Per indicar en el nostre codi que volem aplicar una o vàries plantilles ja hem vist que podem utilitzar la instrucció <code><xsl:apply-templates></code>. Aquesta instrucció ens serveix per indicar que volem aplicar totes o alguna de les plantilles que tenim definides. | ||
| + | |||
| + | Si no indiquem res en la instrucció, en el punt on s'executa la instrucció s'aplicaran '''totes les plantilles''' definides. Que és el que hem fet fins ara en l'element arrel. | ||
| + | |||
| + | Per contra, si indiquem la plantilla que volem indicar, en aquell punt del programa s'aplicarà la plantilla indicada. Per exemple: | ||
| + | |||
| + | <syntaxhighlight lang="XML"> | ||
| + | <?xml version="1.0" encoding="UTF-8"?> | ||
| + | <xsl:stylesheet version="1.0" | ||
| + | xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | ||
| + | |||
| + | <xsl:template match="/"> | ||
| + | <html> | ||
| + | <body> | ||
| + | <h2>My CD Collection</h2> | ||
| + | <xsl:apply-templates/> | ||
| + | </body> | ||
| + | </html> | ||
| + | </xsl:template> | ||
| + | |||
| + | <xsl:template match="cd"> | ||
| + | <p> | ||
| + | <xsl:apply-templates select="title"/> | ||
| + | <xsl:apply-templates select="artist"/> | ||
| + | </p> | ||
| + | </xsl:template> | ||
| + | |||
| + | <xsl:template match="title"> | ||
| + | Title: <span style="color:#ff0000"> | ||
| + | <xsl:value-of select="."/></span> | ||
| + | <br /> | ||
| + | </xsl:template> | ||
| + | |||
| + | <xsl:template match="artist"> | ||
| + | Artist: <span style="color:#00ff00"> | ||
| + | <xsl:value-of select="."/></span> | ||
| + | <br /> | ||
| + | </xsl:template> | ||
| + | |||
| + | </xsl:stylesheet> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 256: | Line 336: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Aquesta etiqueta XSLT ens retorna el valor de l'element seleccionat dins l'atribut <code>select</code> utilitzant una sentència XPath. Hem de tenir en compte que com que estem dins una plantilla de transformació on ja s'ha seleccionat un element, el de la plantilla, la selecció en l'etiqueta <code>xsl:select</code> es farà a partir de l'element seleccionat en la plantilla. | Aquesta etiqueta XSLT ens retorna el valor de l'element seleccionat dins l'atribut <code>select</code> utilitzant una sentència XPath. Hem de tenir en compte que com que estem dins una plantilla de transformació on ja s'ha seleccionat un element, el de la plantilla, la selecció en l'etiqueta <code>xsl:select</code> es farà a partir de l'element seleccionat en la plantilla. | ||
| + | En el nostre exemple si canviem la frase "Aquí hi haurà el valor de l'any" per l'etiqueta <code><xsl:value-of select="."></xsl:value-of></code> tenint en compte que en el select hem inclòs la sentència XPath "." que fa referència a l'etiqueta <code>YEAR</code>. Ens quedarà un codi com aquest: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <?xml version="1.0" encoding="UTF-8"?> | ||
| + | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> | ||
| + | <xsl:template match="/"> | ||
| + | <html> | ||
| + | <head> | ||
| + | <title>Titol de la pàgina</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | <xsl:apply-templates></xsl:apply-templates> | ||
| + | </body> | ||
| + | </html> | ||
| + | </xsl:template> | ||
| + | <xsl:template match="//YEAR"> | ||
| + | <p><b><xsl:value-of select="."></xsl:value-of></b></p> | ||
| + | </xsl:template> | ||
| + | </xsl:stylesheet> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | Que mostrarà el següent: | ||
| + | [[File:XSLHTML3.png|700px|thumb|centre|Resultat de XML + XSLT]] | ||
| + | |||
| + | ===Exemple de creació de transformació=== | ||
| + | Quan volem fer una transformació, una de les primeres coses que hem de tenir clares és des d'on partim i on volem arribar. La primera de les preguntes la tindrem clara, doncs sempre disposarem del fitxer XML amb les dades que haurem de transformar. El que és més important tenir en compte és on volem arribar. Hem de tenir clar quin HTML hem d'acabar generant a partir de les dades XML. Per tant, la primera cosa que hem de tenir és un exemple de l'HTML a crear. | ||
| + | |||
| + | Seguint amb l'exemple que hem anat treballant, podem esperar arribar a un fitxer HTML com el que es mostra a continuació: | ||
| + | <syntaxhighlight lang="HTML"> | ||
| + | <html lang="en"> | ||
| + | <head> | ||
| + | <meta charset="UTF-8"/> | ||
| + | <meta http-equiv="X-UA-Compatible" content="IE=edge"/> | ||
| + | <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||
| + | <title>Títol de la pàgina</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | <h1>Llistat de CD's</h1> | ||
| + | <h2>Titol</h2> | ||
| + | <h3>Autor</h3> | ||
| + | <ul> | ||
| + | <li>Pais:UK</li> | ||
| + | <li>Companyia:CBS Records</li> | ||
| + | <li>Preu:9,70€</li> | ||
| + | <li>Any:1985</li> | ||
| + | </ul> | ||
| + | |||
| + | <h2>Titol</h2> | ||
| + | <h3>Autor</h3> | ||
| + | <ul> | ||
| + | <li>Pais:UK</li> | ||
| + | <li>Companyia:CBS Records</li> | ||
| + | <li>Preu:9,70€</li> | ||
| + | <li>Any:1985</li> | ||
| + | </ul> | ||
| + | </body> | ||
| + | </html> | ||
| + | </syntaxhighlight> | ||
| + | I quedaria un resultat similar al que es mostra: | ||
| + | [[File:Demo2.png|400px|thumb|centre|Resultat de XML + XSLT]] | ||
| + | En aquest punt, on ja tenim clar quin és el codi HTML que hem d'acabar generant el que hem de fer és determinar en quin codi HTML s'ha de transformar cada element del fitxer XML. | ||
| + | Començarem pel primer de tots els elements, l'arrel. Ja hem vist que l'element arrel s'ha de transformar en l'esquelet de la pàgina HTML a generar, ja que és l'únic element que no es repeteix. Per tant el nostre fitxer XSLT haurà de començar contenint: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <?xml version="1.0" encoding="UTF-8"?> | ||
| + | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> | ||
| + | <xsl:template match="/"> | ||
| + | <html lang="en"> | ||
| + | <head> | ||
| + | <meta charset="UTF-8"/> | ||
| + | <meta http-equiv="X-UA-Compatible" content="IE=edge"/> | ||
| + | <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||
| + | <title>Títol de la pàgina</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | <xsl:apply-templates></xsl:apply-templates> | ||
| + | </body> | ||
| + | </html> | ||
| + | </xsl:template> | ||
| + | </xsl:stylesheet> | ||
| + | </syntaxhighlight> | ||
| + | [[File:Demo3.png|400px|thumb|centre|Resultat de XML + XSLT]] | ||
| + | Veiem en la imatge que l'element arrel s'ha transformat bé en la plantilla HTML ja que apareix el títol de la pàgina i el valor de cada un dels element en tant que encara no tenen plantilla i per tant s'estan transformant a través del mètode per defecte. | ||
| + | El següent pas seria incloure el títol "Llistat de CD's". Aquest títol només ha d'aparèixer un cop i ha d'estar dins una etiqueta <code>h1</code>. Per tant, com que no és fruit de la transformació de cap element que es pugui repetir dins l'XML, haurem d'incloure-ho en la plantilla de l'element arrel. | ||
| + | El codi quedaria així: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <?xml version="1.0" encoding="UTF-8"?> | ||
| + | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> | ||
| + | <xsl:template match="/"> | ||
| + | <html lang="en"> | ||
| + | <head> | ||
| + | <meta charset="UTF-8"/> | ||
| + | <meta http-equiv="X-UA-Compatible" content="IE=edge"/> | ||
| + | <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||
| + | <title>Títol de la pàgina</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | <h1>Llistat de CD's</h1> | ||
| + | <xsl:apply-templates></xsl:apply-templates> | ||
| + | </body> | ||
| + | </html> | ||
| + | </xsl:template> | ||
| + | </xsl:stylesheet> | ||
| + | </syntaxhighlight> | ||
| + | I el resultat seria: | ||
| + | [[File:Demo4.png|400px|thumb|centre|Resultat de XML + XSLT]] | ||
| + | Un cop tenim l'estructura principal del codi HTML hem d'analitzar quin codi HTML es repeteix per cada element. Si ens fixem en l'HTML resultat i el XML original veiem que cada element <code>CD</code> del XML li correspon el següent codi HTML: | ||
| + | <syntaxhighlight lang="HTML"> | ||
| + | <h1>Llistat de CD's</h1> | ||
| + | <h2>Titol</h2> | ||
| + | <h3>Autor</h3> | ||
| + | <ul> | ||
| + | <li>Pais:UK</li> | ||
| + | <li>Companyia:CBS Records</li> | ||
| + | <li>Preu:9,70€</li> | ||
| + | <li>Any:1985</li> | ||
| + | </ul> | ||
| + | </syntaxhighlight> | ||
| + | Per tant la transformació a fer és que per cada element <code>CD</code> del XML cal generar l'HTML substituïnt els valors de mostra (Titol, Autor, UK, CBS Records,9,70€ i 1985) pels valors que continguin els elements del XML (TITLE,AUTHOR,COUNTRY,COMPANY,PRICE i YEAR) respectivament. | ||
| + | El codi XSLT quedaria de la següent manera: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> | ||
| + | <xsl:template match="/"> | ||
| + | <html lang="en"> | ||
| + | <head> | ||
| + | <meta charset="UTF-8"/> | ||
| + | <meta http-equiv="X-UA-Compatible" content="IE=edge"/> | ||
| + | <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||
| + | <title>Títol de la pàgina</title> | ||
| + | </head> | ||
| + | <body> | ||
| + | <h1>Llistat de CD's</h1> | ||
| + | <xsl:apply-templates></xsl:apply-templates> | ||
| + | </body> | ||
| + | </html> | ||
| + | </xsl:template> | ||
| + | |||
| + | <xsl:template match="/CATALOG/CD"> | ||
| + | <h2><xsl:value-of select="TITLE"></xsl:value-of></h2> | ||
| + | <h3><xsl:value-of select="ARTIST"></xsl:value-of></h3> | ||
| + | <ul> | ||
| + | <li><xsl:value-of select="COUNTRY"></xsl:value-of></li> | ||
| + | <li><xsl:value-of select="COMPANY"></xsl:value-of></li> | ||
| + | <li><xsl:value-of select="PRICE"></xsl:value-of></li> | ||
| + | <li><xsl:value-of select="YEAR"></xsl:value-of></li> | ||
| + | </ul> | ||
| + | </xsl:template> | ||
| + | </xsl:stylesheet> | ||
| + | </syntaxhighlight> | ||
| + | Hem utilitzat un únic template pels elements <code>/CATALOG/CD</code> de manera que per cada element CD es generi l'HTML que desitgem. Dins el template s'han colocat les etiquetes HTML de la transformació, i dins les mateixes el valors que marca l'element XML corresponent a la informació que ha de mostrar l'etiqueta HTML. | ||
| + | El resultat final és el següent: | ||
| + | [[File:Demo5.png|400px|thumb|centre|Resultat de XML + XSLT]] | ||
| + | ===Estructures de control=== | ||
| + | Com en tots els llenguatges de programació XSLT té un seguit d'estructures de control que permeten dirigir el fluxe d'execució del programa en funció d'una sèrie de condicions imposades pel programador. Anem a veure quines són. | ||
| + | ====Estructura condicional==== | ||
| + | L'estructura condicional és la que ens permet dirigir el fluxe d'execució en funció d'un valor. El que entenem per un "if". | ||
| + | |||
| + | La sintaxis en XSLT és la següent: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:if test="expressió"> | ||
| + | ...codi a executar si l'expressió és certa... | ||
| + | </xsl:if> | ||
| + | </syntaxhighlight> | ||
| + | Fixeu-vos que no existeix la sentència "else". | ||
| + | |||
| + | Així si per exemple volguéssim mostrar els cd's que el seu preu sigui superior a 10, sense utilitzar XPath podriem fer-ho: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:if test="price > 10"> | ||
| + | <tr> | ||
| + | <td><xsl:value-of select="title"/></td> | ||
| + | <td><xsl:value-of select="artist"/></td> | ||
| + | <td><xsl:value-of select="price"/></td> | ||
| + | </tr> | ||
| + | </xsl:if> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | ====Estructura multicondicional==== | ||
| + | Sovint necessitarem comparar el valor d'un element amb més d'un valor. Per fer-ho utilitzarem l'estructura multicondicional. És similar a l'estructura condicional, però en aquest cas ens permet comparar l'element amb més d'un valor. | ||
| + | La seva sintaxis és: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:choose> | ||
| + | <xsl:when test="expressio"> | ||
| + | ... codi a executar si cert ... | ||
| + | </xsl:when> | ||
| + | <xsl:otherwise> | ||
| + | ... codi a executar si no cert .... | ||
| + | </xsl:otherwise> | ||
| + | </xsl:choose> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | Per exemple si volguéssim diferenciar els CD's que valen més de 10 dels que valen entre 9 i 10 i de la resta, podriem fer-ho: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:choose> | ||
| + | <xsl:when test="price > 10"> | ||
| + | <td bgcolor="#ff00ff"> | ||
| + | <xsl:value-of select="artist"/> | ||
| + | </td> | ||
| + | </xsl:when> | ||
| + | <xsl:when test="price > 9"> | ||
| + | <td bgcolor="#cccccc"> | ||
| + | <xsl:value-of select="artist"/> | ||
| + | </td> | ||
| + | </xsl:when> | ||
| + | <xsl:otherwise> | ||
| + | <td> | ||
| + | <xsl:value-of select="artist"/> | ||
| + | </td> | ||
| + | </xsl:otherwise> | ||
| + | </xsl:choose> | ||
| + | </syntaxhighlight> | ||
| + | ====Estructura iterativa==== | ||
| + | '''AQUESTA ESTRUCTURA ÉS EQUIVALENT A UTILITZAR "APPLY-TEMPLATES". ES RECOMANA UTILITZAR "APPLY-TEMPLATES" JA QUE EL CODI QUEDA MÉS NET I ESTRUCTURAT''' | ||
| + | |||
| + | Existeix una estructura que permet iterar entre diferents elements que siguin del mateix tipus, el que seria un bucle. La seva sintaxis és: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:for-each select="expressio"> | ||
| + | ... codi a executar per cada element de l'expressió ... | ||
| + | </xsl-for-each> | ||
| + | </syntaxhighlight> | ||
| + | Així per exemple, si vull iterar sobre tots els CD's del xml, ho podria fer: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:for-each select="catalog/cd"> | ||
| + | <tr> | ||
| + | <td><xsl:value-of select="title"/></td> | ||
| + | <td><xsl:value-of select="artist"/></td> | ||
| + | </tr> | ||
| + | </xsl:for-each> | ||
| + | </syntaxhighlight> | ||
| + | O bé per tots elements cd que siguin de l'artista "Bob Dylan": | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:for-each select="catalog/cd[artist='Bob Dylan']"> | ||
| + | <tr> | ||
| + | <td><xsl:value-of select="title"/></td> | ||
| + | <td><xsl:value-of select="artist"/></td> | ||
| + | </tr> | ||
| + | </xsl:for-each> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | ===Ordenació resultats=== | ||
| + | En molts casos també necessitarem ordenar els resultats que ens retorna la sentència XPath. Això ho podem fer utilitzant la instrucció: <code><xsl-sort></code> | ||
| + | La ordenació la podem fer sobre els resultats que ens retorna XPath en un <code><xsl:apply-templates></code> o sobre una estructura iterativa. | ||
| + | |||
| + | Sobre apply-templates utilitzariem: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:apply-templates select="element"> | ||
| + | <xsl:sort select="condicioOrnacio"/> | ||
| + | </xsl:apply-templates> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | Així per exemple si volem ordenar els CD's per preu, ho podríem fer amb la següent exemple: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:apply-templates select="/CATALOG/CD"> | ||
| + | <xsl:sort select="PRICE"/> | ||
| + | </xsl:apply-templates> | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | D'altra banda si volem ordenar els resultats utlitzant <code>xsl:for-each</code> fariem servir el següent codi: | ||
| + | <syntaxhighlight lang="XML"> | ||
| + | <xsl:for-each select="/CATALOG/CD"> | ||
| + | <xsl:sort select="PRICE"/> | ||
| + | ... codi del bucle ... | ||
| + | </xsl:apply-templates> | ||
| + | </syntaxhighlight> | ||
Latest revision as of 14:34, 26 April 2022
Contents
Maneres de transformar un XML
XML està pensat sobretot per a emmagatzemar i intercanviar informació, de manera que si cal representar les dades d’una manera diferent per optimitzar un procés o per millorar-ne la visualització hi haurà diverses possibilitats:
- Desenvolupar un programa
Com que és relativament senzill treballar amb XML, es podria desenvolupar un programa que agafi les dades XML i generi la sortida tal com la volem. Això té l’inconvenient que caldrà tenir coneixements de programació i que pot representar molta feina encara que el que calgui fer sigui trivial. - Fer servir CSS
En molts casos una solució senzilla seria fer servir CSS per representar la informació de manera més amigable fent servir un navegador. Però només serveix per canviar la visualització, no per canviar el document. - Transformar el document
Una solució alternativa consisteix a transformar el document en un altre que estigui pensat per ser visualitzat. Hi ha molt formats que estan pensats sobretot per ser visualitzats: PDF, HTML, XHTML, etc.
CSS
Mitjançant llenguatge CSS podem modificar la manera com es representa la informació que conté el fitxer XMl i adaptar-la a les nostres necessitats. Aquest mètode té la limitació que no ens permet modificar la seqüència d'aparició de la informació ni ens permet afegir informació extra a la que mostra el XML. Per exemple, si tenim un fitxer XML amb la següent informació:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="books.css"?>
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>I l'enllacem amb el següent fitxer CSS
bookstore{
background-color: darkgray;
}
title{
font-size: 30px;
color:brown
}
book {
display: block;
}
author{
display: block;
font-size: 15px;
font-style:italic;
}
price {
display: block;
font-weight: bold;
padding-bottom: 30px;
}Com a resultat tindrem la següent pàgina web:
Tot i la modificació en la forma de presentació, CSS té moltes limitacions a l’hora de presentar la informació:
- La informació no pot ser reordenada con vulguem. L’única manera de simular el canvi d’ordre és fer servir posicionaments absoluts.
- Els atributs es poden mostrar però hi ha moltes limitacions per fer-ho.
- No es poden afegir estructures noves producte de càlculs o de procés de les dades del document.
- No té maneres senzilles de formatar les dades en pàgines de text per ser impreses.
Per tant, si l’objectiu final no és simplement decorar el fitxer sinó transformar-lo en un altre document totalment diferent, CSS no serveix. CSS no transforma el document sinó que simplement canvia la manera com es visualitza.
Transformacions
Per superar les mancances de CSS a l'hora de transformar documents va aparèixer un nou llenguatge :XSL
XSL és una família de llenguatges que ens permeten definir transformacions i presentacions de documents XML.
La família de llenguatges XSL està formada per tres llenguatges:
- XSL-FO(XSL Formatting Objects): és un llenguatge per definir el format que s'ha d'aplicar a un document.
- XSLT(XSL transformations): és un llenguatge per ens permet transformar documents XML.
- XPath: és un llenguatge que ens permet accedir a parts dels documents XML.
XPath
XSLT
XSLT (extensible stylesheet language for transformations) és un llenguatge de plantilles basat en XML que permet convertir l’estructura dels elements XML en altres documents.
Nosaltres l'utilitzarem per a partir de la informació que conté el fitxer XML generar un fitxer HTML per mostrar-ne la informació del mateix.
XSLT fa servir XPath per identificar les diferents parts de la informació del document XML. Un cop seleccionades les diferents parts del document XML, utilitzant XSLT, es segueixen una sèrie de patrons definits en el fitxer, que determinen com generar el document de sortida (HTML).
El fitxer XSLT actua de la mateixa manera com actua un fitxer CSS en HTML. Cal enllaçar el document XSLT amb el fitxer XML. Per crear aquest enllaç cal incloure en la capçalera del document XML la següent línia de codi:
<?xml-stylesheet type="text/xsl" href="fitxerXSL.xsl"?>Per tant, si volem enllaçar un full XSLT al document XML de l'exemple anterior aquest quedaria de la següent manera:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="fitxerXSL.xsl"?>
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
</CATALOG>Funcionament XSLT
El fitxer XSLT intentarà fer les tranformacions utilitzant les plantilles definides per cada un dels elements seleccionats per les mateixes. Una plantilla selecciona utilitzant XPath l'element que ha de transformar, i aplica les transformacions definides dins seu.
Si hi ha algun element que no es pugui processar amb una plantilla aquest es transformarà amb el funcionament per defecte:
- Si el node té contingut es retornarà el contingut del node
- Si el node no té contingut no es retornarà cap contingut
Els fitxers XSLT es defineixen amb les etiquetes <xsl:stylesheet>. Per tant, l'estructura mínima d'un fitxer XSLT seria:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
</xsl:stylesheet>La línia 1 és la capçalera de fitxer XML, en tant que es tracta d'un fitxer de llenguatge de marques XML. I la línia 2 és el node arrel que engloba tot el contingut del fitxer XSLT.
Per tant, si ara aquest fitxer el guardem amb el nom fitxerXSL.xsl, i el guardem en el mateix directori que el nostre XML, ja tindrem els dos fitxers enllaçats i el resultat seria alguna cosa semblant a això:
Podem veure que únicament apareixen els valors que contenen cada un dels elements del XML. Això és degut a que encara no hem definit cap plantilla de transformació, i per tant cap dels elements és seleccionat per una plantilla i per tant tots estan sent processats amb el comportament per defecte abans comentat.
Anem a crear una primera plantilla per processar, per exemple, els nodes YEAR. Volem que cada element YEAR mostri el text Aqui hi haurà el valor de l'any.
Ho fariem de la següent manera:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="//YEAR">
Aqui hi haurà el valor de l'any
</xsl:template>
</xsl:stylesheet>Les etiquetes <xsl:template match=""> són les que defineixen una plantilla. Dins de l'atribut match hi hem d'incloure la sentència XPath que seleccionarà els elements als que s'aplicarà la plantilla. En aquest cas volem que s'apliqui sobre els elements YEAR per tant, el nostre XPath serà //YEAR
I ara si apliquem el XSLT sobre el XML el resultat serà:
Podem comprovar que ara enlloc del valor de l'any, el que ha aparegut per pantalla ha estat el el text "Aquí hi haurà el valor de l'any". Per tant, l'element YEAR ha estat processat correctament i ha mostrar el valor que hem especificat a la plantilla.
Fixeu-vos que el text ha aparegut en cada una de les ocurrències de l'etiqueta YEAR. Per tant és com si féssim un bucle que passa per totes i cada una de les etiquetes.
Afegir contingut als elements
Serà habitual voler afegir contingut HTML dins la plantilla XSLT que hem creat. De fet, aquest és un dels objectius finals de fer les transformacions.
Per exemple, ens pot interessar mostrar el text Aquí hi haurà el valor de l'any en negreta.
Per fer-ho simplement haurem d'incloure dins la plantilla el codi HTML que necessitem per tal d'aconseguir el nostre objectiu de fer el text en negreta. Concretament quedaria de la següent manera:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" version="4.0"/>
<xsl:template match="//YEAR">
<b>Aqui hi haurà el valor de l'any </b>
</xsl:template>
</xsl:stylesheet>I el resultat quedaria de la següent manera:
I si volguéssim que a més ho fes dins un paràgraf HTML nou, fariem:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" version="4.0"/>
<xsl:template match="//YEAR">
<p><b>Aqui hi haurà el valor de l'any </b><p>
</xsl:template>
</xsl:stylesheet>I quedaria de la següent manera:
Fixeu-vos que cal afegir la línia <xsl:output method="html" version="4.0"/> per tal d'indicar que el fitxer de sortida serà HTML i que per tant s'interpretin les etiquetes b i p com a tals. En cas contrari s'entén que el resultat de la transformació és un XML i per tant no es reconeix l'etiqueta p com a paràgraf ni la b com a negreta.
Això canvia quan ja incloem les etiquetes html head body ja que el navegador amb aquestes etiquetes sí que entén que el document és un HTML i interpreta les etiquetes que trobi en el document com a tals.
Com crear una estructura HTML
Per crear l'estructura típica dels fitxers HTML:
<html>
<head>
</head>
<body>
</body>
</html>el primer que hem de tenir en compte és que aquesta estructura només cal repetir-la una vegada. Si la tinguéssim més d'un cop dins el mateix document aquest no seria vàlid ja que no seguiria la sintaxis HTML. Cal buscar un element dins el fitxer XML d'origen que només estigui un cop dins el document i transformar-lo a l'estructura HTML
Quin element no es repeteix mai en un fitxer XML?
L'arrel. Els documents XML sempre contenene una i només una arrel dins el document. En cas contrari el document XML no estaria ben format i per tant no seria vàlid per fer una transformació. Aprofitant aquest fet habitualment el que tot document XSLT que vulgui transformar a HTML té és la següent plantilla:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<head>
<title>Titol de la pàgina</title>
</head>
<body>
</body>
</html>
</xsl:template>
<xsl:stylesheet>D'aquesta manera el document resultant de fer la transformació contindrà el codi mínim per crear una pàgina web. Fixeu-vos que ja no ha calgut incloure l'etiqueta xsl:output per indicar que el document resultant és HTML. I el resultat final és:
Només ens queda afegir plantilles per cada un dels elements XML que volguem transformar. Per exemple:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<head>
<title>Títol de la pàgina</title>
</head>
<body>
</body>
</html>
</xsl:template>
<xsl:template match="//YEAR">
<p><b>Aqui hi haurà el valor de l'any</b></p>
</xsl:template>
</xsl:stylesheet>Pero veurem que en aquest cas ens torna a mostrar exactament la manteixa pàgina HTML que en cas anterior. No ha implementat la plantilla de l'etiqueta YEAR.
Per què no ha interpretat la plantilla?
No ho ha fet per que totes les etiquetes ja han estat incloses i per tant suposadament transformades dins la plantilla arrel (/), i per tant ja no s'han executat les altres plantilles.
En aquest cas tindriem dues solucions:
- Tractar totes les etiquetes dins la plantilla de l'arrel.
- Incloure una línia de codi que faci interpretar les altres plantilles.
Tractar totes les etiquetes dins l'arrel és possible, i de fet molts desenvolupadors treballen així. Però el codi resultant és molt llarg i brut i costa realitzar modificacions. Quan es comencen amb les transformacions és més senzill i net utilitzar la segona opció.
La línia a incloure per tal que la resta de plantilles siguin interpretades és:
<xsl:apply-templates></xsl:apply-templates>
I la inclourem dins l'etiqueta body de la plantilla de l'arrel:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<head>
<title>Títol de la pàgina</title>
</head>
<body>
<xsl:apply-templates></xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="//YEAR">
<p><b>Aqui hi haurà el valor de l'any</b></p>
</xsl:template>
</xsl:stylesheet>Si ara executem el següent codi, tindriem:
Veiem que tornen a aparèixer els nodes que no tenen una plantilla definida, això és a causa de la instrucció <xsl:apply-templates></xsl:apply-templates> que fa que es tornin a interpretar les etiquetes i per tant les que no tenen plantilla tornen a executar-se pel mètode per defecte comentat anteriorment.
Aplicar plantilles
Per indicar en el nostre codi que volem aplicar una o vàries plantilles ja hem vist que podem utilitzar la instrucció <xsl:apply-templates>. Aquesta instrucció ens serveix per indicar que volem aplicar totes o alguna de les plantilles que tenim definides.
Si no indiquem res en la instrucció, en el punt on s'executa la instrucció s'aplicaran totes les plantilles definides. Que és el que hem fet fins ara en l'element arrel.
Per contra, si indiquem la plantilla que volem indicar, en aquell punt del programa s'aplicarà la plantilla indicada. Per exemple:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="cd">
<p>
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="artist"/>
</p>
</xsl:template>
<xsl:template match="title">
Title: <span style="color:#ff0000">
<xsl:value-of select="."/></span>
<br />
</xsl:template>
<xsl:template match="artist">
Artist: <span style="color:#00ff00">
<xsl:value-of select="."/></span>
<br />
</xsl:template>
</xsl:stylesheet>Obtenir valors
En molts casos ens interessarà mostrar el valor de l'etiqueta en el nostre fitxer HTML generat. Ho haurem de fer utilitzant la següent etiqueta:
<xsl:value-of select="XXXXX"></xsl:value-of>Aquesta etiqueta XSLT ens retorna el valor de l'element seleccionat dins l'atribut select utilitzant una sentència XPath. Hem de tenir en compte que com que estem dins una plantilla de transformació on ja s'ha seleccionat un element, el de la plantilla, la selecció en l'etiqueta xsl:select es farà a partir de l'element seleccionat en la plantilla.
En el nostre exemple si canviem la frase "Aquí hi haurà el valor de l'any" per l'etiqueta <xsl:value-of select="."></xsl:value-of> tenint en compte que en el select hem inclòs la sentència XPath "." que fa referència a l'etiqueta YEAR. Ens quedarà un codi com aquest:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<head>
<title>Titol de la pàgina</title>
</head>
<body>
<xsl:apply-templates></xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="//YEAR">
<p><b><xsl:value-of select="."></xsl:value-of></b></p>
</xsl:template>
</xsl:stylesheet>Que mostrarà el següent:
Exemple de creació de transformació
Quan volem fer una transformació, una de les primeres coses que hem de tenir clares és des d'on partim i on volem arribar. La primera de les preguntes la tindrem clara, doncs sempre disposarem del fitxer XML amb les dades que haurem de transformar. El que és més important tenir en compte és on volem arribar. Hem de tenir clar quin HTML hem d'acabar generant a partir de les dades XML. Per tant, la primera cosa que hem de tenir és un exemple de l'HTML a crear.
Seguint amb l'exemple que hem anat treballant, podem esperar arribar a un fitxer HTML com el que es mostra a continuació:
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Títol de la pàgina</title>
</head>
<body>
<h1>Llistat de CD's</h1>
<h2>Titol</h2>
<h3>Autor</h3>
<ul>
<li>Pais:UK</li>
<li>Companyia:CBS Records</li>
<li>Preu:9,70€</li>
<li>Any:1985</li>
</ul>
<h2>Titol</h2>
<h3>Autor</h3>
<ul>
<li>Pais:UK</li>
<li>Companyia:CBS Records</li>
<li>Preu:9,70€</li>
<li>Any:1985</li>
</ul>
</body>
</html>I quedaria un resultat similar al que es mostra:
En aquest punt, on ja tenim clar quin és el codi HTML que hem d'acabar generant el que hem de fer és determinar en quin codi HTML s'ha de transformar cada element del fitxer XML. Començarem pel primer de tots els elements, l'arrel. Ja hem vist que l'element arrel s'ha de transformar en l'esquelet de la pàgina HTML a generar, ja que és l'únic element que no es repeteix. Per tant el nostre fitxer XSLT haurà de començar contenint:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Títol de la pàgina</title>
</head>
<body>
<xsl:apply-templates></xsl:apply-templates>
</body>
</html>
</xsl:template>
</xsl:stylesheet>Veiem en la imatge que l'element arrel s'ha transformat bé en la plantilla HTML ja que apareix el títol de la pàgina i el valor de cada un dels element en tant que encara no tenen plantilla i per tant s'estan transformant a través del mètode per defecte.
El següent pas seria incloure el títol "Llistat de CD's". Aquest títol només ha d'aparèixer un cop i ha d'estar dins una etiqueta h1. Per tant, com que no és fruit de la transformació de cap element que es pugui repetir dins l'XML, haurem d'incloure-ho en la plantilla de l'element arrel.
El codi quedaria així:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Títol de la pàgina</title>
</head>
<body>
<h1>Llistat de CD's</h1>
<xsl:apply-templates></xsl:apply-templates>
</body>
</html>
</xsl:template>
</xsl:stylesheet>I el resultat seria:
Un cop tenim l'estructura principal del codi HTML hem d'analitzar quin codi HTML es repeteix per cada element. Si ens fixem en l'HTML resultat i el XML original veiem que cada element CD del XML li correspon el següent codi HTML:
<h1>Llistat de CD's</h1>
<h2>Titol</h2>
<h3>Autor</h3>
<ul>
<li>Pais:UK</li>
<li>Companyia:CBS Records</li>
<li>Preu:9,70€</li>
<li>Any:1985</li>
</ul>Per tant la transformació a fer és que per cada element CD del XML cal generar l'HTML substituïnt els valors de mostra (Titol, Autor, UK, CBS Records,9,70€ i 1985) pels valors que continguin els elements del XML (TITLE,AUTHOR,COUNTRY,COMPANY,PRICE i YEAR) respectivament.
El codi XSLT quedaria de la següent manera:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Títol de la pàgina</title>
</head>
<body>
<h1>Llistat de CD's</h1>
<xsl:apply-templates></xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="/CATALOG/CD">
<h2><xsl:value-of select="TITLE"></xsl:value-of></h2>
<h3><xsl:value-of select="ARTIST"></xsl:value-of></h3>
<ul>
<li><xsl:value-of select="COUNTRY"></xsl:value-of></li>
<li><xsl:value-of select="COMPANY"></xsl:value-of></li>
<li><xsl:value-of select="PRICE"></xsl:value-of></li>
<li><xsl:value-of select="YEAR"></xsl:value-of></li>
</ul>
</xsl:template>
</xsl:stylesheet>Hem utilitzat un únic template pels elements /CATALOG/CD de manera que per cada element CD es generi l'HTML que desitgem. Dins el template s'han colocat les etiquetes HTML de la transformació, i dins les mateixes el valors que marca l'element XML corresponent a la informació que ha de mostrar l'etiqueta HTML.
El resultat final és el següent:
Estructures de control
Com en tots els llenguatges de programació XSLT té un seguit d'estructures de control que permeten dirigir el fluxe d'execució del programa en funció d'una sèrie de condicions imposades pel programador. Anem a veure quines són.
Estructura condicional
L'estructura condicional és la que ens permet dirigir el fluxe d'execució en funció d'un valor. El que entenem per un "if".
La sintaxis en XSLT és la següent:
<xsl:if test="expressió">
...codi a executar si l'expressió és certa...
</xsl:if>Fixeu-vos que no existeix la sentència "else".
Així si per exemple volguéssim mostrar els cd's que el seu preu sigui superior a 10, sense utilitzar XPath podriem fer-ho:
<xsl:if test="price > 10">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
<td><xsl:value-of select="price"/></td>
</tr>
</xsl:if>Estructura multicondicional
Sovint necessitarem comparar el valor d'un element amb més d'un valor. Per fer-ho utilitzarem l'estructura multicondicional. És similar a l'estructura condicional, però en aquest cas ens permet comparar l'element amb més d'un valor. La seva sintaxis és:
<xsl:choose>
<xsl:when test="expressio">
... codi a executar si cert ...
</xsl:when>
<xsl:otherwise>
... codi a executar si no cert ....
</xsl:otherwise>
</xsl:choose>Per exemple si volguéssim diferenciar els CD's que valen més de 10 dels que valen entre 9 i 10 i de la resta, podriem fer-ho:
<xsl:choose>
<xsl:when test="price > 10">
<td bgcolor="#ff00ff">
<xsl:value-of select="artist"/>
</td>
</xsl:when>
<xsl:when test="price > 9">
<td bgcolor="#cccccc">
<xsl:value-of select="artist"/>
</td>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:value-of select="artist"/>
</td>
</xsl:otherwise>
</xsl:choose>Estructura iterativa
AQUESTA ESTRUCTURA ÉS EQUIVALENT A UTILITZAR "APPLY-TEMPLATES". ES RECOMANA UTILITZAR "APPLY-TEMPLATES" JA QUE EL CODI QUEDA MÉS NET I ESTRUCTURAT
Existeix una estructura que permet iterar entre diferents elements que siguin del mateix tipus, el que seria un bucle. La seva sintaxis és:
<xsl:for-each select="expressio">
... codi a executar per cada element de l'expressió ...
</xsl-for-each>Així per exemple, si vull iterar sobre tots els CD's del xml, ho podria fer:
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
</tr>
</xsl:for-each>O bé per tots elements cd que siguin de l'artista "Bob Dylan":
<xsl:for-each select="catalog/cd[artist='Bob Dylan']">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
</tr>
</xsl:for-each>Ordenació resultats
En molts casos també necessitarem ordenar els resultats que ens retorna la sentència XPath. Això ho podem fer utilitzant la instrucció: <xsl-sort>
La ordenació la podem fer sobre els resultats que ens retorna XPath en un <xsl:apply-templates> o sobre una estructura iterativa.
Sobre apply-templates utilitzariem:
<xsl:apply-templates select="element">
<xsl:sort select="condicioOrnacio"/>
</xsl:apply-templates>Així per exemple si volem ordenar els CD's per preu, ho podríem fer amb la següent exemple:
<xsl:apply-templates select="/CATALOG/CD">
<xsl:sort select="PRICE"/>
</xsl:apply-templates>D'altra banda si volem ordenar els resultats utlitzant xsl:for-each fariem servir el següent codi:
<xsl:for-each select="/CATALOG/CD">
<xsl:sort select="PRICE"/>
... codi del bucle ...
</xsl:apply-templates>