EL ELEMENTO XSL:SORT

Este elemento se emplea para establecer un orden para los "node-sets". Se puede utilizar en combinación con "apply-templates" y "for-each". Para el ejemplo anterior, podríamos aplicar la siguiente hoja de estilos:

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html> <head> <title> Vehículos descartados </title> </head> <body> <h2> Listado de vehículos</h2> <xsl:apply-templates select="/vehículos/vehículo"> <xsl:sort select="@kilometraje"/> </xsl:apply-templates> </body> </html> </xsl:template> <xsl:template match="vehículo"> <h3><xsl:value-of select="@kilometraje"/></h3> <ul> <xsl:for-each select="característica"> <xsl:sort select="." order="descending"/> <li><xsl:value-of select="."/></li> </xsl:for-each> </ul> </xsl:template> </xsl:stylesheet>

Si probamos este ejemplo, podremos observar algo: el orden del kilometraje se ha establecido por orden alfabético, cuando lo normal es que lo quiera ordenar numéricamente. Para eso, podemos usar el atributo "data-type", del siguiente modo:

<xsl:sort select="@kilometraje" data-type="number"/>

Este atributo, puede tener los valores "text", "number", o "qname" (qname se refiere a tipos definidos por el usuario), siendo por defecto "text".

MODOS

Hasta ahora, cuando hemos utilizado un elemento "apply-templates", lo hemos relacionado con un "template", para lo cual, hacíamos corresponder el atributo "select" de "apply-templates" con el ateributo "match" de "template". No hemos tenido ambigüedades, porque para cada "apply-templates" solo había un "template". Pero... ¿Qué pasa si tenemos que utilizar varios "template" con el mismo valor para "match"? ¿Cómo los distinguiremos?

Para empezar voy a explicar por qué puede hacer falta semejante cosa: si tenemos que procesar un mismo nodo varias veces en el documento. Por ejemplo, supongamos que tenemos un documento como el siguiente:

<?xml version="1.0"?> <Artículo> <Autores> <Autor>Mauricio Matamala</Autor> <Autor>Esperanza Rubí</Autor> <Autor>José María Serrano</Autor> </Autores> <Título> Ortocorrección de imágenes de satélite </Título> <Capítulos> <Capítulo número="1" título="Abstract"> Justificación y estudio de los principios sobre detección remota </Capítulo> <Capítulo número="2" título="Puntos de control"> Principales técnicas actuales para la detección de puntos de control.</Capítulo> <Capítulo número="3" título="Lucas-Kanade"> El empleo de la técnica de Lucas-Kanade para la detección de puntos de control.</Capítulo> <Capítulo número="4" título="Conclusión"> Resultado de las pruebas y conclusiones. </Capítulo> </Capítulos> </Artículo>

Supongamos que queremos generar a partir del documento xml un documento html que tenga el siguiente aspecto:

<html> <head> <title> Ortocorrección de imágenes de satélite </title> </head> <body> <h3> Ortocorrección de imágenes de satélite </h3> <p>Autores: Mauricio Matamala,Esperanza Rubí y José María Serrano.</p> <h2>Índice</h2> <p><strong>1:</strong>Abstract</p> <p><strong>2:</strong>Puntos de control</p> <p><strong>3:</strong>Lucas-Kanade</p> <p><strong>4:</strong>Conclusión</p> <h3>1. Abstract</h3> <p> Justificación y estudio de los principios sobre detección remota </p> <h3>2. Puntos de control</h3> <p> Principales técnicas actuales para la detección de puntos de control.</p> <h3>3. Lucas-Kanade</h3> <p> El empleo de la técnica de Lucas-Kanade para la detección de puntos de control.</p> <h3>4. Conclusión</h3> <p> Resultado de las pruebas y conclusiones. </p> </body> </html>

Como se puede observar, el título de los capítulos, se emplea dos veces: la primera vez para la tabla de contenidos, y la segunda durante el desarrollo del texto. Esto quiere decir, que el documento XSLT que necesitamos utiliza dos "template" con el atributo "match" con valor "Capítulo".

¿Cómo los distinguiremos entre sí, para cuando los referenciemos desde el elemento "apply-templates". La solución es la siguiente:

<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html> <head> <title><xsl:value-of select="/Artículo/Título"/></title> </head> <body> <h3><xsl:value-of select="/Artículo/Título"/></h3> <p>Autores: <xsl:apply-templates select="/Artículo/Autores/Autor"/></p> <h2>Índice</h2> <xsl:apply-templates select="/Artículo/Capítulos/Capítulo" mode="Índice"/> <xsl:apply-templates select="/Artículo/Capítulos/Capítulo" mode="Desarrollo"/> </body> </html> </xsl:template> <xsl:template match="Autor"> <xsl:choose> <xsl:when test="position() < last()-1"> <xsl:value-of select="."/>,</xsl:when> <xsl:when test="position() = last()-1"> <xsl:value-of select="."/> y </xsl:when> <xsl:otherwise> <xsl:value-of select="."/>.</xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="Capítulo" mode="Índice"> <p><strong><xsl:value-of select="@número" />:</strong> <xsl:value-of select="@título"/></p> </xsl:template> <xsl:template match="Capítulo" mode="Desarrollo"> <h3><xsl:value-of select="@número" />. <xsl:value-of select="@título"/></h3> <p><xsl:value-of select="."/></p> </xsl:template> </xsl:stylesheet>

Observa que se emplea el atributo "mode", que distingue un template de otro.

Actividad 7. Observa el siguiente documento XML:

<?xml version="1.0" encoding="UTF-8"?> <libros biblioteca="Biblioteca Pública de la Paz"> <libro isbn="1234-abcd"> <titulo>El 8</titulo> <autor>Katherine Neville</autor> <imagen>el8.png</imagen> </libro> <libro isbn="2345-bcde"> <titulo>El hobbit</titulo> <autor>J. R. Tolkien</autor> <imagen>elhobbit.png</imagen> </libro> <libro isbn="3456-cdef"> <titulo>Don Quijote de la Mancha</titulo> <autor>M. Cervantes</autor> <imagen>donquijote.png</imagen> </libro> </libros>

A partir de este docuemnto xml queremos obtener dos páginas web diferentes:

Observa que en la segunda página, los libros están ordenados por orden alfabético.

Escribe dos hojas de estilos XSLT para realizar las transformaciones pedidas.

Actividad 8. Observa el siguiente documento XML:

<?xml version="1.0"?> <películas> <película> <título> <traducido>Pequeñas mentiras sin importancia.</traducido> <original>Les petits mouchoirs.</original> </título> <país>Francia</país> <año>2010</año> <dirección>Guillaume Canet</dirección> <intérpretes> <intérprete>François Cluzet</intérprete> <intérprete>Marion Cotillard</intérprete> <intérprete>Benoît Magimel</intérprete> <intérprete>Gilles Lellouche</intérprete> <intérprete>Jean Dujardin</intérprete> <intérprete>Laurent Lafitte</intérprete> </intérpretes> <duración unidad="minutos">154</duración> <género>drama</género> <sinopsis>Un grupo de amigos tiene la costumbre de reunirse en sus vacaciones de verano. Este año, deciden no romper esta tradición a pesar de que uno de ellos ha sufrido un accidente en París unos días antes de partir. Ya en la playa, sus contradicciones afloran y su amistad se pone a prueba. Juntos se verán obligados a convivir con esas pequeñas mentiras sin importancia que se dicen cada día.</sinopsis> <cartel>petit_mouchoirs.jpg</cartel> </película> <película> <título> <original>Amigos</original> </título> <país>España</país> <año>2011</año> <dirección>Borja Manso y Marcos Cabotá</dirección> <intérpretes> <intérprete>Ernesto Alterio</intérprete> <intérprete>Diego Martín</intérprete> <intérprete>Alberto Lozano</intérprete> <intérprete>Goya Toledo</intérprete> <intérprete>Manuela Velasco</intérprete> </intérpretes> <duración unidad="minutos">105</duración> <género>comedia</género> <sinopsis>La firme amistad entre tres amigos se pondrá a prueba en el momento en que se enteran de que un antiguo amigo de la infancia ha fallecido, y les ha dejado su herencia. Para hacerse con ella deberán participar en una apuesta ideada por el difunto. Esto desembocará en una espiral de competitividad.</sinopsis> </película> <película> <título> <traducido>Betty Anne Waters</traducido> <original>Betty Anne Waters</original> </título> <país>USA</país> <año>2010</año> <dirección>Tony Goldwyn</dirección> <intérpretes> <intérprete>Hilary Swank</intérprete> <intérprete>Sam Rockwell</intérprete> <intérprete>Melissa Leo</intérprete> <intérprete>Minnie Driver</intérprete> <intérprete>Juliette Lewis</intérprete> </intérpretes> <duración unidad="minutos">107</duración> <género>drama</género> <sinopsis>Betty Anne Waters es la historia verdadera de una mujer que dedicó 18 años de su vida a liberar a su hermano de la cárcel. Cuando Kenneth Waters es condenado a cadena perpetua por el asesinato de una mujer en Massachusetts, su hermana, Betty Anne, empleada en una cafetería, casada y con dos hijos decide luchar para demostrar que es inocente. Sin estudios, uno de sus mayores obstáculos será licenciarse en Derecho para poder reabrir el caso y defenderlo ella misma ante un tribunal. No será fácil, pues también significará dejar de lado su vida para centrarse en la de él. Además, la lucha promete ser larga ya que el Estado no va admitir su error tan fácilmente. El tiempo juega en su contra, pero, mientras hay vida, hay esperanza.</sinopsis> <cartel>betty_anne_waters.jpg</cartel> </película> </películas>

A partir del documento XML, construye dos hojas de estilos XSLT, para obtener a partir de aquél las siguientes páginas html.

Captura de la página 1

Captura de la Página 2

Observa los matices de cada página:

La primera:

  • Las películas están ordenadas por orden alfabético.
  • El título original se muestra como un título, y en caso de haber una traducción, se muestra debajo entre paréntesis, con un tamaño menor.
  • En caso de no haber cartel, se muestra el mensaje "Sin cartel actualmente".
  • Cada cartel tiene un ancho de 100 píxeles.
  • En la línea donde se indican director y actores:
    1. Se muestra el género de la película.
    2. Los actores se muestran separados por comas, salvo el último que se separa con "y", y el último termina con ".".

La segunda:

  • El título original se muestra como un título, y en caso de haber una traducción, se muestra debajo entre paréntesis, con un tamaño menor.
  • Los carteles y los textos están dentro de tablas, una celda para la imagen y la otra para los textos.
  • Cada cartel tiene un ancho de 100 píxeles.
  • La celda de las imágenes tiene un fondo gris y la imagen está centrada en la celda.
  • La forma de presentar el texto es diferente al ejemplo anterior.

[Sólo para el ciclo ASIR] Entrega el documento xml junto con los documentos xslt resultantes con el nombre Act8-xslt.xml, Act8.1-xslt.xsl y Act8.2-xslt.xsl

Actividad 9. En esta actividad vamos a realizar la transformación del documento xml anterior, utilizando PHP. De este modo podemos plantear las transformaciones como un método de generar documentos HTML, con la ventaja que supone la separación de la presentación que conseguimos con xml. Para conseguirlo, sigue las siguientes instrucciones:

  • Instala un servidor Apache2.
  • Instala el módulo de PHP para Apache.
  • Instala el módulo de XSLT para PHP.

Por ejemplo, en Ubuntu, tendrías que hacer lo siguiente:

sudo apt-get install apache2 php5 sudo apt-get install php5-xsl

Reinicia Apache. Para comprobar que todo está bien, vete al directorio raíz del directorio raíz de Apache (en Ubuntu /var/www), y crea un archivo llamado info.php, con el siguiente contenido:

<? phpinfo(); ?>

Ahora vete a un cliente web, y abre la página http://ip-servidor/info.php. Deberías ver información variada sobre el servidor, entre la que se incluye información sobre XSLT. Así comprobarás que a) PHP funciona, y b) que se puede procesar XSLT.

Ahora, solo necesitas incluir el siguiente código PHP en la página desde la que procesarás los archivos XML y XSLT:

<?php $xml = new DOMDocument; $xml->load('xslt.xml'); // Carga del documento XML $xsl = new DOMDocument; $xsl->load('xslt.xsl'); // Carga de la hoja de estilos XSLT $proc = new XSLTProcessor; // Creación de un nuevo procesador XSLT $proc->importStyleSheet($xsl); // Añadiendo al procesador la hoja de estilos echo $proc->transformToXML($xml); // Aplicar la transformación ?>

Puede que no obtengas lo que esperabas (un error 500). Para que esto funcione, el módulo de XSL para PHP debe estar instalado. Puedes comprobarlo del siguiente modo:

<?php if (!class_exists("XSLTProcessor")){ echo "¡El módulo de XSL no está instalado!"; } else { echo "El módulo de XSL está instalado"; } ?>

Si obtienes un resultado negativo, instala el módulo con el siguiente comando:

# apt-get install php5_xsl

Después debes reiniciar Apache

Recuerda que el archivo donde se almacenará este código debe tener extensión .php para sea tratado por Apache como código PHP.

El objetivo es crear un formulario en la que el usuario puede elegir entre la versión A o B de la cartelera mediante un botón de radio. Cuando el usuario realiza la consulta, obtiene a través de una página PHP el resultado pedido.

[Solo ciclo DAW] Entrega los siguientes archivos:

  • El documento php con el nombre act9-xslt.php.
  • Los documentos xml y xsl
  • Una captura del formulario de consulta
  • Una captura con el primer resultado.
  • Una captura con el segundo resultado.

Y con esto, terminamos XSLT. Saludos.