graphic with four colored squares

Introducción a XSLT

Jose Emilio Labra Gayo

Octubre 2006

Contenidos

Introducción a XSLTJose Emilio Labra GayoOctubre 2006

Ejemplo

Formato de una hoja de estilos

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

Procesadores de hojas de estilos

Generando HTML

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

<xsl:template match="/">
 <html>
 <head>
 <title>Ejemplo</title>
 </head>
 <body>
  <h1>Poema</h1>
 </body>
 </html>
</xsl:template>
</xsl:stylesheet>

Reglas de Plantillas

Las reglas de plantillas (templates) se identifican mediante:

<xsl:template match="...">
...resultado...
</xsl:template>

El valor del atributo match es una expresión XPath

Cuando el procesador encaja el nodo actual con la expresión genera el valor de la plantilla

Asociaciar hoja de estilos a documento XML

Es posible indicar en el documento XML qué hoja de estilos lleva asociada

Un navegador puede reconocer dicha información y mostrar el resultado de la transformación

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="hoja.xsl" ?> 
<poema fecha="Abril de 1915" lugar="Granada">
 <titulo>Alba</titulo>
 <verso>Mi corazon oprimido</verso>
 <verso>late junto a la alborada</verso>
 . . .
</poema>

Obtener valores

<xsl:template match="poema">
   Fecha: <xsl:value-of select="@fecha"/>, 
   Lugar: <xsl:value-of select="@lugar"/>
</xsl:template>

Aplicando plantillas

Por defecto, el procesador lee el documento y recorre el árbol según el orden de los nodos

apply-templates permite indicar al procesador que continúe procesando ciertas reglas de plantillas

<xsl:template match="poema">
   Versos: <xsl:apply-templates select="verso" />
   Titulo: <xsl:apply-templates select="titulo" />
</xsl:template>

apply-templates sin argumentos selecciona todos los hijos del nodo actual.

Modos

Es posible indicar varios modos de recorrido

Crear una tabla de contenidos
<xsl:template match="/">
 Contenidos: 
  <ul><xsl:apply-templates mode="cont" /></ul>
 <xsl:apply-templates />
</xsl:template>

<xsl:template match="poema" mode="cont">
 <li><xsl:value-of select="titulo" /></li>
</xsl:template>

<xsl:template match="poema">
 ...
</xsl:template>

Plantillas predefinidas

Plantillas predefinidas

Las plantillas predefinidas tienen la menor prioridad posible

Pueden re-definirse por la aplicación

Plantilla para nodos de texto y atributos


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

Plantilla para elementos y raíz


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

Nota: Esta plantilla funciona para cualquier modo

Plantillas para el resto de nodos

Las instrucciones de procesamiento, comentarios y espacios de nombre se ignoran


<xsl:template match="processing-instruction()|comment()" />

Creación del Árbol de resultado

Árbol de resultado literal

Todos los elementos que no pertenezcan al espacio de nombres de XSLT son generados en el árbol de resultado.

Se añaden todas las declaraciones de espacios de nombres utilizadas

Excepciones:

Creación de elementos

Mediante element puede definirse un elemento nuevo.

  
   <xsl:template match="poema">
    <xsl:element name="h1">
     <xsl:value-of select="titulo" />
    </xsl:element>
   </xsl:template>
  

Puede especificarse el espacio de nombres del elemento mediante el atributo namespace

Creación de atributos

Mediante attribute puede definirse un atributo nuevo.

<enlace 
 url="http://www.uniovi.es">
  Universidad</enlace>
<xsl:template match="enlace">
<xsl:element name="a">
 <xsl:attribute name="href">
  <xsl:value-of select="@url"/>
 </xsl:attribute>
 <xsl:value-of select="."/>
</xsl:element>
</xsl:template>
resultado
<a 
 href="http://www.uniovi.es">
  Universidad</a>

Puede especificarse el espacio de nombres mediante el atributo namespace

Plantillas de atributos

Mediante {...} es posible incluir expresiones XPath en un atributo que son evaluadas al generar el resultado.

<enlace 
 url="http://www.uniovi.es">
  Universidad</enlace>
<xsl:template match="enlace">
 <a href="{@url}">
  <xsl:value-of select="." />
 </a>
</xsl:template>
resultado
<a 
 href="http://www.uniovi.es">
  Universidad</a>

Conjuntos de atributos

Mediante attribute-set pueden definirse conjuntos de atributos para su reutilización posterior

<xsl:attribute-set name="img-grande">
 <xsl:attribute name="width">250px</xsl:attribute>
 <xsl:attribute name="height">250px</xsl:attribute>
</xsl:attribute-set>

<xsl:attribute-set name="img-peque">
 <xsl:attribute name="width">50px</xsl:attribute>
 <xsl:attribute name="height">50px</xsl:attribute>
</xsl:attribute-set>

<xsl:template match="imagen" mode="cont">
 <img xsl:use-attribute-sets="img-peque" src="{@src}" />
</xsl:template>

Texto

Mediante text se puede incluir texto

<xsl:template match="poema">
 <h1>Titulo: <xsl:value-of select="titulo"/></h1>
 <h2>Fecha y lugar: 
  <xsl:value-of select="@fecha" />
  <xsl:text> </xsl:text>
  <xsl:value-of select="@lugar" />
 </h2>
</xsl:template>

Comentarios

Para añadir comentarios al resultado se utiliza comment

<xsl:template match="/">
 <poema>
 <xsl:comment>Generado mediante XSLT</xsl:comment>
 <xsl:apply-templates />
 </poema>
<xsl:template>


 <poema>
 <!-- Generado mediante XSLT -->
  ... 
 </poema>

Instrucciones de procesamiento

Para añadir instrucciones de procesamiento se utiliza processing-instruction

<xsl:template match="/">
 <xsl:processing-instruction 
   name="xml-stylesheet">
   href="poema.xsl" 
   type="text/xsl"
 </xsl:processing-instruction>
Resultado
<?xml-stylesheet href="poema.xsl" type="text/xsl"?>

Copiado de contenido

Mediante copy es posible crear una copia del nodo actual

No se copian los atributos ni los hijos salvo que se especifique mediante apply-templates

<xsl:template match="titulo|verso">
 <xsl:copy>
  <xsl:apply-templates/>
 </xsl:copy>
</xsl:template>

Copiado de contenido

copy-of permite indicar los nodos que serán copiados al resultado mediante el atributo select

Copiado de todo el poema
<xsl:template match="poema">
 <xsl:copy-of select="." />
</xsl:template>

Ejercicio

Eliminar instrucciones de procesamiento

Crear una hoja de estilos que tome un documento XML y devuelva el mismo documento tras eliminar las instrucciones de procesamiento.

NOTA: Deben dejarse el resto de nodos: comentarios, elementos, atributos, etc. tal y como estaban.

Alternativas y control

Condicional

xsl:if establece una condición para generar el resultado

NOTA: No tiene else

<xsl:template match="poema">
 <xsl:if test="@lugar='Granada'">
  <xsl:comment>Granada</xsl:comment>
 </xsl:if>
 <xsl:apply-templates />
</xsl:template>

Condicional

xsl:choose selecciona entre varias alternativas

<xsl:template match="poema">
 <xsl:choose>
  <xsl:when test="@lugar='Granada'">
  <xsl:comment>Granada</xsl:comment>
  </xsl:when>
 <xsl:when test="@lugar='Oviedo'">
  <xsl:comment>Oviedo</xsl:comment>
 </xsl:when>
 <xsl:otherwise>
  <xsl:comment>Otro lugar</xsl:comment>
 </xsl:otherwise>
</xsl:template>

Repetición

for-each repite un procesamiento para un conjunto de nodos

<xsl:template match="poema">
<ul>
<xsl:for-each select="verso">
 <li><xsl:value-of select="." /></li>
</xsl:for-each>
</ul>
</xsl:template>

NOTA: No es un bucle for convencional

Ejercicio

Formatear un libro

Crear una hoja de estilos que tome un documento que represente un libro y genere una página Web.

Como ejemplo, puede utilizarse el documento siguiente

Ejercicio

Formatear una lista de notas

Crear una hoja de estilos que tome un documento que represente una lista de alumnos con sus respectivas notas y las formatee en una página Web.

Como ejemplo, puede utilizarse el documento siguiente

Ejercicio

Lista de eventos

Crear un vocabulario que represente eventos

Cada evento tendrá asociada la siguiente información:

Crear un documento de ejemplo de eventos

Crear una hoja de estilos que transforme documentos con eventos en formato HTML

Ejercicio

Formato Atom

Crear una hoja de estilos que convierta documentos en formato Atom en documentos en el formato de eventos desarrollado en el ejercicio anterior

Variables y parámetros

Variables

variable permite declarar una variable

NOTA: Los valores de las variables no pueden modificarse = Programación declarativa!

<xsl:template match="rectangulo">
<xsl:variable name="area" select="@base * @altura" />

El area es 
 <xsl:value-of select="$area" /> y
 el doble del area es
 <xsl:value-of select="$area * 2" />
</xsl:template>

Lo que no se puede hacer es:

 <xsl:variable name="area" select="$area = $area * 2"/>
 

Parámetros

Mediante param pueden definirse parámetros de la hoja de estilos. Son similares a las variables.

La principal diferencia es que los parámetros toman valores por defecto que pueden ser alterados cuando la plantilla o la hoja de estilo es invocada

<xsl:param name="hazIndice">SI</xsl:param>

<xsl:template match="/">
 <xsl:if test="$hazIndice = 'SI'">
  <xsl:apply-templates mode="indice" />
 </xsl:if>
 <xsl:apply-templates/>
</xsl:template>

Plantillas con nombre y recursividad

Plantillas con nombre

Mediante el atributo name es posible asociar un nombre a una plantilla

Para invocar la plantilla se utiliza call-template

Se pueden pasar parámetros mediante with-param

<xsl:template name="suma">
 <xsl:param name="a" />
 <xsl:param name="b" />
 <xsl:value-of select="$a + $b" />
</xsl:template>

<xsl:template match="/">
 <xsl:call-template name="suma">
  <xsl:with-param name="a" select="2" />
  <xsl:with-param name="b" select="3" />
 </xsl:call-template>
</xsl:template>

Recursividad

Factorial
<xsl:template name="fact">
 <xsl:param name="n" />
 <xsl:choose>
  <xsl:when test="$n=0">1</xsl:when>
  <xsl:otherwise>
   <xsl:variable name="r">
    <xsl:call-template name="fact">
     <xsl:with-param name="n" select="$n - 1"/>
    </xsl:call-template>
   </xsl:variable>
   <xsl:value-of select="$n * $r" />
  </xsl:otherwise>
 </xsl:choose>
</xsl:template>

Ejercicio

Bucle for

Crear una hoja de estilos que tome un número n y genere una lista de n items

con el siguiente formato:
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
...
</ul>

Ejercicio

Tabla

Crear una hoja de estilos que tome un número n y genere una tabla HTML de n filas y n columnas

Ejercicio

Substituir

Crear una hoja de estilos que tome un documento y substituya todas las apariciones de una cadena de texto por otra.

Ejercicio

Crear un calendario

Crear una hoja de estilos que tome como argumento un mes y un año y genere un calendario. Puede partirse del siguiente documento XML y de la siguiente hoja de estilos

Ejercicio

Eventos en calendario

Crear una hoja de estilos que represente documentos de eventos en un calendario

Mensajes y terminación

XSLT es un lenguaje pensado para transformar documentos XML

<xsl:template name="imagen">
 <xsl:if test="not(@href)">
  <xsl:message terminate="yes"> 
   No se encuentra valor de href en imagen
  </xsl:message>
 ...
</xsl:template>

Clasificación

Clasificación

sort realiza una clasificación del conjunto de nodos

Puede utilizarse más de un criterio de clasificación

<xsl:template match="alumnos">
 <xsl:for-each select="alumno">
  <xsl:sort select="apellidos" />
  <xsl:sort select="nombre" />
  <p><xsl:value-of select="apellidos" />, 
     <xsl:value-of select="nombre" /></p>
 </xsl:for-each>
</xsl:template>

Clasificación

El atributo data-type permite indicar la forma de clasificación:

El atributo order indica el tipo de clasificación:

<xsl:template match="alumnos">
  <xsl:for-each select="alumno">
    <xsl:sort select="nota" 
              data-type="number" 
              order="descending"/>
   <p><xsl:value-of select="apellidos" /></p>
  </xsl:for-each>
</xsl:template>

Numeración

Numeración automática

El elemento number permite insertar un número formateado en el resultado

<xsl:template match="alumnos">
  <xsl:for-each select="alumno">
    <xsl:sort select="apellidos"/>
    <p>
      <xsl:number value="position()" format="1. "/>
      <xsl:value-of select="apellidos"/>,
      <xsl:value-of select="nombre"/>
    </p>
  </xsl:for-each>
</xsl:template>

Estilo de numeración

Los atributos de number permiten modificar el formato de la numeración

Formato de numeración

El elemento number-format especifica el formato del número

Los atributos para controlar el formato de salida son:

Claves e identificadores

Identificadores

La función id permite seleccionar un elemento con un identificador determinado

Puede ser útil para buscar elementos

Limitación: requiere declarar atributo como ID en la DTD

<dibujos>
<colores>
<color id="rojo">255,0,0</color>
<color id="azul">0,0,255</color>
...
</colores>

<cuadro color="rojo" .../>
<cuadro color="verde" .../>
...
</dibujos>
<xsl:template match="cuadro">
<svg:rect 
 fill=
 "rgb({id(@color)})"
 ... />
</xsl:template>

Identificadores y claves

El ejemplo anterior puede realizarse mediante una búsqueda completa

Limitación: la búsqueda completa es poco eficiente

<dibujos>
<colores>
<color id="rojo">255,0,0</color>
<color id="azul">0,0,255</color>
...
</colores>

<cuadro color="rojo" .../>
<cuadro color="verde" .../>
...
</dibujos>
<xsl:template match="cuadro">
<xsl:variable 
  name="color" 
  select="@color" />
<svg:rect 
fill=
"rgb({/dibujos/colores/color
 [@id=$color]})" 
  ... />
</xsl:template>

Identificadores y Claves

xsl:key permite optimizar la búsqueda de información en un documento XML mediante la creación de índices

<dibujos>
<colores>
<color id="rojo">255,0,0</color>
<color id="azul">0,0,255</color>
...
</colores>

<cuadro color="rojo" .../>
<cuadro color="verde" .../>
...
</dibujos>
<xsl:key name="claveColor" 
     match="color" 
     use="@id" />
         
<xsl:template match="cuadro">
<svg:rect 
 fill=
 "rgb({key('claveColor',
 @color)})"
 ... />
</xsl:template>

Generación de identificadores

La función generate-id() permite generar un identificador único. Toma como argumento un nodo y devuelve un identificador asociado a dicho nodo.

Puede ser útil para generación de tablas de contenidos

<xsl:template match="poema" mode="cont">
 <li><a href="#{generate-id(.)">
   <xsl:value-of select="titulo" />
 </a></li>
</xsl:template>

<xsl:template match="poema">
 <a name="generate-id(.)">
  ...
 </a>
</xsl:template>

Inclusión

xsl:include permite incluir otra hoja de estilos.

La inclusión actúa como si se hubiese tecleado diréctamente la hoja incluida en dicho lugar.

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

<xsl:include href="otraHoja.xsl" />

...
</xsl:stylesheet>

Importación

xsl:import importa el contenido de otra hoja de estilos en el documento actual.

Las plantillas de la hoja importada tienen menor prioridad que las plantillas de la hoja principal.

La instrucción import debe aparecer al comienzo de la hoja de estilos. No se permite recursividad

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

<xsl:include href="otraHoja.xsl" />

...
</xsl:stylesheet>

Acceso a otros documentos

La función document() permite acceder al contenido de otros documentos XML.

El argumento es la URI del documento a acceder. Si no tiene argumentos, se accede al documento de la hoja de estilos

<xsl:template match="verAlumnos">
 <xsl:for-each 
   select="document('alumnos.xml')/alumnos/alumno">
  <p><xsl:value-of select="nota"/></p>
 </xsl:for-each>
</xsl:template>

Controlando la salida

El elemento output permite controlar el formato del resultado. Puede tener los siguientes atributos:

Contenidos