0% encontró este documento útil (0 votos)
3 vistas19 páginas

Transformaciones XML con XSLT

Titorial XSLT

Cargado por

enemy32
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
3 vistas19 páginas

Transformaciones XML con XSLT

Titorial XSLT

Cargado por

enemy32
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Tutorial de XSL Page 1 of 19

Generación de páginas Web usando XSLT y Página principal del curso de XML
Usando hojas de estilo para generar WML
XML (teléfonos WAP)
Tutorial avanzado de generación de HTML
a partir de XML/XSLT
J. J. Merelo Otros cursos y tutoriales: comercio
electrónico, WAP, Webmaster
Página principal del grupo GeNeura
1 Introducción Ficheros de ejemplo

Al igual que XML, XSLT es un lenguaje de programación. Forma parte de la trilogía transformadora de
XML, compuesta por las CSS (Cascading Style Sheets, hojas de estilo en cascada), que permite dar una
apariencia en el navegador determinada a cada una de las etiquetas XML; XSLT (XML Stylesheets Language for
Transformation , o lenguaje de transformación basado en hojas de estilo); y XSL:FO, (Formatting Objects,
objetos de formateo), o transformaciones para fotocomposición, o, en general, para cualquier cosa que no sea
XML, como por ejemplo HTML "del viejo" o PDF (el formato de Adobe).

XSLT es pues, un lenguaje que se usa para convertir documentos XML en otros XHTML sí es XML, sigue un DTD
documentos XML; puede convertir un documento XML que obedezca a un DTD a otro que (varios, en realidad), y sólo admite
documentos "bien formados".
obedezca otro diferente, un documento XML bien formado a otro que siga un DTD, o, lo más
HTML no lo es, aunque pude
habitual, convertirlo a "formatos finales", tales como WML (usado en los móviles WAP) o convertirse fácilmente en XHTML
XHTML. usando utilidades tales como Tidy.

Los programas XSLT están escritos en XML, y generalmente, se necesita un procesador de hojas de estilo,
o stylesheet processor para procesarlas, aplicándolas a un fichero XML.

El estilo de programación con las hojas XSLT es totalmente diferente a los otros lenguajes a los que
estamos acostumbrados (tales como C++ o Perl), pareciéndose más a "lenguajes" tales como el AWK, o a otros
lenguajes funcionales, tales como ML o Scheme. En la práctica, eso significa dos cosas:

• No hay efectos secundarios. Una instrucción debe de hacer lo mismo cualquier que sea el camino de
ejecución que llegue hasta ella. O sea, no va a haber variables globales (¡Cielos!), ni bucles en los que se
incremente el valor de una variable, o tenga un test de fin de bucle, ni nada por el estilo. En realidad, esto
no es tan grave, y se puede simular usando recursión, como se verá.
• La programación está basada en reglas: cuando ocurre algo en la entrada, se hace algo en la salida. En
eso, se parece al AWK, o a cierto estilo de programación en PERL, pero no en el resto de las cosas. Al fin y
al cabo, no hay efectos secundarios.

En resumen, programar con las hojas XSLT (en inglés se les llama SAX significa Simple API for XML; un filtro SAX
stylesheets o logicsheets) puede ser un poco frustante, pero cuando uno aprende trata un fichero XML como un canal (stream) sobre el
cual se van aplicando transformaciones según se va
a usarlas, no puede vivir sin ellas. En realidad, son la única alternativa cuando
leyendo. Para transformaciones simples tales como
uno quiere adaptar un contenido descrito con XML a diferentes clientes (por extraer un tipo de etiqueta determinada, y, de hecho,
ejemplo, móviles de diferente tamaño, diferentes navegadores), y la mejor la mayoría de las incluidas en este tutorial, es mucho
alternativa cuando uno quiere procesar documentos XML (aunque haya otras: mejor usar un filtro SAX. El principal problema es
que carecen de un lenguaje para describir esas
filtros SAX, expresiones regulares...). Otra alternativa, sobre todo si se está transformaciones, y la sintaxis y aplicación depende
trabajando ya con un documento XML en forma de DOM (Document object totalmente del lenguaje en el que se trabaje. En Perl,
model) es trabajar directamente sobre él. En este claso, de todas formas, se por ejemplo, se puede usar XML::SAX, un módulo
pueden usar transformaciones XSL, sólo que se aplicarán en memoria, en vez de que permite hacer este tipo de transformaciones.
Generalmente, en caso de ficheros muy grandes a los
leerlas desde un fichero. que haya que hacerle un procesamiento relativamente
simple, SAX es una opción mejor, más rápida y con
Lo que consiguen las hojas de estilo es separar la información (almacenada menos consumo de memoria.
en un documento XML) de su presentación, usando en cada caso las
transformaciones que sean necesarias para que el contenido aparezca de la forma más adecuada en el cliente.
Es más, se pueden usar diferentes hojas de estilo, o incluso la misma, para presentar la información de
diferentes maneras dependiendo de los deseos o de las condiciones del usuario.

Aparte del hecho habitual de procesar documentos XML, XSLT es un lenguaje de programación, y por
tanto se podría hacer cualquier cosa con ellas; incluso calcular la célebre criba de Eratóstenes o ejecutar un
algoritmo genético. Pero a nosotros nos va a interesar más como simple herramienta de transformación de XML.

Actualmente hay varias versiones del estándar XSLT: la versión 1.0, que es la que implementan la
mayoría de los procesadores, y se denomina "recomendación", es decir, para el consorcio W3, lo equivalente a
un estándar, y la versión 2.0 , que, a fecha de 4 de noviembre del 2004, es un "working draft", o borrador de
trabajo, que es el paso previo a un estándar. Algunos procesadores, tales como el Saxon, implementan ya esta
última versión. Hay algunas diferencias importantes: el tratamiento uniforme de los árboles (técnicamente, se
pueden convertir fragmentos de árboles de resultados en nodesets), uso de múltiples documentos de salida, y
funciones definidas por el usuario que se pueden definir en XSLT, y no sólo en Java u otro lenguaje, como
sucedía en estándares anteriores. .

Para Windows, en sus diferentes versiones, hay dos herramientas que permiten editar Las convenciones que seguimos en
XML y hojas de estilo XSLT, y aplicar directamente la una a la otra. Una de ellas es XMLSpy, los ejemplos son las siguientes:
cada etiqueta XML en el
que tiene un IDE muy bonito, pero que casca con relativa frecuencia. De hecho, he sido
documento XML van en diferente
incapaz de aplicar una hoja de estilo a un documento XML. Otra opción es usar eXcelon color, dependiendo de su posición
Stylus, un peaso de programa, pero que sólo está disponible para WindowsNT/2000 (y no sé en la jerarquía; en las hojas XSL,
si XP); la versión 3.0 beta es gratuita para desarrolladores. el código XML está en rojo, el
código XSLT en verde, y el código
que no es exclusivo ni de uno ni de
En realidad, para editar XML y XSLT no hace falta ningún editor especial, pero viene otro, y que aparecerá tal cual en el
bien un editor de XML o incluso un entorno integrado que te ayude a indentar bien el código, documento final, en azul.
e incluso a cerrar las etiquetas en el orden correcto, o te saque la etiqueta y atributos
admisibles en cada momento en función del DTD. En ese sentido, si se trabaja en Windows, el mejor es el

[Link] 29/05/2017
Tutorial de XSL Page 2 of 19

eXcelon Stylus; en Linux, se puede uno apañar bien con el XEmacs (que te valida usando un DTD, si es
necesario).

Este tutorial no pretende ser una introducción exhaustiva al XML, en realidad, para los efectos de este
tutorial, hay que saber poco XML: sólo que hace falta emparejar bien las etiquetas, y la estructura de árbol que
sigue un documento XML (es lo que se denomina XML bien formado). En realidad, HTML se puede definir como
un documento bien formado, de hecho, la última versión de HTML, XHTML, también lo es, o sea que no es un
salto grande pasar de WML/XHTML a XML. En todo caso, los que quieran saber un poco más sobre el tema,
pueden consultar los diferentes tutoriales del curso GeNeura de XML.

Ejercicios 1
1. Crear un documento XML que describa una ficha de alumno. Tiene que tener una etiqueta raíz (por ejemplo,
acta), una etiqueta por cada alumno, y dentro de ellas, etiquetas para el DNI, nombre, apellidos y nota.

2 Cómo se usan las hojas de estilo


Hay muchas formas de usar las hojas de estilo. Lo más normal es usarlas dentro de un entorno de
publicación tal como el Cocoon, o el IBM Transcoding Publisher, AxKit u otros por el estilo. Un entorno de
publicación de XML permite mantener sitios completos basados en XML, y generar páginas en diferentes
formatos a partir de ellos. En general, recomendamos Cocoon, que es una herramienta gratuita y Open Source
basada en Java, y además una de las más avanzadas en el sector. Para una solución profesional, es mejor el
IBM TP, pues forma parte del servidor de aplicaciones WebSphere, y cuenta con interfaz gráfico avanzado; el
problema es el coste.

En muchos casos, lo que se necesita es aplicar hojas de estilo dentro de una aplicación, La principal diferencia entre
o usarlas desde línea de comandos a partir de otra aplicación o otro lenguaje de la versión 2 de Xalan y las
programación. En ese caso, lo más útil es usar un procesador de hojas de estilo, que anteriores es que implementa
habitualmente se encuentra en conjunción con un parser XML, con o sin validación. De estos, el llamado TrAX, una API
hay los siguientes: para poder aplicar
transformaciones a árboles
• Xalan, que será el que más usemos en este tutorial, y que además es gratuito. La XML; probablemente
versión actual es la 2.6. Es una herramienta escrita en Java, y lo único que se necesita incorpore también la versión
para hacerla funcionar es una máquina virtual Java (JVM), tal como la de Microsoft, Sun 1.1 de XSLT
o IBM. Xalan necesita un parser XML para funcionar, tal como el Xerces, aunque el
fichero correspondiente ([Link]) viene incluido en la distribución.
• Saxon, un procesador bastante rápido, también escrito en Java, con su propio parser incluido, aunque se
puede usar uno externo. Hay una versión denominada Instant Saxon, un procesador rápido, y fácil de usar,
sólo para Windows. Por lo pronto, es el único que implementa la versión 2.0 de XSLT.
• Hay otros muchos procesadores, tales como el XT de James Clark, xsltproc o el Sablotron. Todos ellos y
muchos más se pueden encontrar en la página de procesadores XSLT de [Link]. En Linux
recomiendo el xsltproc, basado en la librería XML/XSL de gnome; es muy rápido, es un ejecutable y no
hace falta instalar Java para usarlo.
• A su vez, los procesadores de hojas de estilo se pueden usar como librerías de clases, o desde otros
lenguajes. Por ejemplo, el módulo XML::XSLT para Perl. Estos módulos se pueden usar para poder trabajar
con XSLT fuera de entornos de publicación, como por ejemplo un servidor web normal. xalan es en realidad
una librería que se puede usar también desde programas en Java.
• Algunos navegadores también lo implementan, o lo harán en el futuro. En concreto, el Mozilla debería
incluirlo a partir de la versión 0.9; desde la versión 0.7 se podía incluir un plugin llamado TransforMiiX, que
teóricamente aplica XSLT. En realidad, casi todos los navegadores modernos, con mayor o menor fortuna,
lo incluyen. Firefox, por ejemplo, lo toma sin problemas.

Finalmente, para este curso, se puede usar un formulario simple que aplica hojas de estilo XSLT a
documentos XML usando Perl: aplicador de hojas de estilo.

3 Hojas de estilo básicas Contenido de esta


sección
• Ejecutando
Para empezar, vamos a tratar de presentar una hoja XML de lo más simple ([Link]):
hojas de
estilo
<?xml version="1.0" encoding='ISO-8859-1'?> • Hoja de
<?xml-stylesheet href="[Link]" type="text/xsl"?> estilo
<tienda>
básica:
<nombre>La tiendecilla </nombre>
<telefono>953 87 12 23 </telefono> templates
</tienda> • xsl:stylesheet,
xsl:apply-
templates,
xsl:value-of
Este ejemplo lo iremos extendiendo hasta que contenga un catálogo de una tienda virtual. Por
lo pronto incluimos solamente datos básicos sobre la tienda.

Para convertirlo en HTML, usaremos la siguiente hoja de estilo ([Link]):


1 <?xml version="1.0" encoding="UTF-8"?>
3 <xsl:stylesheet version="1.0" xmlns:xsl="[Link]
5 <xsl:template match='/'>
6 <html>
7 <head><title>Generado con [Link]</title></head>
8 <body>
9 <h1> <xsl:apply-templates /> </h1>
10 </body>
11 </html>
12 </xsl:template>
13 </xsl:stylesheet>

[Link] 29/05/2017
Tutorial de XSL Page 3 of 19

Tal como está, se puede cargar directamente con


Firefox, que mostrará algo similar a la imagen. Asimismo
se puede usar cualquier entorno integrado que incluya la
posibilidad de hacer transformaciones, como el XMLShell
o XMLSpy mencionados anteriormente.

3.1 Procesándolo con Xalan

Para procesarlo con el Xalan, tendremos que


hacer lo siguiente:

1. Añadir la máquina virtual Java al PATH:


unix$ export PATH=$PATH:/usr/bin/java
(o donde quiera que esté)
2. Añadir al CLASSPATH los .jar (ficheros de librería) que incluyen Xerces (el parser de XML) y Xalan (el procesador de
XSLT):
unix$ export CLASSPATH=$CLASSPATH:/usr/local/xalan/bin/[Link]:/usr/local/xalan/[Link]
(o donde quiera que estén)
java [Link] -IN [Link] -XSL [Link] -OUT [Link]
.

Esto debería dar como resultado algo como lo que hay en esta página web.

3.2 Procesándolo con Saxon

El saxon es otro procesador de hojas de estilo, que está disponible como un fichero .jar, y que por tanto
se puede ejecutar en cualquier plataforma. Para usarlo, se escribe (después de definir el camino a la máquina
virtual Java y al .jar correspondiente):

java [Link] [Link]


[Link]

3.3 Procesándolo con Instant Saxon

El Instant Saxon es una versión de Saxon que ocupa poco y es relativamente fácil de usar. Hay que tener
instalada una máquina virtual Java en Windows para que funcione; si tenemos instalado el Internet Explorer,
con eso vamos que ardemos. Una vez instalado el explorer, basta escribir:

saxon -o [Link] [Link] [Link]

Que nos dará el mismo resultado que anteriormente, con un poco de suerte.

También se puede usar el script en geneura, editando los ficheros anteriores y cortándolos y pegándolos
en el sitio adecuado. Este script usa dos librerías de Perl: XML::LibXML y XML::LibXSLT, que a su vez están
basadas en las librerías de Gnome LibXML2 equivalentes.

3.4 Explicación del código

Para empezar, el código del documento XML contiene una etiqueta, tienda, que incluye otras dos
etiquetas, nombre y telefono, que contienen el texto que queremos que aparezca en la página web. En el resto, la
primera línea simplemente describe que el resto del documento es XML, y asocia la hoja de estilo XSLT
([Link]) al documento. Esta segunda línea se usa en entornos de publicación tales como el cocoon; algunos
procesadores de XSLT la usan para tomar el nombre de la hoja de estilo que se va a usar; también lo suelen
usar navegadores como el Mozilla/Netscape/Firefox o el Internet Explorer. Cada una de estas etiquetas se
denominan elementos; y en principio, un documento puede tener tantas etiquetas como queramos.

El XML original, como se ve, es simplemente XML bien formado, no usa un DTD ni lo necesita: basta con
que haya una etiqueta raíz (tienda, en nuestro caso), las etiquetas estén emparejadas correctamente y los
atributos entre comillas. Diferentes documentos XML podrían ser procesados con la misma hoja de estilo, y
darían diferente resultado. Ahora mismo, tal como está, un documento XML tiene asociada una sola hoja de
estilo XSLT, y para ese viaje no hacen falta alforjas, salvo por el hecho de que muchos documentos XML pueden
tener la misma hoja XSL y de esa forma mantener una apariencia común. También se verá más adelante la
forma de que el procesador XSLT seleccione diferentes hojas XSLT dependiendo de las circunstancias
(principalmente, el cliente).

La primera hoja de estilo con la que nos enfrentamos es relativamente simple. El "esqueleto" es un
documento HTML normal, al cual tenemos que añadir "contenido dinámico", es decir, contenido generado a
partir del XML original. Para hacernos una idea, en este caso simple, una hoja XSLT es como una plantilla sobre
la que se cambian los contenidos por sus valores al aplicarla. En realidad, tendríamos que pensar en una hoja
XSLT con en un jardinero que va podando árboles, partiendo de la raíz. Al llegar a una rama, hace algo con ella:
la poda, inserta otra cosa, o simpelemente la deja tal cual; el árbol, en este caso, es realmente el árbol DOM del
documento XML que está tratando.

Para empezar, se incluyen una serie de instrucciones, de la línea 1 a la 5: no son instrucciones en sí, sino
que modifican el aspecto de la salida. La primera declara el documento XML y el tipo de codificación (que podría
ser ISO-8859-1 en vez de UTF-8 si quisiéramos incluir acentos y demás caracteres idiosincráticos) y la segunda
es la etiqueta raíz de la hoja de estilo (cerrada en la última línea; recordemos que una hoja de estilo XSL es
también un documento XML y por tanto tiene que seguir todas sus convenciones), que declara la versión de
XSLT que se está usando y el espacio de nombres (namespace) que vamos a usar, es decir, el prefijo que

[Link] 29/05/2017
Tutorial de XSL Page 4 of 19

usarán todas las instrucciones propias de XSLT; en este caso, usamos xsl, pero cambiando esta instrucción
podríamos usar otro cualquiera.

Ese esqueleto está organizado en "templates", que son partes de la hoja que se "disparan" cuando
encuentran una etiqueta que corresponda a lo que hay en su atributo match. El primer y único template comienza
en la línea 5, y, en este caso, el template que corresponde a la etiqueta raíz genera un esqueleto de página
HTML. La "orden" en la línea 9 cede el control a los otros templates, es decir, trata de aplicar todos los demás
templates que haya en el documento, incluyendo el resultado de aplicarlos precisamente en ese punto (es decir,
entre las etiquetas h1. En este caso no hay más templates, salvo los llamados los templates por defecto, que lo
único que hacen es incluir el contenido de las etiquetas en el documento de salida. Es decir, en la práctica lo que
hemos hecho es decirle dónde tiene que incluir en el esqueleto los valores del documento original, sin
procesarlos más.

La orden <xsl:apply-templates /> podría haberse sustituido, en este caso, por <xsl:value-of
select='tienda' /> y habría tenido exactamente el mismo efecto, es decir, incluir el contenido de la etiqueta
tienda (y todas las que descienden de ella).

Ejercicios 2
1. Crear un documento con otra etiqueta raíz, por ejemplo zzzxxx, y ver qué efecto tiene en la salida .
2. Crear un documento con varias etiquetas, con diferentes niveles de anidación, y aplicar la hoja de estilo, para
ver qué efecto tiene.

4 Profundizando Contenido de esta


sección
• Documentos
Vamos a ver algún documento XML algo más complicado; en concreto, vamos a tratar de
XML con
procesar documentos XML que describen diferentes artículos de una tienda. Una tienda virtual está más
formada por diferentes productos, que a su vez tienen una serie de características: código de etiquetas
producto, tipo de artículo, sección. Una tienda virtual se describiría en un fichero como el siguiente • Templates
[Link] múltiples

<?xml version="1.0" encoding='ISO-8859-1'?>

<?xml-stylesheet href="[Link]" type="text/xsl"?>

<tienda>
<nombre>La tiendecilla </nombre>
<telefono>953 87 12 23 </telefono>

<producto>
<codigo>92 </codigo>
<cantidad>10 </cantidad>
<articulo>Radio-Casette </articulo>
</producto>
<producto>
<codigo>103 </codigo>
<cantidad>50 </cantidad>
<articulo>Reloj Cocina </articulo>
</producto>
<producto>
<codigo>1312 </codigo>
<cantidad>3 </cantidad>
<articulo>Sofá </articulo>
</producto>
</tienda>

Este se transforma con la siguiente hoja XSLT [Link]:

5 <xsl:template match='/'>
6 <html>
7 <xsl:apply-templates />
8 </html>
9 </xsl:template>
11 <xsl:template match='tienda'>
12 <head><title><xsl:value-of select='nombre' /> (Generado por [Link])</title></head>
13 <body>
14 <h1><xsl:value-of select='nombre' /> </h1>
16 <h2>Teléfono: <xsl:value-of select='telefono' /> </h2>
18 <h2>Nuestros mejores productos </h2>
19 <table>
20 <tr><th>Código</th><th>Existencias</th><th>Artículo</th></tr>
21 <xsl:apply-templates select='producto' />
22 </table>
23 </body>
24 </xsl:template>
26 <xsl:template match='producto'>
27 <tr><xsl:apply-templates /></tr>
28 </xsl:template>
30 <xsl:template match='codigo|cantidad|articulo'>
31 <td><xsl:apply-templates /></td>
32 </xsl:template>

Esta hoja, a la que se le han suprimido los elementos comunes con la hoja anterior (comienzo y final), se
compone de cuatro templates diferentes, mientras que la anterior tenía solamente uno. Cada template trata
elementos de diferente profundidad dentro del árbol del documento XML: el primer template trataría la raíz, el
segundo las ramas que descienden de él, y el tercer y cuarto ramas progresivamente más bajas.

[Link] 29/05/2017
Tutorial de XSL Page 5 of 19

Por eso el primer template simplemente incluye el código de apertura y cierre del documento HTML, y
cede control al siguiente template, que trata la primera etiqueta, tienda, tal como aparece en el atributo match.
En este template se incluyen dentro del patrón en HTML el nombre y al telefono, usando xsl:value-of, que
simplemente incluye el contenido del elemento correspondiente. También se crea el esqueleto de una tabla en
HTML (líneas 19 en adelante), con su cabecera, y cede control al siguiente template, que se encargará de cada
uno de los productos; para que se procesen sólo las etiquetas de este tipo que desciendan de tienda, y no las
otras (nombre, telefono), que ya están incluidas en la salida, se usa el atributo select (línea 21): con xsl:apply-
templates select='producto' se aplicarán sólo los templates que correspondan a este elemento.

Ese template comienza en la línea 26 y crea el esqueleto de una fila, cediendo el control a los templates
que traten con los descendientes. Hay un sólo template que lo hace, el que comienza en la línea 30; en vez de
procesar un sólo tipo de elemento, procesa 3, y para ello usamos | para indicar que puede procesar cualquiera
de ellos, incluyéndolos dentro de un demarcador de celda de tabla en HTML

El orden en el que se incluyen los elementos en la salida es el mismo en el que se encuentran en la


entrada, es lo que se denomina orden de documento. Este orden se puede alterar usando etiquetas value-of
adecuadamente y usando otros métodos, que veremos a continuación.

Ejercicios 3
1. Crear un documento para una clasificación de equipos de fútbol en XML, y transformarlo mediante XSLT en
una tabla HTML, con cada equipo en una fila, diferentes valores (puntuación, goles a favor y en contra) en
columnas, con el nombre del equipo en negrita.

5 Procesando documentos XML completos Contenido de


esta sección
• Atributos
El XML es infinito, y tiene muchas más cualidades. Para empezar, los elementos pueden tener
• Bucles
atributos, que se añaden dentro de la etiqueta para cualificarla <elemento atributo1='valor1'
atributo2='valor2' />; en este sentido, funciona igual que el HTML, pero los atributos tienen que ir siempre entre
comillas (simples o dobles). De la misma forma, cuando un elemento se repite varias veces, y hay que hacer
algo diferenciado con cada una de ellas, conviene tener a mano bucles. Ambas estructuras las pondremos en
práctica sobre el siguiente ejemplo [Link] (que se muestra incompleto, porque es un rato largo):
<tienda>
<nombre>La tiendecilla </nombre>
<telefono>953 87 12 23 </telefono>
<url etiqueta="URL: ">[Link] </url>
<url prefijo="[Link] etiqueta="Informacion: ">info@[Link] </url>
<producto>
<codigo>92 </codigo>
<cantidad>10 </cantidad>
<articulo>Radio-Casette </articulo>
<seccion>Electrónica </seccion>
<marca>Sony </marca>
<modelo>MKJ-800 </modelo>
<caracteristicas>
<linea>Auto-reverse </linea>
<linea>Dolby-sorround </linea>
<linea>Doble pletina </linea>
<linea>Ecualizador de cinco bandas </linea>
<linea>Garantía de 9 meses. </linea>
</caracteristicas>
<precio moneda="euro">90 </precio>
</producto>
<producto>
<codigo>103 </codigo>
<cantidad>50 </cantidad>
<articulo>Reloj Cocina </articulo>
<seccion>Electrónica </seccion>
<marca>Kenwood </marca>
<modelo>Blue ONE </modelo>
<caracteristicas>
<linea>Varios diseños </linea>
</caracteristicas>
<opciones nombre="color" tipo="unica">
<opcion valor="rojo"/>
<opcion valor="azul"/>
<opcion valor="blanco"/>
</opciones>
<opciones nombre="forma" tipo="unica">
<opcion valor="cuadrado"/>
<opcion valor="triangular"/>
<opcion valor="redondo"/>
<linea>Garantía de 6 meses. </linea>
</opciones>
<precio moneda="euro">12 </precio>
</producto>
<!-- Más cosas por aquí... -->
</tienda>

Este catálogo lo podemos presentar directamente como un formulario HTML, usando la hoja de estilo
siguiente: ([Link]; sólo están las líneas que difieren de los ejemplos anteriores)

[Link] 29/05/2017
Tutorial de XSL Page 6 of 19

11 <xsl:template match='tienda'>

18 <xsl:for-each select='url' >


19 <xsl:value-of select='@etiqueta' />
<a href='{@prefijo}{.}'>
<xsl:value-of select='.' /></a> <br />
20 </xsl:for-each>
21 <h2>Nuestros mejores productos </h2>
22 <table border='1' borderwidth='2'>

37 <xsl:template match='caracteristicas'>
38 <td><ul>
39 <xsl:for-each select='linea'>
40 <li><xsl:value-of select='.' /></li>
41 </xsl:for-each>
42 </ul></td>
43 </xsl:template>
44
45 <xsl:template match='opciones'>
46 <td><xsl:value-of select='@nombre' /><select>
47 <xsl:for-each select='opcion'>
48 <option><xsl:value-of select='@valor' /></option>
49 </xsl:for-each>
50 </select></td>
51 </xsl:template>
52
53 <xsl:template match='precio'>
54 <td>Precio: <xsl:value-of select='.' /> <xsl:value-of select='@moneda' />s </td>
55 </xsl:template>
56
57 </xsl:stylesheet>
Si todavía no sabes lo que es un XPath, esta
En la línea 18 (la tercera del ejemplo) aparece la primera estructura nueva: es una ocasión tan buena como otra
xsl:for-each, que realiza un bucle sobre una serie de elementos que cumplan la cualquiera. Se trata de una forma de
condición que pone en el atributo select; en este caso, todos los elementos url expresar o seleccionar de forma única nodos
que desciendan del contexto actual (estamos al nivel de la etiqueta tienda). En o grupos de nodos de un árbol DOM que
este atributo se puede incluir cualquier XPath que dé como resultado un node- represente a un documento XML. Hay un
set, y se ejecutará una vez por cada elemento del mismo. Por ejemplo, si excelente tutorial que explica qué tipos de
pusiéramos <xsl:for-each select='producto'> se ejecutaría una vez por cada nodos hay, y cómo expresar un nodo
producto, exactamente a como se hace arriba con xsl:apply-templates (en determinado.
realidad, para lo que sabemos en este punto del tutorial, son prácticamente
iguales).

Justamente dentro del bucle usamos atributos; en realidad, forman parte de la definición de XPath y no
tienen mucha historia: para usar un atributo, se le pone la arroba delante y punto. En este caso, se ponen las
llaves alrededor para separar el atributo del valor del elemento que se está procesando (., en la línea 19). Las
características y opciones se procesan de manera análoga: se ejecuta un bucle para cada uno de los
subelementos, generando elementos de una lista en un caso, y opciones de un formulario en otro caso.

Ejercicios 4
1. Hacer el ejercicio anterior, usando atributos para alguna de las cantidades.

6 Generando contenido dinámicamente Contenido de esta


sección
• Parámetros:
Si sólo se pudieran generar páginas estáticas, poco habríamos ganado con respecto al HTML; la xsl:param
gracia del binomio XML/XSLT es que se puede generar contenido diferente dependiendo de las • Decisiones:
xsl:when
entradas. Para ello debe haber alguna forma de pasarle parámetros a las hojas, y eso se hace, cómo
si no, con la orden xsl:param. A la vez, teniendo en cuenta las entradas, habrá que tomar decisiones; o quizás
dependiendo de los atributos. Cambiaremos la hoja de estilo anterior para que liste sólo productos de una
sección, y tomaremos decisiones sobre qué poner dependiendo de los valores de atributos: ( tiendecilla-
[Link]; mostramos como de costumbre sólo las líneas relevantes)

4
5 <xsl:param name='seccion' />

16 <h1><xsl:value-of select='nombre' /> Sección : <xsl:value-of select='$seccion' />


17 </h1>

27 <xsl:apply-templates select='producto[seccion=$seccion]' />

48 <xsl:template match='opciones'>
49 <td><xsl:value-of select='@nombre' />
50 <xsl:choose>
51 <xsl:when test='@tipo="unica"' >
52 <select>
53 <xsl:for-each select='opcion'>
54 <option><xsl:value-of select='@valor' /></option>
55 </xsl:for-each>
56 </select>
57 </xsl:when>
58 <xsl:when test='@tipo="si_no"'>

[Link] 29/05/2017
Tutorial de XSL Page 7 of 19

59 : <xsl:value-of select='opcion/@valor' /> <input type="checkbox" />


60 </xsl:when>
61 </xsl:choose>
62 </td>
63 </xsl:template>

Para usar esta hoja pasándole parámetros desde la línea de órdenes, habrá que hacerlo así (usando
saxon):

java [Link] [Link]


[Link] seccion='Muebles'

o bien, usando Xalan (para más información, mirar las instrucciones

java [Link]
-IN [Link]
-XSL [Link]
-PARAM seccion Muebles
-OUT [Link]

Si se usa la hoja de estilo dentro de un entorno de publicación tal como el Cocoon, habrá que pasarle los
parámetros al documento XML, bien directamente desde el URL o desde un formulario, algo así:
[Link] En Mozilla/Firefox y otros navegadores debería
funcionar algo similar, pero no funciona. Si alguien encuentra como se hace, que avise.

En cualquier caso, el resultado será una página que incluirá solamente los productos correspondientes a
una sección.

El truco para hacer esto está en los primeros templates. Para empezar, XSLT es bastante idiosincrático, y
no puede recoger los parámetros que se le pasan a no ser que se declare un parámetro interno, y se le asigne el
nombre. Este parámetro es similar a las variables de los lenguajes de toda la vida, salvo que no se le puede
cambiar el valor: una vez que se le asigna uno al principio, se queda con él; el ámbito del parámetro será toda
la hoja, y mientras se esté ejecutando. Eso se hace en la línea 5; posteriormente, en la línea 16 se usa el valor
de la variable en una sentencia xsl:value-of; para acceder a su valor, se usa $seccion.

En la línea 27 se usan los predicados de XPath para seleccionar sólo aquellos nodos en los que el
elemento seccion tenga el mismo valor que la variable; en este atributo se puede usar cualquier XPath,
incluyendo este tipo de decisiones; conocer XPath y usarlo con sabiduría nos puede ahorrar un montón de
código.

Para tomar decisiones (más que para seleccionar) un poco más complejas, con diferentes opciones, XSLT
incluye las órdenes xsl:choose/xsl:when, que se usan conjuntamente (como el switch/case en C), tal como se ve
en la línea 53. En este caso se usa para seleccionar diferente presentación, dependiendo del valor del atributo
tipo; en caso de que sea "unica" usamos unos menuses, mientras que si es "si_no" usamos una "checkbox", que
se pueda pulsar o no dependiendo de la opción.

Ejercicios 5
1. Cambiar la clasificación, de forma que se usen sólo los equipos que tengan una puntuación mayor que una
dada, que se pase como parámetro.
2. Cambiar la clasificación, de forma que aparezcan en una tabla los tres primeros con un color, y los siguientes
con un color diferente. Usar expresiones XPath para seleccionarlos o <xsl:number>; usar si es necesario
una variable para establecer el color.

7 Alterando la salida Contenido de esta


sección
• Seleccionando
Un documento XML puede llevar asociadas diferentes hojas de estilo, y el propio sistema de
hojas de
publicación (tal como el cocoon) se encargará de seleccionarla dependiendo del navegador que use estilo
el cliente. Por ejemplo, se puede añadir esta línea a un fichero XML tal como este: • xsl:sort
• Diferentes
<?xml-stylesheet href="[Link]" type="text/xsl" media="lynx"?> modos de
invocar los
templates
En este caso, Cocoon
usará la hoja de estilo
[Link] cuando
el navegador sea el Lynx.
Esta hoja de estilo está
bastante más simplificada
que la anterior, dando un
código HTML más simple y
visible en modo texto. En
el Lynx, se vería como
aparece en la imagen.

¿Qué ocurre si
queremos sacar los
resultados por orden
alfabético, en vez del mismo orden que en el documento? Habrá que usar una nueva opción de apply-templates,
sort. Por ejemplo, si queremos formatear el siguiente fichero XML ([Link]):

[Link] 29/05/2017
Tutorial de XSL Page 8 of 19

<raiz>
<cosa>Pepe </cosa>
<cosa>Juan </cosa>
<cosa>Enrique </cosa>
<cosa>Xabier </cosa>
<cosa>Aarón </cosa>
</raiz>

Se puede hacer con la siguiente hoja de estilo ([Link]), de la cual extraemos solo las órdenes
pertinentes:

11 <xsl:apply-templates select='cosa'>
12 <xsl:sort select='.' data-type='text'/>
13 </xsl:apply-templates><br />

El resultado se puede ver en el fichero [Link]. En este caso, en vez de aplicar la orden apply-
templates en un solo tag "vacío" (con el / al final) se aplica en forma de tag y antitag, con las opciones en medio.
La opción xsl:sortsirve para ordenar, y como clave de ordenación se puede usar cualquier atributo, XPath, o en
este caso, el contenido en sí de la etiqueta cosa. En la salida, saldrán ordenados, Aarón primero y Xabier el
último. El atributo data-type sirve para indicar el criterio de ordenación,< code>text para texto y number para
ordenación numérica.

Todavía se puede cambiar un poco más el sistema: a veces resulta que uno quiere procesar de forma
diferente un elemento, dependiendo de la entrada. Meter decisiones puede ser un poco coñazo, así que el propio
estándar XSL tiene la forma de hacerlo: usando modos, tal como se hace en la siguiente y bonita hoja de estilo
([Link]):

1 <?xml version="1.0" encoding='ISO-8859-1'?>

2
3 <xsl:stylesheet version="1.0" xmlns:xsl="[Link]
4
5 <xsl:param name='modo' />
6 <xsl:output encoding='iso-8859-1' />
7 <xsl:template match='raiz'>
8 <xsl:processing-instruction name="cocoon-format">type="text/html"</xsl:processing-instruction>
9 <html>
10 <head><title>Ordenando</title></head>
11 <body>
12 Mode: <xsl:value-of select='$modo' />
13 <ol>
14 <xsl:choose>
15 <xsl:when test='$modo = verbose'>
16 <xsl:apply-templates select='cosa' mode='verbose'>
17 <xsl:sort select='.' data-type='text'/>
18 </xsl:apply-templates><br />
19 </xsl:when>
20 <xsl:otherwise>
21 <xsl:apply-templates select='cosa' mode='normal'>
22 <xsl:sort select='.' data-type='text'/>
23 </xsl:apply-templates><br />
24 </xsl:otherwise>
25 </xsl:choose>
26 </ol>
27 </body>
28 </html>
29 </xsl:template>
30
31 <xsl:template match='cosa' mode='normal'>
32 <li><xsl:value-of select='.'/></li>
33 </xsl:template>
34
35 <xsl:template match='cosa' mode='verbose'>
36 <li>Nombre: <xsl:value-of select='.'/></li>
37 </xsl:template>
38
39 </xsl:stylesheet>

En esta hoja de estilo se usa el atributo mode al llamar y al definir un template; los nombres que le hemos
asignado son arbitrarios, pero lo que hacen es que, en caso de que se le pase como parámetro "verbose"
imprimirá "nombre" delante del nombre de la persona; si no, lo imprimirá como antes. Para que funcione, se
toma una decisión (a partir de la línea 14): en caso de que el modo sea "verbose", se llama al template usando
como atributo de modo esa palabra; en otro caso, se llama al template "normal". Ese código tiene el efecto de
que se llame a un template o a otro, según el modo que se haya elegido.

Pero claro, esto se puede resolver, en este caso, de una forma mucho más simple. ¿No sería ideal que se
pudiera llamar a un template con parámetros, como si de una subrutina se tratara? Pues sí, se puede, tal como
se hace en la hoja siguiente ([Link]):

[Link] 29/05/2017
Tutorial de XSL Page 9 of 19

6 <xsl:output encoding='iso-8859-1' />


7 <xsl:template match='raiz'>
8 <html>
9 <head><title>Ordenando 3</title></head>
10 <body>
11 Mode: <xsl:value-of select='$modo' />
12 <ol>
13 <xsl:apply-templates select='cosa'>
14 <xsl:with-param name='miModo' select='$modo' />
15 <xsl:sort select='.' data-type='text'/>
16 </xsl:apply-templates><br />
17 </ol>
18 </body>
19 </html>
20 </xsl:template>
21
22 <xsl:template match='cosa'>
23 <xsl:param name='miModo' />
24 <li><xsl:choose><xsl:when test='$miModo = "verbose"'>Nombre: </xsl:when></xsl:choose>
25 <xsl:value-of select='.'/></li>
26 </xsl:template>
27
28 </xsl:stylesheet>

La principal diferencia con los dos anteriores está en la línea 14: la orden xsl:with-param hace que se llame
al template con un parámetro determinado, cuyo nombre y valor queda establecido por los atributos. En este
caso, estamos asignándole al parámetro miModo el mismo valor que el del parámetro modo (y por eso es
innecesario, peor admitámoslo por mor de la pedagogía). Ese parámetro se recibe dentro del template con una
sentencia similar a la que se usa para los parámetros globales: xsl:param; si el parámetro no se declara aquí, al
principio del template, XSL no le hará ni puto caso.

Y ya dentro del template, usamos una decisión, como las que se han visto anteriormente, para imprimir el
introito a cada nombre en caso de que el modo sea el adecuado. Y aquí paz y después gloria.

Ejercicios 6
1. Cambiar el programa de procesamiento del XML de los equipos de fútbol, de forma que salgan ordenados por
orden de puntuación (se supone que el original puede estar desordenado), o por orden alfabético, dependido de
un parámetro.
2. Añadir modos a la hoja de procesamiento de las quinielas, de forma que, en un modo, salga en forma de tabla,
y en otro modo, en forma de lista ordenada.
3. Cambiar la hoja de procesamiento de las quinielas, de forma que cada fila aparezca con un color diferente.

8 Clamando al cielo Contenido de esta sección


• Llamando a
templates
Como era de esperar, el jefe no está contento; ya que el tema de las quinielas está explícitamente
agotado, vamos a por las encuestas. Y la encuesta hay que hacerla medianamente bien, • Usando recursividad
poniendo diferentes elementos de formularios, y no dejando que el usuario conteste lo que • xsl:call-
template/xsl:param/xsl:with-
le dé la gana. Usando el fichero [Link], habría que aplicar la siguiente hoja
param/xsl:if, variables
([Link]): • Usando extensiones
de XSL en el
61 <xsl:when test='@tipo="numero"'> procesador Saxon
62 <tr>
63 <td colspan ='2' width="100%" bgcolor="white">
64 <select name='numero'>
65 <xsl:call-template name='option-range'>
66 <xsl:with-param name='range' select='@rango'/>
67 </xsl:call-template>
68 </select>
69 </td>
70 </tr>
71 </xsl:when>

115 <xsl:template name='option-range'>


116 <xsl:param name='range' />
117 <xsl:param name='i'>0</xsl:param>
118 <xsl:if test='$range != $i'>
119 <option><xsl:value-of select='$i' /></option>
120 <xsl:call-template name='option-range'>
121 <xsl:with-param name='range' select='$range'/>
122 <xsl:with-param name='i' select='$i+1'/>
123 </xsl:call-template>
124 </xsl:if>
125 </xsl:template>
126 </xsl:stylesheet>

Como siempre, aquí está la salida. Se han puesto las líneas que introducen elementos nuevos solamente.

La principal complicación de este tipo de problemas, que se resuelven fácilmente con un bucle for en
cualquier lenguaje de programación pachanguero, en lenguajes funcionales pueden ser un poco más
complicados. Por eso, muchos procesadores de XSL tienen extensiones que permiten hacer bucles
convencionales, como veremos más adelante.

El principal problema es que, dado que no se pueden actualizar variables por la ausencia de efectos
secundarios, no se puede crear un bucle que vaya comprobando el valor de una variable y actualizándolo en

[Link] 29/05/2017
Tutorial de XSL Page 10 of 19

cada iteración. La única solución es sustituir los bucles clásicos por bucles recursivos, en los cuales se llama
recursivamente a una subrutina (en este caso, template) hasta que se cumple una condición.

En este caso, vamos a incluir una etiqueta select y sus correspondientes option, una para cada uno de las
opciones que haya. Y no tenemos más remedio que llamar a una rutina recursivamente. Eso se hace en la línea
65. En este caso en vez de dejar que los templates se disparen según los valores de una etiqueta, lo llamamos
explícitamente con la orden xsl:call-template. Y dado que se trata de una especie de subrutina o procedimiento,
hay que llamarlo también con sus correspondientes parámetros, para lo cual se usa xsl:with-param. Es decir, las
siguientes órdenes

<xsl:call-template name='option-range'>
<xsl:with-param name='range' select='@rango'/>
</xsl:call-template>

corresponderían en cualquier otro lenguaje de programación a option-range( range ).

De la misma forma, la "declaración" de un template es un tanto peculiar (línea 115):

<xsl:template name='option-range'> <xsl:param name='range' /> <xsl:param


name='i'>0</xsl:param>

Esto correspondería a algo así como void function option-range(var range, var i=0), es decir, declaración
de dos variables, una de las cuales tiene un valor por defecto, el 0, y otra sin valor por defecto, que tiene que
ser dado por el usuario.

El resto de ese template, a partir de la línea 118, comprueba si el range es distinto al contador que
usamos, i, y si lo es, imprime las etiquetas HTML, y vuelve a llamarse recursivamente, incrementando el
contador. Cuando range y i sean iguales, la recursión para.

En este template se usan también variables, las que se pasan como parámetro. Las variables, aunque no
lo son en el sentido clásico, se pueden actualizar dentro de un template, asignársele valor y pasar como
parámetro a otros templates; para asignarles valor se puede usar esta construcción:

<xsl:param name='i'>0</xsl:param>

o bien con esta, que es equivalente

<xsl:param name='i' select='0' />

En ambos casos se le asignaría el valor 0 a la variable


i. Para recuperar el valor de la variable i
se usa con el $ delante, de esta forma $i. Por ejemplo,
si queremos asignar a una variable el valor de otra, se podría hacer
de dos formas:

<xsl:param name='i' select='$j'>


<xsl:param name='i'>{$j}<xsl:param>

En el segundo caso, las llaves indican que, a pesar de encontrarse


la variable fuera de una etiqueta XSL, debe ser evaluada.

Las variables y parámetros se declaran sin tipo: pueden contener


una cadena, un node-set, o un resulting tree fragment, que se puede
convertir en una cadena, pero no en un node-set; según el contexto, se
usarán como conjuntos de nodos, árboles o cadenas. La transformación a
cadenas se hace automáticamente, pero hacerlo al revés es bastante
fastidiado. Algunos procesadores incluyen extensiones que permiten

También se usa la orden xsl:if, cuyo significado es


similar a cualquier otro lenguaje. Si la condición que se le pasa en
el atributo test es cierta, se incluye en la salida el
fragmento correspondiente; si no, no se hace nada. Como no tiene nada
parecido al "else", si hay más de una opción, lo mejor es usar
xsl:when en tal caso.

[Link] 29/05/2017
Tutorial de XSL Page 11 of 19

En resumen, con esta hoja de estilo se obtiene una página HTML ([Link]) similar a la
anterior, salvo que las respuestas de valor numérico se seleccionan a
través de un menú.

Y como evidentemente hacer las cosas así puede convertirse en un


poco pesado, algunos procesadores como el Saxon lo solucionan a base
de extensiones, es decir, etiquetas propias, tal como se muestra en el
ejemplo [Link]. En este
caso, se tiene que añadir al principio del fichero una declaración de
espacio de nombres y de prefijo:

<xsl:stylesheet version="1.0"
xmlns:xsl="[Link]
xmlns:saxon="[Link]
extension-element-prefixes="saxon">

y con esa declaración (y lo necesario para usar Saxon, que se ha


explicado anteriormente), se puede incluir el menú de la forma
siguiente:

<xsl:for-each select='saxon:range(0,@rango)'>
<option><xsl:value-of select='.' /></option>
</xsl:for-each>

Esta construcción saxon:range equivale a un bucle que se ejecuta desde 0 hasta


el número indicado en el atributo rango
(@rango). Con esto, nos ahorramos toda la historia de la
recursión y todo eso. Y el resultado es exactamente el mismo. En
realidad lo que hace es que crea un conjunto de nodos, cada uno de los
cuales tiene un valor en el rango indicado; pero qué se le va a hacer,
es la forma de hacer las cosas. El problema de usar estas extensiones
es que solamente funcionan con el procesador que las implementa, no
con el resto. Una construcción usando elementos estándar XSL
funcionará, teóricamente, en cualquier procesador. En realidad, la
orden xsl:for-each la veremos más adelante.

Ejercicios

1. Hacer un template que sume números desde 1 hasta el número


indicado. Por ejemplo, si se le llama con el 10, sumará todos los
números de 1 a 10. El número se pasará en el atributo de una etiqueta
XML. Hacerlo usando recursión primero, y luego
usando extensiones del procesador XSLT.

Contenido
de esta
sección
• Funciones
XPath
9 Funciones y bucles • xsl:variable
• Bucles y
node-
sets

El jefe ya está un poquitín más contento, la encuesta sale chuli y


tal, pero, puntilloso como siempre, nos indica que toda encuesta que
se precie tiene los numeritos de la pregunta delante de las preguntas
mismamente. De nada sirve explicarle la ausencia de bucles for (o casi
ausencia) en XSLT. Si hay que poner numeritos, hay que poner
numeritos. Además, la encuesta tal cual tiene buena pinta, pero en

[Link] 29/05/2017
Tutorial de XSL Page 12 of 19

realidad no sirve para nada, porque cada campo no tiene nombre propio
ni nada de eso. O sea, que hay que ponerle nombre propio, para poder
procesarlo de verdad como un formulario. Como el jefe no dice que haya
que hacerlo de verdad, ya veremos como lo haremos luego. Y hacemos la
siguiente hoja de estilo ([Link]),
de la cual ponemos sólo los sitios que más han cambiado.:

59 <xsl:template match="cuestion">
60 <p><br/></p>
61 <table border="0" width="90%" bgcolor="#000000" cellspacing="0" cellpadding="0">
62 <tr>
63 <td width="100%">
64 <table border="0" width="100%" cellpadding="4">
65 <tr>
66 <td width="100%" colspan='2' bgcolor="#e0e0e0">
67 <big> <xsl:value-of select="pregunta"/></big>
68 </td>
69 </tr>
70 <xsl:choose>
71 <xsl:when test='@tipo="multiple"'>
72 <xsl:variable name='pos' select='position()' />
73 <xsl:variable name='varios' select='@varios' />
74 <xsl:for-each select='.//respuesta'>
75 <tr>
76 <td width="100%" bgcolor="white">
77 <xsl:value-of select='position()' />. <xsl:value-of select='.' />
78 </td>
79 <td width="100%" bgcolor="white">
80 <xsl:choose>
81 <xsl:when test='$varios=1'>
82 <input type='radio' name='radio{$pos}' />
83 </xsl:when>
84 <xsl:otherwise>
85 <input type='checkbox' name='cb{$pos}' />
86 </xsl:otherwise>
87 </xsl:choose>
88 </td>
89 </tr>
90 </xsl:for-each>
91 </xsl:when>
92 <xsl:when test='@tipo="numero"'>
93 <tr>
94 <td colspan ='2' width="100%" bgcolor="white">
95 <select name='{concat("select",position())}'>
96 <xsl:call-template name='option-range'>
97 <xsl:with-param name='range' select='@rango'/>
98 </xsl:call-template>
99 </select>
100 </td>
101 </tr>
102 </xsl:when>
103 <xsl:when test='@tipo="rollete"'>
104 <tr>
105 <td colspan='2' width="100%" bgcolor="white">
106 <input type='text' name='{concat("radio",position())}'/>
107 </td>
108 </tr>
109 </xsl:when>
110 <xsl:when test='@tipo="bool"'>
111 <tr>
112 <td bgcolor="white">
113 Si
114 </td>
115 <td bgcolor="white">
116 <input type='radio' name='{concat("radio",position())}'/>
117 </td>
118 </tr>
119 <tr>
120 <td bgcolor="white">
121 No
122 </td>
123 <td bgcolor="white">
124 <input type='radio' name='{concat("radio",position())}' />
125 </td>
126 </tr>
127 </xsl:when>
128 </xsl:choose>
129 </table>
130 </td>
131 </tr>
132 </table>
133 </xsl:template>

Los resultados se pueden ver en forma de


página.. En cualquier caso, una de las
estructuras nuevas (o casi) está en la línea 74:<xsl:for-each
select='.//respuesta'>, que introduce la orden
xsl:for-each. Esta orden es lo más parecido a un bucle
que tiene XSLT: realiza el código que le sigue (hasta el antitag
correspondiente) aplicándolo una vez por cada nodo del
node-set incluido en el atributo select. En este
caso, usa un XPath que indica que se tienen que coger todos los tags
respuesta que desciendan del tag actual (.),

[Link] 29/05/2017
Tutorial de XSL Page 13 of 19

sean o no descendientes directos; aunque en este caso son todos


descendientes directos; en este caso, serán todas las respuestas
correspondientes a una pregunta determinada.

Previamente al bucle, en las líneas 72 y 73, se usa


xsl:variable, que es bastante parecido a
xsl:param hasta el punto que yo no sabría
diferenciarlas... En realidad, se diferencian en cómo se les puede
asignar un valor en el caso de que sean variables globales. A una
xsl:variable se le puede asignar cualquier valor fuera de
un template, pero a un xsl:param sólo se le puede asignar
valores externos, procedentes de parámetros con los que se llama a la
página. Además, las variables no se pueden usar para pasar valores a
templates. En lo que sí se diferencian ambos de las variables
"normales", es que su valor no se puede guardar entre una invocación y
otra de un template; si se quiere conservar el valor de una variable,
hay que llamar al template explícitamente. En este caso, usamos las
variables para tomar valores que son dependientes del contexto, la
posición y un atributo, que se pierden cuando se está procesando otro
tag.

También en la línea 77 se usa una función XPath, position(),


que devuelve la posición del nodo actual dentro del contexto que se
está procesando, es decir, en este caso, el número de orden de la
respuesta actual dentro de todas las respuestas que hay.

Las dos variables declaradas, varios y


pos, se usan más adelante. varios se usa
para generar diferentes tags HTML en el caso de que se permita
respuestas múltiples (una novedad en esta hoja), o si no se permiten;
en el primer caso se usarán checkboxes, y en el segundo
botones de radio (se podía haber usado en ambos casos una combo
box con la opción múltiple o no, pero bueno...). El nombre de
los elementos del formulario se halla concatenando un prefijo tal como
"cb" o "radio" a la posición de la pregunta en el contexto,
multiplicada por dos (porque en realidad, procesamos uno de cada dos
nodos). En todo caso, consigue lo que nos interesa: que cada elemento
del formulario tenga un nombre único.

En la línea 95 se usa otra función XPath, concat, que


aunque en realidad, que nos permite concatenar la posición del nodo al
prefijo. Algo similar se usa en la línea 106. concat es
una función que devuelve como salida una cadena que concatena todo lo
que se le meta como entrada.

Ejercicios

1. A partir de un fichero XML con los equipos de fútbol tales como los
que se han usado en ejercicios anteriores, devolver otro fichero XML
que contenga sólo los equipos que tengan más goles a favor que en
contra.

2. A partir de un fichero XML con direcciones tales como los


que se han usado en ejercicios anteriores, devolver sólo aquellos cuyo
número de teléfono comience por 958. Usar la función contains.

Contenido de
esta sección
• Procesando
con XSL

[Link] 29/05/2017
Tutorial de XSL Page 14 of 19

10 Procesando información como si


fuera un
CGI

• Algunas
extensiones
En fin, que el jefe que dice que vale, que el formulario está Xalan
para
perfecto, pero a ver, tanto XML y tanta gaita gallega, pero al final escribir
el formulario habrá que procesarlo usando PERL o algún otro lenguaje ficheros, y
serio. Así que, para demostrarle que no tiene razón, tendremos que lo mismo
procesar también el formulario usando XSLT, aunque sea nada más que en
por eso. Y lo hacemos sobre el siguiente fichero de encuesta ([Link]): XSLT 1.1

<encuesta>

<cuestion tipo='multiple'>

<pregunta>¿Eres un listo? </pregunta>

<respuesta>Si </respuesta>

<respuesta>No </respuesta>

<respuesta>Lo que diga mi señora </respuesta>

<respuesta>La gallina </respuesta>

</cuestion>

<cuestion tipo='multiple'>

<pregunta>¿Porque pierdes tu tiempo contestando encuestas? </pregunta>

<respuesta>Porque no tengo nada mejor que hacer </respuesta>

<respuesta>Porque me lo ha dicho mi señora </respuesta>

<respuesta>A tí te lo voy a decir, so listo </respuesta>

<respuesta>La gallina </respuesta>

</cuestion>

<cuestion tipo='multiple'>

<pregunta>¿Cómo considera la coyuntura actual de la mejora de las


prestaciones en orden a una europeización más completa? </pregunta>

<respuesta>Epatante </respuesta>

<respuesta>No contestaré a preguntas excluyentes </respuesta>

<respuesta>La considero positivante y conducente a unas relaciones más


normalizadas con el conjunto de los agentes socioeconómicos </respuesta>

<respuesta>La gallina </respuesta>

</cuestion>

</encuesta>

Esta encuesta la procesaremos con la siguiente hoja de estilo ([Link]), de la cual sólo mostramos las
líneas en las que se diferencia con la anterior:

1 <?xml version="1.0" encoding='ISO-8859-1'?>

2
3 <xsl:stylesheet version="1.0"
4 xmlns:xsl="[Link]
5 xmlns:redirect='[Link]'
6 extension-element-prefixes="redirect">
7
8 <xsl:param name='radio2'></xsl:param>
9 <xsl:param name='radio4'></xsl:param>
10 <xsl:param name='radio6'></xsl:param>
11
12 <xsl:template match='/'>
13 <xsl:choose>
14 <xsl:when test="$radio2">
15 <xsl:call-template name='procesa-encuesta'>
16 </xsl:call-template>

[Link] 29/05/2017
Tutorial de XSL Page 15 of 19

17 </xsl:when>
18 <xsl:otherwise>
19 <xsl:apply-templates />
20 </xsl:otherwise>
21 </xsl:choose>
22 </xsl:template>
23
24 <xsl:template name="procesa-encuesta">
25 <xsl:processing-instruction name="cocoon-format">type="text/html"</xsl:processing-instruction>
26 <redirect:write select='"/tmp/[Link].1"'>
27 Resultados:
28 <xsl:value-of select='$radio2' /> -
29 <xsl:value-of select='$radio4' /> -
30 <xsl:value-of select='$radio6' />
31 </redirect:write>
32 <html>
33 <head>
34 <title>Procesando encuesta</title>
35 </head>
36 <body>
37 <h1>Procesando encuesta</h1>
38
39 <table border="0" width="80%" bgcolor="#000000" cellspacing="0" cellpadding="0">
40 <tr>
41 <td width="100%">
42 <table border="0" width="100%" cellpadding="4">
43 <tr>
44 <td width="100%" bgcolor="#c0c0c0" align="right">
45 <big><big>Encuesta chuli</big></big>
46 </td>
47 </tr>
48 <tr>
49 <td width="100%" bgcolor="#ffffff" align="center">
50 <xsl:for-each select='.//cuestion'>
51 <table border="0" width="90%" bgcolor="#000000" cellspacing="0" cellpadding="0">
52 <tr>
53 <td width="100%">
54 <table border="0" width="100%" cellpadding="4">
55 <tr>
56 <td width="100%" bgcolor="#e0e0e0">
57 <big> <xsl:value-of select="pregunta"/></big>
58 </td>
59 <td width="100%" bgcolor="white">
60 <xsl:choose>
61 <xsl:when test='position()=1'> <xsl:value-of select='$radio2' /> </xsl:when>
62 <xsl:when test='position()=2'> <xsl:value-of select='$radio4' /> </xsl:when>
63 <xsl:when test='position()=3'> <xsl:value-of select='$radio6' /> </xsl:when>
64 </xsl:choose>
65 </td>
66 </tr>
67 </table>
68 </td>
69 </tr>
70 </table>
71 <p><br/></p>
72
73 </xsl:for-each>
74 </td>
75 </tr>
76 </table>
77 </td>
78 </tr>
79 </table>
80 </body>
81 </html>
82 </xsl:template>
83

En realidad, estamos haciendo trampa; lo cierto es que XSLT, sólo,


no puede realizar cosas tan potentes como un CGI o cualquier otro
método de procesamiento en el servidor, tales como los JSPs; XSLT está
enfocado sólo a transformaciones de documentos XML, y por eso, tenemos
que forzar un poco el estándar usando extensiones. En este caso, sería
mucho más adecuado usar XSP, por ejemplo, que permite incluir
programas en Java (u otro lenguaje) dentro de un documento XML, o
incluso las extensiones Xalan, que permiten incluir JavaScript dentro
del documento.

En este caso, si queremos generar la página usando Xalan, hay que


añadir una librería más al CLASSPATH:

export
CLASSPATH=$CLASSPATH:/usr/local/xalan-j_1_2_2/[Link]

(sustituyendo /usr/local/xalan... por dondequiera que


esté instalado Xalan). La librería que se añade es la que contiene el

[Link] 29/05/2017
Tutorial de XSL Page 16 of 19

Bean Scripting Framework, que permite usar diferentes lenguajes dentro


de la máquina virtual Java; las extensiones de Xalan están escritas
usando BSF, por eso hay que hacerlo. Y una vez hecho, se puede generar
la página siguiente ([Link]).

Por eso, para empezar, a partir de la línea 3, se tienen que


declarar las extensiones de Xalan en la declaración de la hoja de
estilo. En este caso se declara un namespace redirect,
que será el prefijo que usen las extensiones que se van a usar, y se
indica que corresponde a una clase determinada dentro del conjunto de
clases en Java que incluye Xalan. Estas extensiones se usarán más
adelante para poder escribir en disco desde una hoja de estilo.

Más adelante, en las líneas 8,9 y 10, se tienen que declarar los
parámetros del formulario que se van a usar. En este caso, el
formulario que se ha creado tiene 3 elementos: radio2, 4 y 6. A la
vez, se inicializan con un valor nulo; en la misma sentencia se le
podría asignar un valor por defecto, simplemente metiéndolo dentro de
los tags. En nuestro caso, no nos conviene, porque vamos a usarlo para
saber si el fichero XML se está procesando "de primeras" o no, o se
está procesando después de rellenar el formulario. Hay otra
alternativa a declarar esas variables, y es usar las taglibs
que vienen con el Cocoon; en concreto,
request:get-parameter-names. Una vez más, no son
universales, o sea que no van a funcionar en todos los sistemas,
aunque probablemente haya algo muy similar en el resto de los
sistemas.

Si se está usando Xalan desde la línea de comandos, se le pueden


incluir también los parámetros de la forma siguiente:

java [Link]
-in [Link] -xsl [Link] -out [Link]
-param radio2 3 -param radio4 5 -param radio6 3

que daría como salida un fichero HTML


([Link]), y a la vez crea el fichero de salida, como
veremos más adelante.

De hecho, eso es lo que se intenta dilucidar en las líneas a partir


de la 12. Esta hoja de estilo sirve a la vez para presentar la
encuesta en forma de formulario, y para procesar el formulario una vez
rellenado; y todo ello sobre el mismo documento XML y usando la misma
hoja de estilo XSLT. ¡Toma ya!

El template que comienza en la línea 12 comprueba si existe alguno


de los elementos del formulario; si existe, llama al template
procesa-encuesta, si no, aplica los templates de toda la
vida, empezando por el raíz.

Pasamos entonces al nuevo template, procesa-encuesta,


que para empezar, inserta en la salida la instrucción de siempre, que
le dice al Cocoon que tiene que servir la página como HTML, y luego
viene lo bueno: la instrucción específica de Xalan
redirect:write, que hace lo que es de esperar: escribe un
fichero con el nombre que se le pasa en el atributo
select. El nombre está entrecomillado para indicar que se
trata de una cadena, no de un XPath o algo peor; el fichero se
escribirá en el directorio /tmp, que está en todas las
distribuciones Unix con permisos de escritura. Pero, ojo, no quiero
decir que uséis esto en un entorno de producción: podría ser muy
peligroso. En tal caso sería mejor que usárais una base de datos, con

[Link] 29/05/2017
Tutorial de XSL Page 17 of 19

las autorizaciones adecuadas. En el fichero se escribe lo que hay


entre los dos tags, es decir, "Resultados " y el valor de los
parámetros. Saldrá algo así:

<?xml version="1.0" encoding="ISO-8859-1"?>

Resultados:
3 -
5 -
3

con su orden XML al principio y tó, tan mona. Si os dáis cuenta,


hemos tenido que hacer una verdadera chapuza: tenemos que poner de uno
en uno los valores de los parámetros; y además, solo admitimos un tipo
de parámetro, el más fácil de procesar. En realidad, lo cierto es que
XSLT no es tan potente, para este tipo de cosas, como un CGI, al menos
sin extensiones.

A continuación, a partir de la línea 50, imprimimos también cada


una de las preguntas y la respuesta correspondiente en la página HTML
que se muestra al usuario; usamos for-each y el XPath
.//cuestion, que forma un node-set con todas las
etiquetas cuestion que desciendan del nodo actual. Para
seleccionar la respuesta a esa pregunta que se va a imprimir, se hace
un truco un tanto sucio en la línea 60: con un
xsl:choose, se mira si la posición de la pregunta es la
primera, segunda o tercera, usando la función de XPath
position(), que ya hemos visto anteriormente, y se
selecciona el parámetro correspondiente. Y es una chapuza porque lo
suyo es que se carculara, pero es muy difícil convertir el contenido
de una variable en parte del nombre de un nodo, salvo que se usen
extensiones, así que lo dejamos como está.

En otros procesadores XSLT, habrá que usar otras alternativas. Y si


usamos un procesador XSL que siga la especificación XSLT 1.1, se puede
usar xsl:document de esta forma:

<xsl:document href="encuesta_resultados_s.1">
Resultados:
<xsl:value-of select='$radio2' /> -
<xsl:value-of select='$radio4' /> -
<xsl:value-of select='$radio6' />
</xsl:document>

La última versión de Saxon, usa esa orden. Probablemente, en


siguientes versiones de Xalan (y por tanto de Cocoon) se incluya
también. Para usar los parámetros desde Saxon, y obtener el
mismo resultado, hay que escribir

java [Link]
-o [Link] [Link]
[Link] radio2=3 radio4=6 radio6=1

Es decir, se le pasan los parámetros de la forma


parametro=valor y ya está. El resultado es exactamente el
mismo.

En realidad, lo más adecuado sería usar XSP, JSP o un servlet para


procesarla. Pero bueno, por lo menos hemos probado lo que se puede
intentar hacer.

[Link] 29/05/2017
Tutorial de XSL Page 18 of 19

Ejercicios

1. Sobre cualquier documento XML, hacer una hoja de estilo que tome
como parámetro un XPath y presente ese XPath del documento original.

2. Sobre una encuesta con el formato anterior, hacer una hoja de


estilo que tenga dos parámetros, el número de pregunta y el número de
respuesta, y escribir ese número de pregunta y respuesta. Habrá que
construir un XPath a partir de los parámetros.

3. A partir de un documento XML que contenga una tabla HTML, hacer una
hoja de estilo, que, según el valor de un parámetro, escriba sólo el
valor de la primera columna o sólo el contenido de la tabla, sin
etiquetas.

11 Bibliografía y enlaces relacionados con XSLT

Esta es la bibliografía que ha aparecido hasta el momento sobre el


tema, especialmente en castellano

• Hoja de estilos XSL, Linux Actual, Año 1, nº 15, segunda


época, p. 48, por Diego Berea y Marcos Paredes, una introducción
bastante sencilla que usa Xalan.

• Un sitio
bastante completo, con tutoriales de XSLT y de muchas otras cosas, que incluye páginas en las cuales se pueden
aplicar transformaciones XSLT sobre la marcha.

• El sitio de XSLT, que a veces no


va. Tiene todo: artículos, programas, tutoriales.

• Taller Web. Convertir XML en HTML utilizando XSLT En: [Link]


una introducción básica usando el motor XT.

• XSLT
Programmer's Reference, 2nd edition, por Michael Kay, un peazo de libro,
completo, que sirve como tutorial y como referencia
también. Imprescindible. Además,
ahora está actualizado a la
segunda edición, incluyendo la
versión 1.1 de XSLT.

• Professional XSL, de varios autores,


que es un poco más avanzado que el anterior, y está bastante bien para
aprender truquillos.

Hay también algunos tutoriales bastante buenos en inglés

• Un capítulo sobre XSLT, parte


de un la Biblia de XML. Si sólo tienes tiempo para un tutorial en
inglés, después del que estás leyendo, que sea este.

[Link] 29/05/2017
Tutorial de XSL Page 19 of 19

• Un sitio
bastante completo, con tutoriales de XSLT y de muchas otras cosas, que incluye páginas en las cuales se pueden
aplicar transformaciones XSLT sobre la marcha.

• El sitio de XSLT, que a veces no


va. Tiene todo: artículos, programas, tutoriales.

• El resto, lo puedes ver en una lista de punteros, con artículos, libros y tutoriales.

Este tutorial es (c) Juan J. Merelo Guervós. Se podrá reproducir en todo o en parte, siempre que se mantenga un enlace al sitio original.

[Link] 29/05/2017

También podría gustarte