Diferencia entre revisiones de «XSLT»

De MediaWiki
Ir a la navegación Ir a la búsqueda
 
(No se muestran 40 ediciones intermedias del mismo usuario)
Línea 1: Línea 1:
 +
 +
[[Category:LMSXI]]
 +
 +
[[File:Xsl_icon.png|right]]
  
 
= XSLT =
 
= XSLT =
Línea 12: Línea 16:
 
: linguaxe que nos permite formatear os datos contidos no documento XML. Traballa con áreas, bloques, rexións, anchuras e alturas das páginas, dos márxenes, etc. Moi utilizado para xenerar ficheiros PDF a partir de documentos XML.
 
: linguaxe que nos permite formatear os datos contidos no documento XML. Traballa con áreas, bloques, rexións, anchuras e alturas das páginas, dos márxenes, etc. Moi utilizado para xenerar ficheiros PDF a partir de documentos XML.
  
XSLT permítenos transformar un documento XML engadindo ou eliminando etiquetas ou atributos no documento final, reorganizando os seus elementos, ordenalos segundo algún criterio, etc. Así poderemos crear distintos documentos a partir dun mesmo XML orixe, ou ter distintas vistas da mesma información (dun mesmo documento con información dos meus clientes poido obtener un listado dos morosos, as etiquetas para as cartas que se lles envía ou información sobre a súa facturación, e todo como resultado de aplicar distintos XSLTs ó mesmo documento).
+
XSLT '''permítenos transformar un documento XML''' engadindo ou eliminando etiquetas ou atributos no documento final, reorganizando os seus elementos, ordenalos segundo algún criterio, etc. Así poderemos crear distintos documentos a partir dun mesmo XML orixe, ou ter distintas vistas da mesma información (dun mesmo documento con información dos meus clientes poido obtener un listado dos morosos, as etiquetas para as cartas que se lles envía ou información sobre a súa facturación, e todo como resultado de aplicar distintos XSLTs ó mesmo documento).
  
XSLT é unha linguaxe declarativa: as follas de estilo XSLT non se escriben como unha secuencia de instruccións, se non coma unha colección de plantillas (''template rules''). Cada plantilla establece cómo se transforma un determinado elemento (definido mediante expresións XPath). O seu funcionamento básico consiste en aplicar transformacións a aquelas partes do documento seleccionadas a través dunha expresión XPath que encaixan con alguhna plantilla:
+
XSLT é unha '''linguaxe declarativa''': as follas de estilo XSLT non se escriben como unha secuencia de instruccións, se non coma unha colección de plantillas (''template rules''). Cada plantilla establece cómo se transforma un determinado elemento (definido mediante expresións XPath). O seu funcionamento básico consiste en aplicar transformacións a aquelas partes do documento seleccionadas a través dunha expresión XPath que encaixan con alguhna plantilla:
 
* O procesador analiza o documento e constrúe a árbore do documento.
 
* O procesador analiza o documento e constrúe a árbore do documento.
 
* O procesador recorre a árbore do documento desde o nodo raíz.
 
* O procesador recorre a árbore do documento desde o nodo raíz.
Línea 20: Línea 24:
 
:* Se a un nodo non se lle pode aplicar ningunha plantilla, aplícaselle un patrón predefinido, que copia o seu contenido no documento final (o texto do nodo, non o dos nodos descendentes). A continuación, o procesador recorre os seus nodos hijos.
 
:* Se a un nodo non se lle pode aplicar ningunha plantilla, aplícaselle un patrón predefinido, que copia o seu contenido no documento final (o texto do nodo, non o dos nodos descendentes). A continuación, o procesador recorre os seus nodos hijos.
 
:* Se a un nodo se lle pode aplicar unha plantilla, se lle aplica. A plantilla pode generar texto que se inclúe no documento final. En principio, o procesador non recorre os seus nodos fillos, salvo que a plantilla indique ó procesador que sí que deben recorrerse os nodos fillos.
 
:* Se a un nodo se lle pode aplicar unha plantilla, se lle aplica. A plantilla pode generar texto que se inclúe no documento final. En principio, o procesador non recorre os seus nodos fillos, salvo que a plantilla indique ó procesador que sí que deben recorrerse os nodos fillos.
* Cuando o procesador recorreu a árbore, a transformación rematou
+
* Cando o procesador recorreu a árbore, a transformación rematou
 +
 
 +
== Versións ==
 +
É un estándar do W3C con tres versións:
 +
<div style="column-count:3;-moz-column-count:3;-webkit-column-count:3">
 +
* [http://www.w3.org/TR/xslt XSLT 1.0]
 +
* [http://www.w3.org/TR/xslt20/ XSLT 2.0]
 +
* [http://www.w3.org/TR/xslt-30/ XSLT 3.0]
 +
</div>
 +
 
 +
Podes ver un resumo das melloras entre versións na [https://en.wikipedia.org/wiki/XSLT#History Wikipedia], e exemplos das novas posibiidades da [https://www.xml.com/articles/2017/02/14/why-you-should-be-using-xslt-30/ versión 3.0].
  
 
= Estrutura dun documento =
 
= Estrutura dun documento =
Una hoja de estilo XSLT es un documento XML que tiene la siguiente estructura:  
+
Unha folla de estilo XSLT é un documento XML que ten a seguinte estrutura:  
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> </xsl:stylesheet>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
En lugar de xsl:stylesheet se puede utilizar la etiqueta xls:transform. Esta instrucción es la etiqueta raíz de la hoja de estilo y sus atributos indican la versión y el espacio de nombres correspondiente (un documento XSLT siempre tiene que utilizar un espacio de nombres).
+
No lugar de xsl:stylesheet pódese utilizar a etiqueta xls:transform. Esta instrucción é a etiqueta raíz da folla de estilo e os seus atributos indican a versión e o espazo de nomes correspondente (un documento XSLT sempre ten que utilizar un espazo de nomes).
  
Para enlazar el documento XML a la hoja de estilo, añadiremos antes del elemento raíz del documento XML la siguiente instrucción de procesamiento:  
+
Para enlazar o documento XML á folla de estilo engadiremos antes do elemento raíz do documento XML a seguinte instrucción de procesamento:  
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
Línea 37: Línea 53:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Dentro de la instrucción <xsl:stylesheet> se pueden encontrar los llamados elementos de alto nivel y las plantillas:  
+
Dentro da instrucción <xsl:stylesheet> podense atopar os denominados elementos de alto nivel e as plantillas:  
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> </xsl:template> </xsl:stylesheet>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 +
    <xsl:output method="xml" indent="yes"/>
 +
    <xsl:template match="/"></xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Donde:
+
Onde:
* el elemento de alto nivel <xsl:output> indica el tipo de salida producida.
+
* o elemento de alto nivel <xsl:output> indica o tipo de saída producida.
* la instrucción <xsl:template> es una plantilla.
+
* a instrucción <xsl:template> é unha plantilla.
:* El atributo match indica los elementos afectados por la plantilla y contiene una expresión XPath.
+
:* O atributo ''match'' indica os elementos afectados pola plantilla e contén una expresión XPath.
:* El contenido de la instrucción define la transformación a aplicar (si la instrucción no contiene nada, como en el ejemplo anterior, sustituirá el nodo por nada, es decir, eliminará el nodo, aunque conservará el texto contenido en el elemento).
+
:* O contido da instrucción define a transformación a aplicar (se a instrucción non contén nada coma no exemplo anterior, sustituirá o nodo por nada, o que quere dicir que eliminará o nodo, aínda que conservará o texto contido no elemento).
Cuando se aplica una plantilla a un nodo, en principio no se recorren los nodos descendientes. Para indicar que sí queremos recorrer los nodos descendientes y aplicarles las plantillas que les correspondan, hay que utilizar la instrucción <xsl:apply-templates />, como en el ejemplo siguiente:
+
 
 +
Cando se aplica unha plantilla a un nodo, en principio non se recorren os nodos descendentes. Para indicar que sí queremos recorrer os nodos descendentes e aplicarlles as plantillas que lles correspondan hao que utilizar a instrucción <xsl:apply-templates />, coma no seguinte exemplo:
 +
 
 +
PENDIENTE
  
 
== Plantillas ==
 
== Plantillas ==
Para construir plantillas usamos el elemento xsl:template: <xsl:template match=”expresión XPath”> </xsl:template>
+
Para construir plantillas usamos o elemento xsl:template:  
Estas plantillas contienen reglas que se aplican a los nodos que encajan con su atributo match. El resultado del procesamiento de las reglas conformará el documento resultante de la transformación.
+
 
Por ejemplo, al siguiente documento XML:  
+
<syntaxhighlight lang="xslt">
 +
<xsl:template match=”expresión XPath”> </xsl:template>
 +
</syntaxhighlight>
 +
 
 +
Estas plantillas conteñen reglas que se aplican aos nodos que encaixan co seu atributo ''match''. O resultado do procesamiento das reglas conformará o documento resultante da transformación.
 +
 
 +
Por exemplo, ó seguinte documento XML:  
  
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="UTF-8"?> <Curso horas=”30”> <Asistente>Simon Templar</Asistente> <Asistente>Ralph Hinkley</Asistente> <Asistente>Maddie Hayes</Asistente> <Asistente>Blanche Devereaux</Asistente> </Curso>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<Curso horas=”40”>
 +
    <Asistente>Pepe Carballeira</Asistente>
 +
    <Asistente>Rafael Chousa</Asistente>
 +
    <Asistente>Ana Chamadoira</Asistente>
 +
    <Asistente>Alba Pereira</Asistente>
 +
</Curso>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
se le pueden aplicar cualquiera de las siguientes transformaciones:  
+
Se lle poden aplicar calquiera das seguintes transformacións:  
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//Curso">
+
<?xml version="1.0" encoding="UTF-8"?>
</xsl:template> </xsl:stylesheet>  
+
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="//Curso"></xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//Asistente"> … </xsl:template> </xsl:stylesheet>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="//Asistente">  
 +
   
 +
    </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Cuando aplicamos la primera plantilla, el único elemento del documento origen que cumple la expresión XPath es el elemento raíz (Curso).
+
Cuando aplicamos a primeira plantilla o único elemento do documento orixe que cumple a expresión XPath é o elemento raíz (Curso).
 +
 
 +
Aplicando a segunda plantilla, hai catro elementos que cumplirán a expresión, e as reglas que forman a plantilla procesaríanse unha vez por cada un deles.
  
Si aplicamos la segunda plantilla, habría cuatro elementos que cumplirían la expresión, y las reglas que forman la plantilla se procesarían una vez por cada uno de ellos.
+
As plantillas poden ter un atributo ''name'' en lugar do atributo ''match'' . Neste caso o que facemos é definir, non aplicar as reglas que compoñen a plantilla. Estas reglas aplicaríanse cando se chame á plantilla empregando a seguinte estrutura:
  
En lugar del atributo match, las plantillas pueden tener un atributo name. En este caso, lo que hacemos es definir, no aplicar las reglas que componen la plantilla. Estas reglas se aplicarían cuando se llame a la plantilla empleando la siguiente estructura: <xsl:call-template name=”nombreDeLaPlantilla”/>
+
<syntaxhighlight lang="xslt">
 +
<xsl:call-template name=”nombreDeLaPlantilla”/>
 +
</syntaxhighlight>
  
Aunque no es muy utilizado, también es posible crear plantillas que tengan ambos atributos: match y name.
+
Aínda que non é moi utilizado é posible crear plantillas que teñan ambos atributos: ''match'' e ''name''.
  
 
==  Contido ==
 
==  Contido ==
 
=== Texto: <xsl:text> ===
 
=== Texto: <xsl:text> ===
Se utiliza para incluir texto en el documento resultante. También se puede escribir el texto directamente en la plantilla, pero utilizando este elemento se pueden controlar los espacios y saltos de línea generados. Las siguientes plantillas son similares:  
+
Útilizase para incluir texto no documento resultante. Tamén se pode escribir ó texto directamente na plantilla, pero utilizando este elemento pódense controlar os espazos e saltos de liña xenerados.  
 +
 
 +
As seguintes plantillas son similares:  
  
 +
<div style="column-count:2;-moz-column-count:2;-webkit-column-count:2">
 +
<syntaxhighlight lang="xslt">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="//Asistente">
 +
        <xsl:text>Encontrado un asistente!</xsl:text>
 +
    </xsl:template>
 +
</xsl:stylesheet>
 +
</syntaxhighlight>
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//Asistente"> <xsl:text>Encontrado un asistente!</xsl:text> </xsl:template> </xsl:stylesheet> <?xml version="1.0" encoding="UTF-8"?>
+
 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//Asistente"> Encontrado un asistente! </xsl:template> </xsl:stylesheet>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="//Asistente"> Encontrado un asistente! </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
</div>
  
 
=== Elementos: <xsl:element> ===
 
=== Elementos: <xsl:element> ===
Crea un nuevo elemento en el documento resultante. El atributo name indica el nombre del nuevo elemento. Este atributo se puede componer como combinación de texto, partes del documento original, variables, valores devueltos por funciones, etc.
+
Crea un novo elemento no documento resultante. O atributo ''name'' indica o nome do nuevo elemento. Este atributo pódese compoñer coma:
 +
 
 +
<div style="column-count:5;-moz-column-count:5;-webkit-column-count:5">
 +
* combinación de texto
 +
* partes do documento orixinal
 +
* variables
 +
* valores devoltos por funcións
 +
* etc.
 +
</div>
  
 
=== Atributos: <xsl:attribute> ===
 
=== Atributos: <xsl:attribute> ===
Crea un nuevo atributo en el elemento del documento resultante. El valor del atributo name será el nombre del nuevo atributo.  
+
Crea un novo atributo no elemento do documento resultante. O valor do atributo ''name'' será o nome do novo atributo.  
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//Curso"> <xsl:element name="Curso"> <xsl:attribute name="asistentes"> <xsl:value-of select="count(Asistente)"/> </xsl:attribute> <xsl:element name="Horas"> <xsl:value-of select="@horas"/> </xsl:element> </xsl:element> </xsl:template> </xsl:stylesheet>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="//Curso">
 +
        <xsl:element name="Curso">
 +
            <xsl:attribute name="asistentes">
 +
                <xsl:value-of select="count(Asistente)"/>
 +
            </xsl:attribute>
 +
            <xsl:element name="Horas">
 +
                <xsl:value-of select="@horas"/>
 +
            </xsl:element>
 +
        </xsl:element>
 +
    </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Línea 100: Línea 187:
  
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
<Curso asistentes="4"> <Horas>30</Horas> </Curso>
+
<Curso asistentes="4">
 +
    <Horas>30</Horas>
 +
</Curso>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
También es posible definir un conjunto de atributos para luego utilizarlos en uno o varios elementos. Esto se realiza con:
+
Tamén é posible definir un conxunto de atributos para logo utilizalos en un ou varios elementos. Esto realiza con <xsl:attribute-set>:
<xsl:attribute-set>  
 
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:attribute-set name="datos"> <xsl:attribute name="nombre">
+
<?xml version="1.0" encoding="UTF-8"?>
<xsl:value-of select="."/> </xsl:attribute> <xsl:attribute name="horas"> <xsl:value-of select="/Curso/@horas"/> </xsl:attribute> </xsl:attribute-set> <xsl:template match="//Asistente"> <xsl:element name="Asistente" use-attribute-sets="datos"/> </xsl:template> </xsl:stylesheet>
+
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:attribute-set name="datos">
 +
        <xsl:attribute name="nombre">
 +
            <xsl:value-of select="."/>
 +
        </xsl:attribute>
 +
        <xsl:attribute name="horas">
 +
            <xsl:value-of select="/Curso/@horas"/>
 +
        </xsl:attribute>
 +
    </xsl:attribute-set>
 +
    <xsl:template match="//Asistente">
 +
        <xsl:element name="Asistente" use-attribute-sets="datos"/>
 +
    </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
El elemento <xsl:value-of> permite obtener el valor devuelto por funciones o el valor de elementos concretos del documento original.
+
O elemento <xsl:value-of> permite obter o valor devolto por funcións ou o valor de elementos concretos do documento orixinal.
  
 
=== Comentarios: <xsl:comment> ===
 
=== Comentarios: <xsl:comment> ===
Crea comentarios en el documento de salida con el formato <!-- comentario ... -->
+
Crea comentarios no documento de saída co formato <!-- comentario ... -->
  
=== Instrucciones de procesamiento: <xsl:processing-instruction> ===
+
=== Instruccións de procesamento: <xsl:processing-instruction> ===
Inserta una instrucción de procesamiento en el documento resultante. Como en los elementos <xsl:element> y <xsl:attribute>, cada elemento <xsl:processing-instruction> tiene un atributo name obligatorio.
+
Inserta una instrucción de procesamento no documento resultante. Coma nos elementos <xsl:element> e <xsl:attribute>, cada elemento <xsl:processing-instruction> ten un atributo ''name'' obrigatorio.
  
 
== Documentos con varias plantillas ==
 
== Documentos con varias plantillas ==
Línea 123: Línea 224:
  
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="curso2.xsl"?> <Curso horas="30"> <Asistente>Simon Templar</Asistente> <Asistente>Ralph Hinkley</Asistente> <Asistente>Maddie Hayes</Asistente> <Asistente>Blanche Devereaux</Asistente> <Tema>Xeración de documentos XML</Tema> <Tema>Validación de documentos XML</Tema> <Tema>Transformación de documentos XML</Tema> </Curso>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<?xml-stylesheet type="text/xsl" href="curso2.xsl"?>
 +
<Curso horas="40">
 +
    <Asistente>Pepe Carballeira</Asistente>
 +
    <Asistente>Rafael Chousa</Asistente>
 +
    <Asistente>Ana Chamadoira</Asistente>
 +
    <Asistente>Alba Pereira</Asistente>
 +
    <Tema>Xeración de documentos XML</Tema>
 +
    <Tema>Validación de documentos XML</Tema>
 +
    <Tema>Transformación de documentos XML</Tema>
 +
</Curso>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Aplicamos la siguiente transformación:  
+
Aplicamos a seguinte transformación:  
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
 
<?xml version="1.0" encoding="UTF-8"?>
 
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//Asistente"> Encontramos un asistente. </xsl:template> <xsl:template match="//Tema"> Encontramos un tema. </xsl:template> </xsl:stylesheet>
+
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="//Asistente"> Encontramos un asistente. </xsl:template>
 +
    <xsl:template match="//Tema"> Encontramos un tema. </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Como los elementos Asistente y Tema están al mismo nivel (ninguno de ellos es hijo del otro), se procesan ambas plantillas y se obtiene el siguiente documento resultante: Encontramos un asistente. Encontramos un asistente. Encontramos un asistente. Encontramos un asistente. Encontramos un tema. Encontramos un tema. Encontramos un tema.
+
Coma os elementos Asistente y Tema están ó mesmo nivel (ningún deles é fillo do outro), procésanse ambas plantillas e obtense o siguiente documento resultante:  
Sin embargo, si procesásemos el mismo documento origen con el siguiente documento XSLT: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//Curso"> Encontramos un curso. </xsl:template> <xsl:template match="//Asistente"> Encontramos un asistente. </xsl:template> </xsl:stylesheet>
+
<pre>
 +
Encontramos un asistente.  
 +
Encontramos un asistente.  
 +
Encontramos un asistente.  
 +
Encontramos un asistente.  
 +
Encontramos un tema.  
 +
Encontramos un tema.  
 +
Encontramos un tema.
 +
</pre>
  
Se podría esperar que el resultado mostrara “Encontramos un asistente” repetido cuatro veces y, a continuación, “Encontramos un curso” una vez. Sin embargo, la salida que produce es simplemente: “Encontramos un curso”.
+
Mais se procesásemos o mesmo documento orixe co seguinte documento XSLT:
  
La razón es que el procesador encuentra la plantilla con la expresión //Asistente que encaja con los elementos Asistente, y la plantilla con la expresión //Curso, que encaja con el elemento Curso. Como los elementos encontrados por la primera expresión ya están contenidos en el elemento
+
<syntaxhighlight lang="xslt">
Curso (son sus hijos), esta plantilla no llega a aplicarse.
+
<?xml version="1.0" encoding="UTF-8"?>
Esto es, los elementos Asistente se procesarán con la plantilla de la expresión //Curso, que es de mayor nivel, y no se muestra nada referente a los asistentes en el documento resultante porque las reglas de la plantilla no lo contemplan.
+
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="//Curso"> Encontramos un curso. </xsl:template>
 +
    <xsl:template match="//Asistente"> Encontramos un asistente. </xsl:template>
 +
</xsl:stylesheet>
 +
</syntaxhighlight>
  
Para que al aplicar una plantilla sobre un elemento continúe procesando sus hijos, tendríamos que incluir el elemento <xsl:apply-templates> dentro de la plantilla. Este elemento tiene un atributo “select” que permite restringir los hijos sobre los que seguir procesando la plantilla: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/Curso"> Encontramos un curso. <xsl:apply-templates select=”Tema”/> </xsl:template> <xsl:template match="Asistente"> Encontramos un asistente. </xsl:template> <xsl:template match="Tema"> Encontramos un tema. </xsl:template>
+
O resultado amosaría “Encontramos un asistente” repetido catro veces e a continuación “Encontramos un curso” unha vez? Non. A saída que produce é simplemente:  
  
En este caso la salida sería: Encontramos un curso. Encontramos un tema. Encontramos un tema. Encontramos un tema.
+
<pre>
 +
“Encontramos un curso”.
 +
</pre>
 +
 
 +
A razón é que o procesador atopa a plantilla coa expresión //Asistente que encaixa cos elementos Asistente, e a plantilla coa expresión //Curso, que encaixa co elemento Curso. Coma os elementos atopados pola primeira expresión xa están contidos no elemento Curso (son os seus fillos), esta plantilla non chega a aplicarse.
 +
 
 +
Porén, os elementos Asistente procesaranse coa plantilla da expresión //Curso, que é de maior nivel, e non se mostra nada referente aos asistentes no documento resultante porque as reglas da plantilla non o contemplan.
 +
 
 +
Para que ó aplicar unha plantilla sobre un elemento continúe procesando os seus fillos, tenriamos que incluir o elemento <xsl:apply-templates> dentro da plantilla. Este elemento tene un atributo ''select'' que permite restrinxir os fillos sobre os que seguir procesando a plantilla:
 +
 
 +
<syntaxhighlight lang="xslt">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="/Curso"> Encontramos un curso.
 +
        <xsl:apply-templates select=”Tema”/>
 +
    </xsl:template>
 +
    <xsl:template match="Asistente"> Encontramos un asistente. </xsl:template>
 +
    <xsl:template match="Tema"> Encontramos un tema. </xsl:template>
 +
</xsl:stylesheet>
 +
</syntaxhighlight>
 +
 
 +
Neste caso a saída sería:  
 +
<pre>
 +
Encontramos un curso.  
 +
Encontramos un tema.  
 +
Encontramos un tema.  
 +
Encontramos un tema.
 +
</pre>
  
 
= Plantillas predefinidas =
 
= Plantillas predefinidas =
Cuando tenemos algún elemento del documento origen que no se procesa por ninguna plantilla (es decir, un elemento que no encaja con la expresión de una plantilla ni es hijo de los elementos que encajan), entonces el procesador XSLT les aplica las plantillas predefinidas.
+
Cando tenemos algún elemento do documento orixe que non se procesa por ningunha plantilla (isto é, un elemento que non encaixa coa expresión dunha plantilla nin é fillo dos elementos que encaixan), entón o procesador XSLT aplicalles as plantillas predefinidas.
Por ejemplo, si le aplicásemos al documento anterior la siguiente transformación:  
+
 
 +
Por exemplo, se lle aplicásemos ao documento anterior a seguinte transformación:  
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//Tema"> Encontramos un tema. </xsl:template>
+
<?xml version="1.0" encoding="UTF-8"?>
</xsl:stylesheet>
+
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="//Tema"> Encontramos un tema. </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Obtendríamos el siguiente resultado: Simon Templar Ralph Hinkley Maddie Hayes Blanche Devereaux Encontramos un tema. Encontramos un tema. Encontramos un tema.
+
Obteríamos o seguiente resultado:  
Básicamente, el comportamiento de las plantillas predefinidas es procesar estos elementos comentados y sus hijos, mostrando el texto que contienen.
+
<pre>
 +
Pepe Carballeira
 +
Rafael Chousa
 +
Ana Chamadoira
 +
Alba Pereira
 +
Encontramos un tema.  
 +
Encontramos un tema.  
 +
Encontramos un tema.
 +
</pre>
 +
 
 +
Básicamente, o comportamento das plantillas predefinidas é procesar estes elementos comentados e os seus fillos amosando o texto que conteñen.
 +
 
 +
= Aspectos avanzados das plantillas =
 +
 
 +
== Estruturas de control ==
 +
Coma parte das plantillas podemos usar certas estruturas de control no procesamento dos elementos do documento orixinal.
  
= Aspectos avanzados de las plantillas =
+
=== Bucles: <xsl:for-each> ===  
== Variables ==
+
O elemento <xsl:for-each select=”expresión XPath”> selecciona cada un dos nodos do conxunto de nodos resultado da expresión indicada.
Al igual que en los lenguajes de programación, podemos definir variables para después utilizar su contenido en la creación de patrones.
 
Para definir una variable usamos el elemento xls:variable: <xsl:variable name=”nombreVariable”>
 
Su valor puede ser una expresión XPath en el atributo select o bien una plantilla contenida en el propio elemento.
 
  
Las variables se pueden definir en el interior de una plantilla o fuera, como hijo directo del elemento <xsl:stylesheet>. Según sea el caso, tendremos una variable local a una plantilla o global a todo el documento XSLT.
+
=== Condicións simples: <xsl:if> ===
 +
O elemento <xsl:if test=”condición”> permite xenerar un contido únicamente cando a condición sexa certa.
  
Para obtener el valor de una variable se utiliza el elemento <xsl:value-of>. El nombre de la variable estará contenido en el atributo select, precedido por el símbolo $. En dicho atributo, en el lugar del nombre de una variable, también podremos poner una expresión XPath. En el caso de que existan múltiples nodos seleccionados por la expresión, se seleccionará el primero de ellos.
+
=== Condicións múltiples: <xsl:choose>, <xsl:when> e <xsl:otherwise> ===
 +
O elemento <xsl:choose> permite incluir múltiples condicións, cada unha especificada polo elemento <xsl:when test=”condición”> ou <xsl:otherwise>.  
  
El elemento <xsl:value-of> se sustituirá por el valor de la variable o por el valor obtenido por la expresión indicada:  
+
Cando se cumple unha condición prodúcese a saída desexada e abandónase a estrutura:  
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//Curso">
+
<xsl:choose>
<xsl:variable name="numAsistentes" select="count(Asistente)"/> <xsl:element name="Curso"> <xsl:attribute name="asistentes"> <xsl:value-of select="$numAsistentes"/> </xsl:attribute> <xsl:element name="Horas"> <xsl:value-of select="@horas"/> </xsl:element> </xsl:element> </xsl:template> </xsl:stylesheet>
+
    <xsl:when test="condición"> </xsl:when>
 +
    <xsl:when test="condición"> </xsl:when>
 +
    <xsl:otherwise> </xsl:otherwise>
 +
</xsl:choose>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Estructuras de control ==
+
=== Conversións máis avanzadas coas estruturas de control ===
Como parte de las plantillas, podemos usar ciertas estructuras de control en el procesamiento de los elementos del documento original.
+
Estas estruturas de control permiten realizar conversións más avanzadas. Se queremos amosar o seguinte documento XML con notas de alumnos:  
* Bucles <xsl:for-each>: El elemento <xsl:for-each select=”expresión XPath”> selecciona cada uno de los nodos del conjunto de nodos resultado de la expresión indicada.
 
* Condiciones simples <xsl:if>: El elemento <xsl:if test=”condición”> nos permite generar un contenido únicamente cuando la condición sea cierta.
 
* Condiciones múltiples <xsl:choose>: El elemento <xsl:choose> nos permite incluir múltiples condiciones, cada una especificada por el elemento <xsl:when test=”condición”> o <xsl:otherwise>. Cuando se cumple una condición se produce la salida deseada y se abandona la estructura: <xsl:choose> <xsl:when test="condición"> … </xsl:when> <xsl:when test="condición"> … </xsl:when> <xsl:otherwise> … </xsl:otherwise> </xsl:choose>
 
Estas estructuras de control nos permitirían realizar conversiones más avanzadas. Pongamos que queremos mostrar el siguiente documento XML con notas de alumnos:  
 
  
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
 
<?xml version="1.0" encoding="UTF-8"?>
 
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Notas por Cores.xslt"?> <alumnos> <alumno> <nombre>Perico dos Palotes</nombre> <nota>8</nota> </alumno> <alumno> <nombre>Arsenio Lupin</nombre> <nota>9.7</nota> </alumno> <alumno> <nombre>Frodo Bolson</nombre> <nota>4.6</nota> </alumno> <alumno> <nombre>Smeagol</nombre> <nota>6.2</nota> </alumno> <alumno> <nombre>Pulgarcito</nombre> <nota>7.6</nota> </alumno> </alumnos>
+
<?xml-stylesheet type="text/xsl" href="Notas por Cores.xslt"?>
 +
<alumnos>
 +
    <alumno>
 +
        <nombre>Perico dos Palotes</nombre>
 +
        <nota>8</nota>
 +
    </alumno>
 +
    <alumno>
 +
        <nombre>Arsenio Lupin</nombre>
 +
        <nota>9.7</nota>
 +
    </alumno>
 +
    <alumno>
 +
        <nombre>Frodo Bolson</nombre>
 +
        <nota>4.6</nota>
 +
    </alumno>
 +
    <alumno>
 +
        <nombre>Smeagol</nombre>
 +
        <nota>6.2</nota>
 +
    </alumno>
 +
    <alumno>
 +
        <nombre>Pulgarcito</nombre>
 +
        <nota>7.6</nota>
 +
    </alumno>
 +
</alumnos>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
En forma de tabla HTML con colores alternos para el fondo de las filas y con distinto color en función de la nota:  
+
E o queremos en forma de táboa HTML con cores alternas para o fondo das filas e con distinta cor en función da nota:
 +
<syntaxhighlight lang="xslt">
 +
<?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>
 +
                <h1>Notas</h1>
 +
                <table border="1">
 +
                    <tr bgcolor="gray">
 +
                        <th>Alumno</th>
 +
                        <th>Nota</th>
 +
                    </tr>
 +
                    <xsl:for-each select="alumnos/alumno">
 +
                        <xsl:text disable-output-escaping="yes">
 +
                            <tr
 +
                            </xsl:text>
 +
                            <xsl:if test="(position() mod 2) = 1"> bgcolor="yellow" </xsl:if>
 +
                            <xsl:text disable-output-escaping="yes"> ></xsl:text>
 +
                            <td>
 +
                                <xsl:value-of select="nombre"/>
 +
                            </td>
 +
                            <xsl:choose>
 +
                                <xsl:when test="nota < 5">
 +
                                    <td bgcolor="red">
 +
                                        <xsl:value-of select="nota"/>
 +
                                    </td>
 +
                                </xsl:when>
 +
                                <xsl:when test="nota < 7">
 +
                                    <td bgcolor="yellow">
 +
                                        <xsl:value-of select="nota"/>
 +
                                    </td>
 +
                                </xsl:when>
 +
                                <xsl:otherwise>
 +
                                    <td bgcolor="green">
 +
                                        <xsl:value-of select="nota"/>
 +
                                    </td>
 +
                                </xsl:otherwise>
 +
                            </xsl:choose>
 +
                            <xsl:text disable-output-escaping="yes">
 +
                                <tr/>
 +
                            </xsl:text>
 +
                        </xsl:for-each>
 +
                    </table>
 +
                </body>
 +
            </html>
 +
        </xsl:template>
 +
    </xsl:stylesheet>
 +
</syntaxhighlight>
  
 +
Outra opción sería utilizar plantillas:
 +
<syntaxhighlight lang="xslt">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="/alumnos">
 +
        <html>
 +
            <body>
 +
                <h1>Notas</h1>
 +
                <table border="1">
 +
                    <tr bgcolor="gray">
 +
                        <th>Alumno</th>
 +
                        <th>Nota</th>
 +
                    </tr>
 +
                    <xsl:apply-templates select="alumno"/>
 +
                </table>
 +
            </body>
 +
        </html>
 +
    </xsl:template>
 +
    <xsl:template match="alumno">
 +
        <xsl:text disable-output-escaping="yes"> &lt;tr </xsl:text>
 +
        <xsl:if test="(position() mod 2) = 1"> bgcolor="yellow" </xsl:if>
 +
        <xsl:text disable-output-escaping="yes"> &gt; </xsl:text>
 +
        <td>
 +
            <xsl:value-of select="nombre"/>
 +
        </td>
 +
        <xsl:choose>
 +
            <xsl:when test="nota < 5">
 +
                <td bgcolor="red">
 +
                    <xsl:value-of select="nota"/>
 +
                </td>
 +
            </xsl:when>
 +
            <xsl:when test="nota < 7">
 +
                <td bgcolor="yellow">
 +
                    <xsl:value-of select="nota"/>
 +
                </td>
 +
            </xsl:when>
 +
            <xsl:otherwise>
 +
                <td bgcolor="green">
 +
                    <xsl:value-of select="nota"/>
 +
                </td>
 +
            </xsl:otherwise>
 +
        </xsl:choose>
 +
        <xsl:text disable-output-escaping="yes"> &lt;/tr&gt; </xsl:text>
 +
    </xsl:template>
 +
</xsl:stylesheet>
 +
</syntaxhighlight>
 +
 +
== Ordenar os resultados: <xsl:sort > ==
 +
Para ordenar os resultados teremos que empregar o elemento <xsl:sort select=”elementoXML”/> dentro do <xsl:for-each> ou <xsl:apply-templates> que corresponda.
 +
 +
Este elemento pode ter tres atributos:
 +
* select: indica cal será o elemento polo que se ordearán os resultados.
 +
* order: pode ser ''ascending'' ou ''descending''
 +
* data-type: pode ser ''number'' ou ''text''
  
 +
No exemplo anterior, para ordear a táboa pola nota do alumno:
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?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> <h1>Notas</h1> <table border="1"> <tr bgcolor="gray"> <th>Alumno</th> <th>Nota</th> </tr> <xsl:for-each select="alumnos/alumno"> <xsl:text disable-output-escaping="yes"> <tr </xsl:text> <xsl:if test="(position() mod 2) = 1"> bgcolor="yellow" </xsl:if> <xsl:text disable-output-escaping="yes"> > </xsl:text>
+
...  
<td><xsl:value-of select="nombre"/></td> <xsl:choose> <xsl:when test="nota < 5"> <td bgcolor="red"><xsl:value-of select="nota"/></td> </xsl:when> <xsl:when test="nota < 7"> <td bgcolor="yellow"><xsl:value-of select="nota"/></td> </xsl:when> <xsl:otherwise> <td bgcolor="green"><xsl:value-of select="nota"/></td> </xsl:otherwise> </xsl:choose> <xsl:text disable-output-escaping="yes"> <tr/> </xsl:text> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
+
<xsl:for-each select="alumnos/alumno">  
 +
<xsl:sort select="nota" data-type="number" order="descending"/>  
 +
...
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Otra opción sería utilizar plantillas:
+
== Variables: <xsl:variable> ==
 +
Do mesmo xeito que nas linguaxes de programación podemos definir variables para despois utilizar o seu contido.
  
 +
Para definir una variable empregamos o elemento:
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/alumnos"> <html> <body> <h1>Notas</h1> <table border="1"> <tr bgcolor="gray"> <th>Alumno</th> <th>Nota</th> </tr> <xsl:apply-templates select="alumno"/> </table> </body> </html> </xsl:template> <xsl:template match="alumno">
+
<xsl:variable name=”nomeVariable”>
<xsl:text disable-output-escaping="yes"> &lt;tr </xsl:text> <xsl:if test="(position() mod 2) = 1"> bgcolor="yellow" </xsl:if> <xsl:text disable-output-escaping="yes"> &gt; </xsl:text> <td> <xsl:value-of select="nombre"/> </td> <xsl:choose> <xsl:when test="nota < 5"> <td bgcolor="red"><xsl:value-of select="nota"/></td> </xsl:when> <xsl:when test="nota < 7"> <td bgcolor="yellow"><xsl:value-of select="nota"/></td> </xsl:when> <xsl:otherwise> <td bgcolor="green"><xsl:value-of select="nota"/></td> </xsl:otherwise> </xsl:choose> <xsl:text disable-output-escaping="yes"> &lt;/tr&gt; </xsl:text> </xsl:template> </xsl:stylesheet>
 
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
O seu valor pode ser unha expresión XPath no atributo ''select'' ou ben unha plantilla contida no propio elemento.
  
== Ordenar os resultados - <xsl:sort > ==
+
As variables podense definir no interior dunha plantilla ou fora, coma fillo directo do elemento <xsl:stylesheet>. Segundo sea o caso, teremos unha variable local a unha plantilla ou global a todo o documento XSLT.
Para ordenar los resultados tendremos que emplear el elemento <xsl:sort select=”elementoXML”/> dentro del <xsl:for-each> o <xsl:apply-templates> que corresponda.
 
Este elemento puede tener 3 atributos:
 
* select: indica cual será el elemento por el que se ordenarán los resultados.
 
* order: puede ser ascending o descending
 
* data-type: puede ser number o text.
 
  
En el ejemplo anterior, para ordenar la tabla por la nota del alumno: ... <xsl:for-each select="alumnos/alumno"> <xsl:sort select="nota" data-type="number" order="descending"/> ...
+
Para obter o valor dunha variable utilízase o elemento <xsl:value-of>. O nome da variable estará contido no atributo ''select'' precedido polo símbolo $. Nese atributo, en lugar do nome dunha variable tamén podremos poñer unha expresión XPath. No caso de que existan múltiples nodos seleccionados pola expresión, seleccionarase o primeiro deles.
  
== Copiar elementos del documento origen ==
+
O elemento <xsl:value-of> substituirase polo valor da variable ou polo valor obtido pola expresión indicada:
XSLT permite copiar en el documento resultante un nodo o un conjunto de nodos del documento origen. Esta copia la podemos hacer de dos maneras:
+
 
* <xsl:copy>: realiza una copia sencilla del elemento al que se refiere la plantilla. No copia sus atributos, su texto o sus hijos, solamente el elemento. Si quisiéramos procesar también su contenido, habría que hacerlo de forma específica.
+
<syntaxhighlight lang="xslt">
* <xsl:copy-of>: hace una copia profunda y traslada al documento resultante el texto, los hijos y los atributos del original. A diferencia de <xsl:copy>, necesita del atributo select para seleccionar los nodos que debe copiar.
+
<?xml version="1.0" encoding="UTF-8"?><
Por ejemplo, el documento siguiente: <?xml version="1.0" encoding="UTF-8"?> <Curso horas="30"> <Asistente>Simon Templar</Asistente> <Asistente>Ralph Hinkley</Asistente> <Asistente>Maddie Hayes</Asistente> <Asistente>Blanche Devereaux</Asistente> </Curso>
+
<xsl:stylesheet version="1.0"
Lo podríamos copiar de las siguientes maneras:
+
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="//Curso">
 +
        <xsl:variable name="numAsistentes" select="count(Asistente)"/>
 +
        <xsl:element name="Curso">
 +
            <xsl:attribute name="asistentes">
 +
                <xsl:value-of select="$numAsistentes"/>
 +
            </xsl:attribute>
 +
            <xsl:element name="Horas">
 +
                <xsl:value-of select="@horas"/>
 +
            </xsl:element>
 +
        </xsl:element>
 +
    </xsl:template>
 +
</xsl:stylesheet>
 +
</syntaxhighlight>
 +
 
 +
== Parámetros: <xsl:param> e <xsl:with-param> ==
 +
 
 +
xsl:with-param permite definir un parámetro que se lle pasará a una plantilla.
 +
 
 +
Atributos:
 +
* name:nombe do parámetro
 +
* select:ExpresiónXPath(opcional)
 +
 
 +
xsl:param Se é declarado coma elemento de alto nivel será un parámetro global e Se se declara dentro dunha plantilla é local e ten que ir asociado a un elemento xsl:with-param.
 +
 
 +
Atributos:
 +
* name:nome do parámetro
 +
* select:ExpresiónXPath(opcional)
 +
 
 +
Exemplo:
 +
 
 +
<syntaxhighlight lang="xslt">
 +
<xsl:templatematch="/">
 +
<html>
 +
<body>
 +
  <xsl:for-eachselect=“//persona">
 +
  <xsl:call-templatename=“mostrar_dni">
 +
  <xsl:with-paramname=“dni" select= “@dni" />
 +
  </xsl:call-template>
 +
  </xsl:for-each>
 +
</body>
 +
</html>
 +
</xsl:template>
 +
<xsl:templatename= “mostrar_dni" >
 +
<xsl:paramname= “dni" />
 +
  <p>DNI: <xsl:value-ofselect= "$dni" /></p>
 +
</xsl:template>
 +
</xsl:stylesheet>
 +
</syntaxhighlight>
 +
 
 +
== Copiar elementos do documento orixe: <xsl:copy> e <xsl:copy-of> ==
 +
XSLT permite copiar no documento resultante un nodo ou un conxunto de nodos do documento orixe. Esta copia pódese facer de dous xeitos:
 +
* <xsl:copy>: realiza unha copia sinxela do elemento ó que se refire a plantilla. Non copia os seus atributos, o seu texto ou os seus fillos e so ó elemento. Se quixeramos procesar tamén o seu contenido habería que facelo de xeito específico.
 +
* <xsl:copy-of>: fai unha copia profunda e traslada ó documento resultante o texto, os fillos e os atributos do orixinal. A diferencia de <xsl:copy>, necesita do atributo select para seleccionar os nodos que debe copiar.
 +
 
 +
Por ejemplo, o documento seguinte:  
 +
<syntaxhighlight lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<Curso horas="40">
 +
    <Asistente>Simon Templar</Asistente>
 +
    <Asistente>Ralph Hinkley</Asistente>
 +
    <Asistente>Maddie Hayes</Asistente>
 +
    <Asistente>Blanche Devereaux</Asistente>
 +
</Curso>
 +
</syntaxhighlight>
 +
 
 +
Poderíamolo copiar dos seguintes xeitos:
  
XSLT
 
 
xls:copy
 
xls:copy
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/Curso"> <Asistentes> <xsl:apply-templates/> </Asistentes> </xsl:template> <xsl:template match="Asistente"> <xsl:copy/> </xsl:template> </xsl:stylesheet>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="/Curso">
 +
        <Asistentes>
 +
            <xsl:apply-templates/>
 +
        </Asistentes>
 +
    </xsl:template>
 +
    <xsl:template match="Asistente">
 +
        <xsl:copy/>
 +
    </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
Resultado:
 
Resultado:
 
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
<Asistentes> <Asistente /> <Asistente /> <Asistente /> <Asistente /> </Asistentes>
+
<Asistentes>
 +
    <Asistente />
 +
    <Asistente />
 +
    <Asistente />
 +
    <Asistente />
 +
</Asistentes>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
xls:copy-of
 
xls:copy-of
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?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:copy-of select="Curso"/> </xsl:template> </xsl:stylesheet>
+
<?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:copy-of select="Curso"/>
 +
    </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
<Curso> <Asistente>Simon Templar</Asistente> <Asistente>Ralph Hinkley</Asistente> <Asistente>Maddie Hayes</Asistente> <Asistente>Blanche Devereaux</Asistente> </Curso>
+
<Curso>
 +
    <Asistente>Simon Templar</Asistente>
 +
    <Asistente>Ralph Hinkley</Asistente>
 +
    <Asistente>Maddie Hayes</Asistente>
 +
    <Asistente>Blanche Devereaux</Asistente>
 +
</Curso>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
También se podrían hacer copias idénticas del documento origen con xls:copy, seleccionando todos los elementos y atributos de la siguiente forma:
+
Tamén se poderían facer copias idénticas do documento orixe con xls:copy, seleccionando todos os elementos e atributos así:
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:template match="@* | node()">
 +
        <xsl:copy>
 +
            <xsl:apply-templates select="@* | node()"/>
 +
        </xsl:copy>
 +
    </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
== Aplicar varias plantillas ao mesmo nodo: <xsl:template> e <xsl:applytemplates> con atributo ''mode'' ==
 +
Por defecto, un procesador XSLT selecciona a plantilla que se vai aplicar a cada un dos nodos que forman o documento XML que se procesa. Se o que desexamos é transformar un ou varios nodos de dúas ou máis formas diferentes, necesitamos que o procesador aplique máis dunha plantilla sobre o mesmo nodo: empregaremos o atributo ''mode''.
  
== Aplicar varias plantillas al mismo nodo ==
+
Este atributo permite definir máis dunha plantilla para o mesmo nodo. Aplicase aos elementos <xsl:template> e <xsl:applytemplates>. Se varias plantillas se aplican ao mesmo nodo, os valores dos seus atributos ''mode'' deben ser distintos.
Por defecto, un procesador XSLT selecciona la plantilla que se va a aplicar a cada uno de los nodos que forman el documento XML que se procesa. Si lo que queremos es transformar uno o varios nodos de dos o más formas diferentes, necesitamos que el procesador aplique más de una plantilla sobre el mismo nodo.
 
  
Para conseguir esto, empleamos el atributo mode. Este atributo permite definir más de una plantilla para el mismo nodo. Se aplica a los elementos <xsl:template> y <xsl:applytemplates>. Si varias plantillas se aplican al mismo nodo, los valores de sus atributos mode deben ser distintos.
+
Por exemplo, para ordenar a lista de asistentes de forma ascendente primeiro e descendente despois podémolo facer así:
 
 
Por ejemplo, para ordenar la lista de asistentes de forma ascendente primero, y descendiente después, lo podemos hacer de la siguiente manera:
 
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?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:element name="Asistentes"> <xsl:element name="Asistentes_Asc"> <xsl:apply-templates mode="asc"/> </xsl:element> <xsl:element name="Asistentes_Desc"> <xsl:apply-templates mode="desc"/> </xsl:element> </xsl:element> </xsl:template> <xsl:template match="Curso" mode="asc"> <xsl:for-each select="Asistente"> <xsl:sort select="."/> <xsl:copy-of select="."/> </xsl:for-each> </xsl:template> <xsl:template match="Curso" mode="desc"> <xsl:for-each select="Asistente"> <xsl:sort select="." order="descending"/> <xsl:copy-of select="."/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
+
<?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:element name="Asistentes">
 +
            <xsl:element name="Asistentes_Asc">
 +
                <xsl:apply-templates mode="asc"/>
 +
            </xsl:element>
 +
            <xsl:element name="Asistentes_Desc">
 +
                <xsl:apply-templates mode="desc"/>
 +
            </xsl:element>
 +
        </xsl:element>
 +
    </xsl:template>
 +
    <xsl:template match="Curso" mode="asc">
 +
        <xsl:for-each select="Asistente">
 +
            <xsl:sort select="."/>
 +
            <xsl:copy-of select="."/>
 +
        </xsl:for-each>
 +
    </xsl:template>
 +
    <xsl:template match="Curso" mode="desc">
 +
        <xsl:for-each select="Asistente">
 +
            <xsl:sort select="." order="descending"/>
 +
            <xsl:copy-of select="."/>
 +
        </xsl:for-each>
 +
    </xsl:template>
 +
</xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Lo que produciría la siguiente salida:
+
Produciría a seguinte saída:
  
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
<Asistentes> <Asistentes_Asc> <Asistente>Blanche Devereaux</Asistente> <Asistente>Maddie Hayes</Asistente> <Asistente>Ralph Hinkley</Asistente> <Asistente>Simon Templar</Asistente> </Asistentes_Asc> <Asistentes_Desc> <Asistente>Simon Templar</Asistente> <Asistente>Ralph Hinkley</Asistente> <Asistente>Maddie Hayes</Asistente> <Asistente>Blanche Devereaux</Asistente> </Asistentes_Desc> </Asistentes>
+
<Asistentes>
 +
    <Asistentes_Asc>
 +
        <Asistente>Blanche Devereaux</Asistente>
 +
        <Asistente>Maddie Hayes</Asistente>
 +
        <Asistente>Ralph Hinkley</Asistente>
 +
        <Asistente>Simon Templar</Asistente>
 +
    </Asistentes_Asc>
 +
    <Asistentes_Desc>
 +
        <Asistente>Simon Templar</Asistente>
 +
        <Asistente>Ralph Hinkley</Asistente>
 +
        <Asistente>Maddie Hayes</Asistente>
 +
        <Asistente>Blanche Devereaux</Asistente>
 +
    </Asistentes_Desc>
 +
</Asistentes>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Claves e identificadores ==
+
== Claves e identificadores: <xsl:key> ==
Al procesar un documento XML podemos crear claves para identificar elementos del documento original. Los procesadores XSLT suelen crear índices internos para las claves, lo que mejora el acceso a su contenido.
+
 
Para crear una clave se utiliza el elemento <xsl:key>. Este elemento debe ser hijo directo de <xsl:stylesheet>. No se puede utilizar en ningún otro sitio, como por ejemplo formando parte de una plantilla.
+
Podemos crear claves para identificar elementos do documento original. Os procesadores XSLT adoitan crear índices internos para as claves mellorando o acceso ao seu contido.
Tiene tres atributos requeridos:
+
 
* name: asigna un nombre a la clave para poder utilizarla posteriormente
+
Para crear una clave utilízase o elemento <xsl:key>. Este elemento debe ser fillo directo de <xsl:stylesheet>. Nno se pode utilizar en ningún outro sitio, coma por exemplo formando parte dunha plantilla.
* match: indica los nodos que serán indexados por la clave
 
* use: define la propiedad de los nodos que se empleará para crear el índice. Esta propiedad es la que usaremos para acceder a los nodos del índice.
 
  
Por ejemplo, si quisiéramos definir una clave para los alumnos sobre su nombre:
+
Ten tres atributos requeridos:
 +
* name: asigna un nome á clave para poder utilizala posteriormente
 +
* match: indica os nodos que serán indexados pola clave
 +
* use: define a propiedade dos nodos que se empregará para crear o índice. Esta propiedade é a que usaremos para acceder aos nodos do índice.
 +
 
 +
Por exemplo, para definir unha clave para os alumnos sobre o seu nome:
  
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="UTF-8"?> <alumnos> <alumno> <nombre>Perico dos Palotes</nombre> <nota>8</nota> </alumno> <alumno> <nombre>Arsenio Lupin</nombre> <nota>7</nota> </alumno> <alumno> <nombre>Frodo Bolson</nombre> <nota>7</nota> </alumno> <alumno> <nombre>Smeagol</nombre> <nota>4</nota> </alumno> <alumno> <nombre>Pulgarcito</nombre> <nota>8</nota> </alumno> </alumnos>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<alumnos>
 +
    <alumno>
 +
        <nombre>Perico dos Palotes</nombre>
 +
        <nota>8</nota>
 +
    </alumno>
 +
    <alumno>
 +
        <nombre>Arsenio Lupin</nombre>
 +
        <nota>7</nota>
 +
    </alumno>
 +
    <alumno>
 +
        <nombre>Frodo Bolson</nombre>
 +
        <nota>7</nota>
 +
    </alumno>
 +
    <alumno>
 +
        <nombre>Smeagol</nombre>
 +
        <nota>4</nota>
 +
    </alumno>
 +
    <alumno>
 +
        <nombre>Pulgarcito</nombre>
 +
        <nota>8</nota>
 +
    </alumno>
 +
</alumnos>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
Faríamos o seguinte:
 
Faríamos o seguinte:
 
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="clave_alumno" match="alumno" use="nombre"/> </xls:stylesheet>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsl:stylesheet version="1.0"
 +
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:key name="clave_alumno" match="alumno" use="nombre"/>
 +
</xls:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Una vez creada la clave, utilizando la función key() obtendremos los nodos de la clave indicando la propiedad definida en el atributo “use”.
+
Unha vez creada a clave, utilizando a función key() obteremos os nodos da clave indicando a propiedade definida no atributo ''use''.
En nuestro ejemplo, si posteriormente quisiéramos obtener a partir del nombre de un alumno la nota correspondiente, haríamos:
 
  
 +
No noso exemplo se posteriormente quixeramos obter a partir do nome dun alumno a nota correspondeente faríamos:
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
 
<xsl:template match="/">
 
<xsl:template match="/">
<xsl:value-of select="key('clave_alumno', 'Pulgarcito')/nota" /> </xsl:template>
+
    <xsl:value-of select="key('clave_alumno', 'Pulgarcito')/nota" />
 +
</xsl:template>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
== Identificadores de nodos ==
 
== Identificadores de nodos ==
Existe una función específica de XSLT: generate-id, que recibe como parámetro un nodo, y devuelve un valor único generado aleatoriamente. Este valor será único en todo el documento, y además será siempre el mismo para ese nodo y esa ejecución, es decir, si más adelante empleamos de nuevo la función generate-id con el mismo nodo, obtendremos el mismo valor.
+
A función específica de XSLT generate-id recibe como parámetro un nodo e devolve un valor único xenerado aleatoriamente. Este valor será único en todo o documento, e ademáis será sempre o mesmo para ese nodo e esa execución: se máis adiante empregamos de novo a función generate-id co mesmo nodo obteremos o mesmo valor.
  
Se usa, por ejemplo, para generar identificadores y enlaces internos a ellos mismos en un documento HTML.
+
Úsase por exemplo para xenerar identificadores e enlaces internos a eles mesmos nun documento HTML:
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<a name="{generate-id(.)}"> <xsl:value-of select="nombre" /> </a> … <!-- y generamos el enlace --> <a href="#{generate-id(.)}"> Para ir al elemento, pinche aquí </a>
+
<a name="{generate-id(.)}">
 +
    <xsl:value-of select="nombre" />
 +
</a>  
 +
…  
 +
<!-- y xeneramos o enlace -->
 +
<a href="#{generate-id(.)}"> Para ir al elemento, pinche aquí </a>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Agrupamiento de nodos ==
+
== Agrupamento de nodos ==
Gracias a las claves y a la generación de identificadores, podemos realizar una aplicación interesante que es el agrupamiento de nodos. Se hace en dos pasos: un bucle for-each selecciona el primer nodo de cada grupo y otro bucle dentro del primero crea los elementos del grupo.
+
Gracias as claves e á xeneración de identificadores, podemos realizar o agrupamento de nodos.  
En nuestro caso podemos hacer un grupo por cada valor de la nota, y mostrar dentro de cada uno, a los alumnos que obtuvieron dicha nota.
+
 
 +
Faise en dous pasos:
 +
* un bucle for-each selecciona o primeiro nodo de cada grupo  
 +
* outro bucle dentro do primeiro crea os elementos do grupo
 +
 
 +
Podemos facer un grupo por cada valor da nota, e amosar dentro de cada un aos alumnos que obtuvieron esa nota.
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="clave_alumno" match="alumno" use="nota"/> <xsl:template match="/"> <xsl:element name="Notas"> <xsl:for-each select="/alumnos/alumno[generate-id(.)=generate-id(key('clave_alumno',nota))]"> <xsl:sort select="nota" order="descending" /> <xsl:element name="Nota"> <xsl:attribute name="valor"> <xsl:value-of select="nota" /> </xsl:attribute>
+
<?xml version="1.0" encoding="UTF-8"?>
<xsl:for-each select="key('clave_alumno',nota)"> <xsl:element name="Alumno"> <xsl:value-of select="nombre" /> </xsl:element> </xsl:for-each> </xsl:element> </xsl:template> </xsl:stylesheet>
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 +
    <xsl:key name="clave_alumno" match="alumno" use="nota"/>
 +
    <xsl:template match="/">
 +
        <xsl:element name="Notas">
 +
            <xsl:for-each select="/alumnos/alumno[generate-id(.)=generate-id(key('clave_alumno',nota))]">
 +
                <xsl:sort select="nota" order="descending" />
 +
                <xsl:element name="Nota">
 +
                    <xsl:attribute name="valor">
 +
                        <xsl:value-of select="nota" />
 +
                    </xsl:attribute>
 +
                    <xsl:for-each select="key('clave_alumno',nota)">
 +
                        <xsl:element name="Alumno">
 +
                            <xsl:value-of select="nombre" />
 +
                        </xsl:element>
 +
                    </xsl:for-each>
 +
                </xsl:element>
 +
            </xsl:template>
 +
        </xsl:stylesheet>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
El primer bucle recorre los alumnos y, con la condición indicada en la expresión XPath, se queda solamente con uno por cada valor diferente de la nota.
+
O primeiro bucle recorre os alumnos e coa condición indicada na expresión XPath quédase soamente con uno por cada valor diferente da nota.
La función key('clave_alumno',nota) busca la nota del nodo que procesa el bucle (nota) en la clave creada sobre la nota, y devuelve el nodo correspondiente al primer alumno de todos los que comparten esa nota.
+
 
Después empleando generate-id comprobamos si el nodo que está procesando el bucle (.) es el mismo que devuelve la función key. Si no es el caso, no se cumple la condición (no es el primer nodo con esa misma nota) y no se procesan los elementos del bucle.
+
A función key('clave_alumno',nota) busca a nota do nodo que procesa o bucle (nota) na clave creada sobre a nota e devolve o nodo correspondente ó primeiro alumno de todos os que comparten esa nota.
El segundo bucle utiliza la clave para procesar todos los nodos con una misma nota.
+
 
El resultado será el siguiente:
+
Despois empregando generate-id comprobamos se o nodo que está procesando o bucle (.) é o mesmo que devolve a función key. Se non e así, non se cumple a condición (non é o primeiro nodo con esa mesma nota) e non se procesan os elementos do bucle.
  
 +
O segundo bucle utiliza a clave para procesar todos os nodos cunha mesma nota.
 +
 +
O resultado será:
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="UTF-8"?> <Notas> <Nota valor="8"> <Alumno>Perico dos Palotes</Alumno> <Alumno>Pulgarcito</Alumno> </Nota> <Nota valor="7"> <Alumno>Arsenio Lupin</Alumno> <Alumno>Frodo Bolson</Alumno> </Nota> <Nota valor="4"> <Alumno>Smeagol</Alumno> </Nota> </Notas>
+
<?xml version="1.0" encoding="UTF-8"?>
 +
<Notas>
 +
    <Nota valor="8">
 +
        <Alumno>Perico dos Palotes</Alumno>
 +
        <Alumno>Pulgarcito</Alumno>
 +
    </Nota>
 +
    <Nota valor="7">
 +
        <Alumno>Arsenio Lupin</Alumno>
 +
        <Alumno>Frodo Bolson</Alumno>
 +
    </Nota>
 +
    <Nota valor="4">
 +
        <Alumno>Smeagol</Alumno>
 +
    </Nota>
 +
</Notas>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
= Formato do resultado =
+
= Formato do resultado: <xsl:output> =
Con la etiqueta <xsl:output > podemos definir distintas características sobre el formato del documento de salida (todas son opcionales):
+
 
 +
Coa etiqueta <xsl:output ...> podemos definir distintas características sobre o formato do documento de saída (son todas opcionais):
  
 
<syntaxhighlight lang="xslt">
 
<syntaxhighlight lang="xslt">
Línea 326: Línea 832:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Es importante el atributo method. Si no se incluye, el formato de salida por defecto es XML (a no ser que el elemento raíz del documento sea html: en este caso el formato de salida será HTML si no se indica ningún otro).
+
O atributo ''method'' e importante; se non se inclúe, o formato de saída por defecto é XML (a no ser que o elemento raíz do documento sexa html, no que a saída será HTML se non se indica outro formato).
Aunque depende del procesador XSLT que utilicemos, en la mayoría de las ocasiones si el documento resultante es XML se incluirá en el mismo, de forma automática, una declaración <?xml ?>.
+
 
 +
Aínda que depende do procesador XSLT que utilicemos, na maioría das ocasións se o documento resultante é XML incluirase no mesmo de forma automática unha declaración <?xml ... ?>.
 +
 
 +
= Resumo =
 +
* Os ficheiros XML permiten organizar a información de forma xerárquica
 +
:* Son lexibles mais hai que procesar a información para darlle un valor engadido e facilitar a comprensión
 +
* XSLT e un estándar para transformar documentos XML a outros documentos coma HTML ou XML
 +
* A etiqueta do ficheiro XML que fai referencia a folla de estilo XSL:
 +
<syntaxhighlight lang="xslt">
 +
<?xml-stylesheet type="text/xsl" href="ficheiro.xsl"?>
 +
</syntaxhighlight>
 +
* E a orden template:
 +
<syntaxhighlight lang="xslt">
 +
<?xsl:template match="/">
 +
</syntaxhighlight>
 +
:* Distínguese a orde e o atributo ''match'' que asocia en XPath a plantilla a un nodo XML
 +
* As etiquetas máis usadas:
 +
:* <xsl:value-of>. Extrae o valor dun documento XML e o engade o fluxo de saída da transformación.
 +
:* <xsl:for-each>. Selecciona todos os elementos un a un dunha lista determinada.
 +
:* <xsl:sort>. Ordena alfabéticamente un grupo de nodos.
 +
:* <xsl:if>. Estrutura condicional. Executase o seu contido cando se cumpra a condición do IF
 +
:* <xsl:choose>. Estrutura condicional. Permite optar entre varias condicións.
 +
 
 +
= Exercicios =
 +
* [[Exercicios con XSLT]]
 +
 
 +
= Referencias =
 +
<div style="column-count:2;-moz-column-count:2;-webkit-column-count:2">
 +
* [https://www.mclibre.org/consultar/xml/ Curso XML: Lenguaje de marcas extensible], [https://www.mclibre.org/consultar/xml/lecciones/xml-xslt.html sección XSLT] por [https://www.mclibre.org/ Bartolomé Sintes Marco] baixo Licencia CC BY-SA 4.0
 +
* [https://www.xml.com/articles/2017/01/01/what-is-xslt/ What is XSLT]
 +
* [https://www.xml.com/articles/2017/02/14/why-you-should-be-using-xslt-30/ Why you should be using XSLT 3.0]
 +
* [http://www.ling.helsinki.fi/kit/2002s/ctl230/XSLT-HTML/Hands-onXSL.html XSL for fun and diversion]
 +
* [https://www.ticarte.com/contenido/que-es-el-lenguaje-de-transformacion-xslt Exemplos - ticarte]
 +
* [https://docplayer.es/14914842-Transformacion-de-documentos-xml-con.html XSLT]. JL Comesaña. Universida de Sevilla
 +
* [https://developer.mozilla.org/en-US/docs/Web/API/XSLTProcessor XSLT processor and examples]
 +
* [https://xsltdev.com/ XSLT 3.1 Elements reference (examples)]
 +
</div>

Revisión actual del 11:06 9 may 2023


Xsl icon.png

XSLT

Fluxo de XSLT

XSL (eXtensible Stylesheet Language, linguaxe de follas de estilo extensible) é un estándar que engloba un conxunto de tres estándares que teñen o obxectivo común de transformar e aplicar estilos aos documentos XML:

XPath
empregado para construir expresións que busquen e accedan a partes concretas do documento XML.
XSLT (XSL Transformations)
é unha linguaxe que nos permite crear unha serie de reglas e patróns que tranformarán o contido do documento orixinal noutro documento XML (ou con outro formato: XHTML, texto, LaTeX, etc.). Un uso típico é para pasar un documento XML a unha web XHTML.
XSL-FO (XSL Formatting Objects)
linguaxe que nos permite formatear os datos contidos no documento XML. Traballa con áreas, bloques, rexións, anchuras e alturas das páginas, dos márxenes, etc. Moi utilizado para xenerar ficheiros PDF a partir de documentos XML.

XSLT permítenos transformar un documento XML engadindo ou eliminando etiquetas ou atributos no documento final, reorganizando os seus elementos, ordenalos segundo algún criterio, etc. Así poderemos crear distintos documentos a partir dun mesmo XML orixe, ou ter distintas vistas da mesma información (dun mesmo documento con información dos meus clientes poido obtener un listado dos morosos, as etiquetas para as cartas que se lles envía ou información sobre a súa facturación, e todo como resultado de aplicar distintos XSLTs ó mesmo documento).

XSLT é unha linguaxe declarativa: as follas de estilo XSLT non se escriben como unha secuencia de instruccións, se non coma unha colección de plantillas (template rules). Cada plantilla establece cómo se transforma un determinado elemento (definido mediante expresións XPath). O seu funcionamento básico consiste en aplicar transformacións a aquelas partes do documento seleccionadas a través dunha expresión XPath que encaixan con alguhna plantilla:

  • O procesador analiza o documento e constrúe a árbore do documento.
  • O procesador recorre a árbore do documento desde o nodo raíz.
  • En cada nodo recorrido o procesador aplica ou non algunha plantilla:
  • Se a un nodo non se lle pode aplicar ningunha plantilla, aplícaselle un patrón predefinido, que copia o seu contenido no documento final (o texto do nodo, non o dos nodos descendentes). A continuación, o procesador recorre os seus nodos hijos.
  • Se a un nodo se lle pode aplicar unha plantilla, se lle aplica. A plantilla pode generar texto que se inclúe no documento final. En principio, o procesador non recorre os seus nodos fillos, salvo que a plantilla indique ó procesador que sí que deben recorrerse os nodos fillos.
  • Cando o procesador recorreu a árbore, a transformación rematou

Versións

É un estándar do W3C con tres versións:

Podes ver un resumo das melloras entre versións na Wikipedia, e exemplos das novas posibiidades da versión 3.0.

Estrutura dun documento

Unha folla de estilo XSLT é un documento XML que ten a seguinte estrutura:

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

No lugar de xsl:stylesheet pódese utilizar a etiqueta xls:transform. Esta instrucción é a etiqueta raíz da folla de estilo e os seus atributos indican a versión e o espazo de nomes correspondente (un documento XSLT sempre ten que utilizar un espazo de nomes).

Para enlazar o documento XML á folla de estilo engadiremos antes do elemento raíz do documento XML a seguinte instrucción de procesamento:

<?xml-stylesheet type="text/xsl" href="archivo.xsl"?>

Dentro da instrucción <xsl:stylesheet> podense atopar os denominados elementos de alto nivel e as plantillas:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/"></xsl:template>
</xsl:stylesheet>

Onde:

  • o elemento de alto nivel <xsl:output> indica o tipo de saída producida.
  • a instrucción <xsl:template> é unha plantilla.
  • O atributo match indica os elementos afectados pola plantilla e contén una expresión XPath.
  • O contido da instrucción define a transformación a aplicar (se a instrucción non contén nada coma no exemplo anterior, sustituirá o nodo por nada, o que quere dicir que eliminará o nodo, aínda que conservará o texto contido no elemento).

Cando se aplica unha plantilla a un nodo, en principio non se recorren os nodos descendentes. Para indicar que sí queremos recorrer os nodos descendentes e aplicarlles as plantillas que lles correspondan hao que utilizar a instrucción <xsl:apply-templates />, coma no seguinte exemplo:

PENDIENTE

Plantillas

Para construir plantillas usamos o elemento xsl:template:

<xsl:template match=”expresión XPath”> </xsl:template>

Estas plantillas conteñen reglas que se aplican aos nodos que encaixan co seu atributo match. O resultado do procesamiento das reglas conformará o documento resultante da transformación.

Por exemplo, ó seguinte documento XML:

<?xml version="1.0" encoding="UTF-8"?>
<Curso horas=”40”>
    <Asistente>Pepe Carballeira</Asistente>
    <Asistente>Rafael Chousa</Asistente>
    <Asistente>Ana Chamadoira</Asistente>
    <Asistente>Alba Pereira</Asistente>
</Curso>

Se lle poden aplicar calquiera das seguintes transformacións:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="//Curso"></xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="//Asistente"></xsl:template>
</xsl:stylesheet>

Cuando aplicamos a primeira plantilla o único elemento do documento orixe que cumple a expresión XPath é o elemento raíz (Curso).

Aplicando a segunda plantilla, hai catro elementos que cumplirán a expresión, e as reglas que forman a plantilla procesaríanse unha vez por cada un deles.

As plantillas poden ter un atributo name en lugar do atributo match . Neste caso o que facemos é definir, non aplicar as reglas que compoñen a plantilla. Estas reglas aplicaríanse cando se chame á plantilla empregando a seguinte estrutura:

<xsl:call-template name=”nombreDeLaPlantilla”/>

Aínda que non é moi utilizado é posible crear plantillas que teñan ambos atributos: match e name.

Contido

Texto: <xsl:text>

Útilizase para incluir texto no documento resultante. Tamén se pode escribir ó texto directamente na plantilla, pero utilizando este elemento pódense controlar os espazos e saltos de liña xenerados.

As seguintes plantillas son similares:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="//Asistente">
        <xsl:text>Encontrado un asistente!</xsl:text>
    </xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="//Asistente"> Encontrado un asistente! </xsl:template>
</xsl:stylesheet>

Elementos: <xsl:element>

Crea un novo elemento no documento resultante. O atributo name indica o nome do nuevo elemento. Este atributo pódese compoñer coma:

  • combinación de texto
  • partes do documento orixinal
  • variables
  • valores devoltos por funcións
  • etc.

Atributos: <xsl:attribute>

Crea un novo atributo no elemento do documento resultante. O valor do atributo name será o nome do novo atributo.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="//Curso">
        <xsl:element name="Curso">
            <xsl:attribute name="asistentes">
                <xsl:value-of select="count(Asistente)"/>
            </xsl:attribute>
            <xsl:element name="Horas">
                <xsl:value-of select="@horas"/>
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Daría como resultado:

<Curso asistentes="4">
    <Horas>30</Horas>
</Curso>

Tamén é posible definir un conxunto de atributos para logo utilizalos en un ou varios elementos. Esto realiza con <xsl:attribute-set>:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:attribute-set name="datos">
        <xsl:attribute name="nombre">
            <xsl:value-of select="."/>
        </xsl:attribute>
        <xsl:attribute name="horas">
            <xsl:value-of select="/Curso/@horas"/>
        </xsl:attribute>
    </xsl:attribute-set>
    <xsl:template match="//Asistente">
        <xsl:element name="Asistente" use-attribute-sets="datos"/>
    </xsl:template>
</xsl:stylesheet>

O elemento <xsl:value-of> permite obter o valor devolto por funcións ou o valor de elementos concretos do documento orixinal.

Comentarios: <xsl:comment>

Crea comentarios no documento de saída co formato

Instruccións de procesamento: <xsl:processing-instruction>

Inserta una instrucción de procesamento no documento resultante. Coma nos elementos <xsl:element> e <xsl:attribute>, cada elemento <xsl:processing-instruction> ten un atributo name obrigatorio.

Documentos con varias plantillas

Cuando en un documento encontramos varias plantillas, se debe tener claro cómo se procesa el documento origen y cuál será el resultado. Por ejemplo, si sobre el documento XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="curso2.xsl"?>
<Curso horas="40">
    <Asistente>Pepe Carballeira</Asistente>
    <Asistente>Rafael Chousa</Asistente>
    <Asistente>Ana Chamadoira</Asistente>
    <Asistente>Alba Pereira</Asistente>
    <Tema>Xeración de documentos XML</Tema>
    <Tema>Validación de documentos XML</Tema>
    <Tema>Transformación de documentos XML</Tema>
</Curso>

Aplicamos a seguinte transformación:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="//Asistente"> Encontramos un asistente. </xsl:template>
    <xsl:template match="//Tema"> Encontramos un tema. </xsl:template>
</xsl:stylesheet>

Coma os elementos Asistente y Tema están ó mesmo nivel (ningún deles é fillo do outro), procésanse ambas plantillas e obtense o siguiente documento resultante:

Encontramos un asistente. 
Encontramos un asistente. 
Encontramos un asistente. 
Encontramos un asistente. 
Encontramos un tema. 
Encontramos un tema. 
Encontramos un tema.

Mais se procesásemos o mesmo documento orixe co seguinte documento XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="//Curso"> Encontramos un curso. </xsl:template>
    <xsl:template match="//Asistente"> Encontramos un asistente. </xsl:template>
</xsl:stylesheet>

O resultado amosaría “Encontramos un asistente” repetido catro veces e a continuación “Encontramos un curso” unha vez? Non. A saída que produce é simplemente:

“Encontramos un curso”.

A razón é que o procesador atopa a plantilla coa expresión //Asistente que encaixa cos elementos Asistente, e a plantilla coa expresión //Curso, que encaixa co elemento Curso. Coma os elementos atopados pola primeira expresión xa están contidos no elemento Curso (son os seus fillos), esta plantilla non chega a aplicarse.

Porén, os elementos Asistente procesaranse coa plantilla da expresión //Curso, que é de maior nivel, e non se mostra nada referente aos asistentes no documento resultante porque as reglas da plantilla non o contemplan.

Para que ó aplicar unha plantilla sobre un elemento continúe procesando os seus fillos, tenriamos que incluir o elemento <xsl:apply-templates> dentro da plantilla. Este elemento tene un atributo select que permite restrinxir os fillos sobre os que seguir procesando a plantilla:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/Curso"> Encontramos un curso. 
        <xsl:apply-templates select=”Tema”/>
    </xsl:template>
    <xsl:template match="Asistente"> Encontramos un asistente. </xsl:template>
    <xsl:template match="Tema"> Encontramos un tema. </xsl:template>
</xsl:stylesheet>

Neste caso a saída sería:

Encontramos un curso. 
Encontramos un tema. 
Encontramos un tema. 
Encontramos un tema.

Plantillas predefinidas

Cando tenemos algún elemento do documento orixe que non se procesa por ningunha plantilla (isto é, un elemento que non encaixa coa expresión dunha plantilla nin é fillo dos elementos que encaixan), entón o procesador XSLT aplicalles as plantillas predefinidas.

Por exemplo, se lle aplicásemos ao documento anterior a seguinte transformación:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="//Tema"> Encontramos un tema. </xsl:template>
</xsl:stylesheet>

Obteríamos o seguiente resultado:

Pepe Carballeira
Rafael Chousa
Ana Chamadoira
Alba Pereira
Encontramos un tema. 
Encontramos un tema. 
Encontramos un tema.

Básicamente, o comportamento das plantillas predefinidas é procesar estes elementos comentados e os seus fillos amosando o texto que conteñen.

Aspectos avanzados das plantillas

Estruturas de control

Coma parte das plantillas podemos usar certas estruturas de control no procesamento dos elementos do documento orixinal.

Bucles: <xsl:for-each>

O elemento <xsl:for-each select=”expresión XPath”> selecciona cada un dos nodos do conxunto de nodos resultado da expresión indicada.

Condicións simples: <xsl:if>

O elemento <xsl:if test=”condición”> permite xenerar un contido únicamente cando a condición sexa certa.

Condicións múltiples: <xsl:choose>, <xsl:when> e <xsl:otherwise>

O elemento <xsl:choose> permite incluir múltiples condicións, cada unha especificada polo elemento <xsl:when test=”condición”> ou <xsl:otherwise>.

Cando se cumple unha condición prodúcese a saída desexada e abandónase a estrutura:

<xsl:choose>
    <xsl:when test="condición"></xsl:when>
    <xsl:when test="condición"></xsl:when>
    <xsl:otherwise></xsl:otherwise>
</xsl:choose>

Conversións máis avanzadas coas estruturas de control

Estas estruturas de control permiten realizar conversións más avanzadas. Se queremos amosar o seguinte documento XML con notas de alumnos:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Notas por Cores.xslt"?>
<alumnos>
    <alumno>
        <nombre>Perico dos Palotes</nombre>
        <nota>8</nota>
    </alumno>
    <alumno>
        <nombre>Arsenio Lupin</nombre>
        <nota>9.7</nota>
    </alumno>
    <alumno>
        <nombre>Frodo Bolson</nombre>
        <nota>4.6</nota>
    </alumno>
    <alumno>
        <nombre>Smeagol</nombre>
        <nota>6.2</nota>
    </alumno>
    <alumno>
        <nombre>Pulgarcito</nombre>
        <nota>7.6</nota>
    </alumno>
</alumnos>

E o queremos en forma de táboa HTML con cores alternas para o fondo das filas e con distinta cor en función da nota:

<?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>
                <h1>Notas</h1>
                <table border="1">
                    <tr bgcolor="gray">
                        <th>Alumno</th>
                        <th>Nota</th>
                    </tr>
                    <xsl:for-each select="alumnos/alumno">
                        <xsl:text disable-output-escaping="yes">
                            <tr 
                            </xsl:text>
                            <xsl:if test="(position() mod 2) = 1"> bgcolor="yellow" </xsl:if>
                            <xsl:text disable-output-escaping="yes"> ></xsl:text>
                            <td>
                                <xsl:value-of select="nombre"/>
                            </td>
                            <xsl:choose>
                                <xsl:when test="nota < 5">
                                    <td bgcolor="red">
                                        <xsl:value-of select="nota"/>
                                    </td>
                                </xsl:when>
                                <xsl:when test="nota < 7">
                                    <td bgcolor="yellow">
                                        <xsl:value-of select="nota"/>
                                    </td>
                                </xsl:when>
                                <xsl:otherwise>
                                    <td bgcolor="green">
                                        <xsl:value-of select="nota"/>
                                    </td>
                                </xsl:otherwise>
                            </xsl:choose>
                            <xsl:text disable-output-escaping="yes">
                                <tr/>
                            </xsl:text>
                        </xsl:for-each>
                    </table>
                </body>
            </html>
        </xsl:template>
    </xsl:stylesheet>

Outra opción sería utilizar plantillas:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/alumnos">
        <html>
            <body>
                <h1>Notas</h1>
                <table border="1">
                    <tr bgcolor="gray">
                        <th>Alumno</th>
                        <th>Nota</th>
                    </tr>
                    <xsl:apply-templates select="alumno"/>
                </table>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="alumno">
        <xsl:text disable-output-escaping="yes"> &lt;tr </xsl:text>
        <xsl:if test="(position() mod 2) = 1"> bgcolor="yellow" </xsl:if>
        <xsl:text disable-output-escaping="yes"> &gt; </xsl:text>
        <td>
            <xsl:value-of select="nombre"/>
        </td>
        <xsl:choose>
            <xsl:when test="nota < 5">
                <td bgcolor="red">
                    <xsl:value-of select="nota"/>
                </td>
            </xsl:when>
            <xsl:when test="nota < 7">
                <td bgcolor="yellow">
                    <xsl:value-of select="nota"/>
                </td>
            </xsl:when>
            <xsl:otherwise>
                <td bgcolor="green">
                    <xsl:value-of select="nota"/>
                </td>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:text disable-output-escaping="yes"> &lt;/tr&gt; </xsl:text>
    </xsl:template>
</xsl:stylesheet>

Ordenar os resultados: <xsl:sort >

Para ordenar os resultados teremos que empregar o elemento <xsl:sort select=”elementoXML”/> dentro do <xsl:for-each> ou <xsl:apply-templates> que corresponda.

Este elemento pode ter tres atributos:

  • select: indica cal será o elemento polo que se ordearán os resultados.
  • order: pode ser ascending ou descending
  • data-type: pode ser number ou text

No exemplo anterior, para ordear a táboa pola nota do alumno:

... 
<xsl:for-each select="alumnos/alumno"> 
<xsl:sort select="nota" data-type="number" order="descending"/> 
...

Variables: <xsl:variable>

Do mesmo xeito que nas linguaxes de programación podemos definir variables para despois utilizar o seu contido.

Para definir una variable empregamos o elemento:

<xsl:variable name=”nomeVariable”>

O seu valor pode ser unha expresión XPath no atributo select ou ben unha plantilla contida no propio elemento.

As variables podense definir no interior dunha plantilla ou fora, coma fillo directo do elemento <xsl:stylesheet>. Segundo sea o caso, teremos unha variable local a unha plantilla ou global a todo o documento XSLT.

Para obter o valor dunha variable utilízase o elemento <xsl:value-of>. O nome da variable estará contido no atributo select precedido polo símbolo $. Nese atributo, en lugar do nome dunha variable tamén podremos poñer unha expresión XPath. No caso de que existan múltiples nodos seleccionados pola expresión, seleccionarase o primeiro deles.

O elemento <xsl:value-of> substituirase polo valor da variable ou polo valor obtido pola expresión indicada:

<?xml version="1.0" encoding="UTF-8"?><
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="//Curso">
        <xsl:variable name="numAsistentes" select="count(Asistente)"/>
        <xsl:element name="Curso">
            <xsl:attribute name="asistentes">
                <xsl:value-of select="$numAsistentes"/>
            </xsl:attribute>
            <xsl:element name="Horas">
                <xsl:value-of select="@horas"/>
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Parámetros: <xsl:param> e <xsl:with-param>

xsl:with-param permite definir un parámetro que se lle pasará a una plantilla.

Atributos:

  • name:nombe do parámetro
  • select:ExpresiónXPath(opcional)

xsl:param Se é declarado coma elemento de alto nivel será un parámetro global e Se se declara dentro dunha plantilla é local e ten que ir asociado a un elemento xsl:with-param.

Atributos:

  • name:nome do parámetro
  • select:ExpresiónXPath(opcional)

Exemplo:

<xsl:templatematch="/">
 <html>
 <body>
  <xsl:for-eachselect=“//persona">
   <xsl:call-templatename=“mostrar_dni">
   <xsl:with-paramname=“dni" select= “@dni" />
   </xsl:call-template>
  </xsl:for-each>
 </body>
 </html>
</xsl:template>
<xsl:templatename= “mostrar_dni" >
 <xsl:paramname= “dni" />
  <p>DNI: <xsl:value-ofselect= "$dni" /></p>
 </xsl:template>
</xsl:stylesheet>

Copiar elementos do documento orixe: <xsl:copy> e <xsl:copy-of>

XSLT permite copiar no documento resultante un nodo ou un conxunto de nodos do documento orixe. Esta copia pódese facer de dous xeitos:

  • <xsl:copy>: realiza unha copia sinxela do elemento ó que se refire a plantilla. Non copia os seus atributos, o seu texto ou os seus fillos e so ó elemento. Se quixeramos procesar tamén o seu contenido habería que facelo de xeito específico.
  • <xsl:copy-of>: fai unha copia profunda e traslada ó documento resultante o texto, os fillos e os atributos do orixinal. A diferencia de <xsl:copy>, necesita do atributo select para seleccionar os nodos que debe copiar.

Por ejemplo, o documento seguinte:

<?xml version="1.0" encoding="UTF-8"?>
<Curso horas="40">
    <Asistente>Simon Templar</Asistente>
    <Asistente>Ralph Hinkley</Asistente>
    <Asistente>Maddie Hayes</Asistente>
    <Asistente>Blanche Devereaux</Asistente>
</Curso>

Poderíamolo copiar dos seguintes xeitos:

xls:copy

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/Curso">
        <Asistentes>
            <xsl:apply-templates/>
        </Asistentes>
    </xsl:template>
    <xsl:template match="Asistente">
        <xsl:copy/>
    </xsl:template>
</xsl:stylesheet>

Resultado:

<Asistentes>
    <Asistente />
    <Asistente />
    <Asistente />
    <Asistente />
</Asistentes>

xls:copy-of

<?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:copy-of select="Curso"/>
    </xsl:template>
</xsl:stylesheet>
<Curso>
    <Asistente>Simon Templar</Asistente>
    <Asistente>Ralph Hinkley</Asistente>
    <Asistente>Maddie Hayes</Asistente>
    <Asistente>Blanche Devereaux</Asistente>
</Curso>

Tamén se poderían facer copias idénticas do documento orixe con xls:copy, seleccionando todos os elementos e atributos así:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Aplicar varias plantillas ao mesmo nodo: <xsl:template> e <xsl:applytemplates> con atributo mode

Por defecto, un procesador XSLT selecciona a plantilla que se vai aplicar a cada un dos nodos que forman o documento XML que se procesa. Se o que desexamos é transformar un ou varios nodos de dúas ou máis formas diferentes, necesitamos que o procesador aplique máis dunha plantilla sobre o mesmo nodo: empregaremos o atributo mode.

Este atributo permite definir máis dunha plantilla para o mesmo nodo. Aplicase aos elementos <xsl:template> e <xsl:applytemplates>. Se varias plantillas se aplican ao mesmo nodo, os valores dos seus atributos mode deben ser distintos.

Por exemplo, para ordenar a lista de asistentes de forma ascendente primeiro e descendente despois podémolo facer así:

<?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:element name="Asistentes">
            <xsl:element name="Asistentes_Asc">
                <xsl:apply-templates mode="asc"/>
            </xsl:element>
            <xsl:element name="Asistentes_Desc">
                <xsl:apply-templates mode="desc"/>
            </xsl:element>
        </xsl:element>
    </xsl:template>
    <xsl:template match="Curso" mode="asc">
        <xsl:for-each select="Asistente">
            <xsl:sort select="."/>
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:template>
    <xsl:template match="Curso" mode="desc">
        <xsl:for-each select="Asistente">
            <xsl:sort select="." order="descending"/>
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Produciría a seguinte saída:

<Asistentes>
    <Asistentes_Asc>
        <Asistente>Blanche Devereaux</Asistente>
        <Asistente>Maddie Hayes</Asistente>
        <Asistente>Ralph Hinkley</Asistente>
        <Asistente>Simon Templar</Asistente>
    </Asistentes_Asc>
    <Asistentes_Desc>
        <Asistente>Simon Templar</Asistente>
        <Asistente>Ralph Hinkley</Asistente>
        <Asistente>Maddie Hayes</Asistente>
        <Asistente>Blanche Devereaux</Asistente>
    </Asistentes_Desc>
</Asistentes>

Claves e identificadores: <xsl:key>

Podemos crear claves para identificar elementos do documento original. Os procesadores XSLT adoitan crear índices internos para as claves mellorando o acceso ao seu contido.

Para crear una clave utilízase o elemento <xsl:key>. Este elemento debe ser fillo directo de <xsl:stylesheet>. Nno se pode utilizar en ningún outro sitio, coma por exemplo formando parte dunha plantilla.

Ten tres atributos requeridos:

  • name: asigna un nome á clave para poder utilizala posteriormente
  • match: indica os nodos que serán indexados pola clave
  • use: define a propiedade dos nodos que se empregará para crear o índice. Esta propiedade é a que usaremos para acceder aos nodos do índice.

Por exemplo, para definir unha clave para os alumnos sobre o seu nome:

<?xml version="1.0" encoding="UTF-8"?>
<alumnos>
    <alumno>
        <nombre>Perico dos Palotes</nombre>
        <nota>8</nota>
    </alumno>
    <alumno>
        <nombre>Arsenio Lupin</nombre>
        <nota>7</nota>
    </alumno>
    <alumno>
        <nombre>Frodo Bolson</nombre>
        <nota>7</nota>
    </alumno>
    <alumno>
        <nombre>Smeagol</nombre>
        <nota>4</nota>
    </alumno>
    <alumno>
        <nombre>Pulgarcito</nombre>
        <nota>8</nota>
    </alumno>
</alumnos>

Faríamos o seguinte:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="clave_alumno" match="alumno" use="nombre"/>
</xls:stylesheet>

Unha vez creada a clave, utilizando a función key() obteremos os nodos da clave indicando a propiedade definida no atributo use.

No noso exemplo se posteriormente quixeramos obter a partir do nome dun alumno a nota correspondeente faríamos:

<xsl:template match="/">
    <xsl:value-of select="key('clave_alumno', 'Pulgarcito')/nota" />
</xsl:template>

Identificadores de nodos

A función específica de XSLT generate-id recibe como parámetro un nodo e devolve un valor único xenerado aleatoriamente. Este valor será único en todo o documento, e ademáis será sempre o mesmo para ese nodo e esa execución: se máis adiante empregamos de novo a función generate-id co mesmo nodo obteremos o mesmo valor.

Úsase por exemplo para xenerar identificadores e enlaces internos a eles mesmos nun documento HTML:

<a name="{generate-id(.)}">
    <xsl:value-of select="nombre" />
</a><!-- y xeneramos o enlace -->
<a href="#{generate-id(.)}"> Para ir al elemento, pinche aquí </a>

Agrupamento de nodos

Gracias as claves e á xeneración de identificadores, podemos realizar o agrupamento de nodos.

Faise en dous pasos:

  • un bucle for-each selecciona o primeiro nodo de cada grupo
  • outro bucle dentro do primeiro crea os elementos do grupo

Podemos facer un grupo por cada valor da nota, e amosar dentro de cada un aos alumnos que obtuvieron esa nota.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="clave_alumno" match="alumno" use="nota"/>
    <xsl:template match="/">
        <xsl:element name="Notas">
            <xsl:for-each select="/alumnos/alumno[generate-id(.)=generate-id(key('clave_alumno',nota))]">
                <xsl:sort select="nota" order="descending" />
                <xsl:element name="Nota">
                    <xsl:attribute name="valor">
                        <xsl:value-of select="nota" />
                    </xsl:attribute>
                    <xsl:for-each select="key('clave_alumno',nota)">
                        <xsl:element name="Alumno">
                            <xsl:value-of select="nombre" />
                        </xsl:element>
                    </xsl:for-each>
                </xsl:element>
            </xsl:template>
        </xsl:stylesheet>

O primeiro bucle recorre os alumnos e coa condición indicada na expresión XPath quédase soamente con uno por cada valor diferente da nota.

A función key('clave_alumno',nota) busca a nota do nodo que procesa o bucle (nota) na clave creada sobre a nota e devolve o nodo correspondente ó primeiro alumno de todos os que comparten esa nota.

Despois empregando generate-id comprobamos se o nodo que está procesando o bucle (.) é o mesmo que devolve a función key. Se non e así, non se cumple a condición (non é o primeiro nodo con esa mesma nota) e non se procesan os elementos do bucle.

O segundo bucle utiliza a clave para procesar todos os nodos cunha mesma nota.

O resultado será:

<?xml version="1.0" encoding="UTF-8"?>
<Notas>
    <Nota valor="8">
        <Alumno>Perico dos Palotes</Alumno>
        <Alumno>Pulgarcito</Alumno>
    </Nota>
    <Nota valor="7">
        <Alumno>Arsenio Lupin</Alumno>
        <Alumno>Frodo Bolson</Alumno>
    </Nota>
    <Nota valor="4">
        <Alumno>Smeagol</Alumno>
    </Nota>
</Notas>

Formato do resultado: <xsl:output>

Coa etiqueta <xsl:output ...> podemos definir distintas características sobre o formato do documento de saída (son todas opcionais):

<xsl:output method="xml|html|text" version="string" encoding="string" omit-xml-declaration="yes|no" standalone="yes|no" doctype-public="string" doctype-system="string" cdata-section-elements="namelist" indent="yes|no" media-type="string"/>

O atributo method e importante; se non se inclúe, o formato de saída por defecto é XML (a no ser que o elemento raíz do documento sexa html, no que a saída será HTML se non se indica outro formato).

Aínda que depende do procesador XSLT que utilicemos, na maioría das ocasións se o documento resultante é XML incluirase no mesmo de forma automática unha declaración <?xml ... ?>.

Resumo

  • Os ficheiros XML permiten organizar a información de forma xerárquica
  • Son lexibles mais hai que procesar a información para darlle un valor engadido e facilitar a comprensión
  • XSLT e un estándar para transformar documentos XML a outros documentos coma HTML ou XML
  • A etiqueta do ficheiro XML que fai referencia a folla de estilo XSL:
<?xml-stylesheet type="text/xsl" href="ficheiro.xsl"?>
  • E a orden template:
<?xsl:template match="/">
  • Distínguese a orde e o atributo match que asocia en XPath a plantilla a un nodo XML
  • As etiquetas máis usadas:
  • <xsl:value-of>. Extrae o valor dun documento XML e o engade o fluxo de saída da transformación.
  • <xsl:for-each>. Selecciona todos os elementos un a un dunha lista determinada.
  • <xsl:sort>. Ordena alfabéticamente un grupo de nodos.
  • <xsl:if>. Estrutura condicional. Executase o seu contido cando se cumpra a condición do IF
  • <xsl:choose>. Estrutura condicional. Permite optar entre varias condicións.

Exercicios

Referencias