XSLT (II)

Seguimos con XSLT.

EL ELEMENTO <XSL:COPY>

El elemento <xsl:copy> copia un nodo al árbol resultado, pero no copia los nodos descendentes. Esto es útil si queremos cambiar la estructura de un elemento o su contenido, o añadir o eliminar atributos.

Vamos a ver un ejemplo:

<Personas> <Persona> <Nombre>Linux</Nombre> <Apellido>Torvalds</Apellido> </Persona> <Persona> <Nombre>Eric</Nombre> <Apellido>Raimond</Apellido> </Persona> <Persona> <Nombre>Alan</Nombre> <Apellido>Cox</Apellido> </Persona> </Personas>

Para el ejemplo anterior, al que llamaremos "Personaas.xml", le aplicaremos la siguiente hoja de estilos xslt, a la que llamaremos "Personas.xsl":

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" > <xsl:template match="/"> <Personas> <xsl:apply-templates select="/Personas/Persona" /> </Personas> </xsl:template> <xsl:template match="Persona"> <xsl:copy> <xsl:attribute name="Nombre"> <xsl:value-of select="Nombre"/> </xsl:attribute> <xsl:attribute name="Apellido"> <xsl:value-of select="Apellido"/> </xsl:attribute> </xsl:copy> </xsl:template> </xsl:stylesheet>

Después de probar el ejemplo, vamos a analizarlo. Como anteriormente, existe un template que tiene el atributo matches="/". En vez de crear elementos literales HTML/XHTML, se añade el elemento literal <Persona>. El elemento <xsl:apply-templates> es usado con la ruta XPath /Personas/Persona.

Existe un template que tiene match a "Persona", lo que coincide con el valor del atributo "select" del elemento "xsl:apply-templates". Por tanto, para cada nodo "Persona" en el documento fuente, el template especifica como procesarlo.

El elemento xsl:copy es usado cuando el nodo de contexto es un nodo elemento Persona (en el segundo template). Por tanto, cada nodo elemento "Persona" es añadido al árbol resultado, pero sin copiar los nodos hijo.

En este punto, lo que tendríamos si el documento acabase en el primer elemento xsl:copy tendríamos el siguiente resultado:

<Personas> <Persona/> <Persona/> <Persona/> </Persona>

El template emplea el elemento xsl:attribute para añadir un nuevo nodo atributo al elemento persona en el árbol resultado. En la línea <xsl:attribute name="Nombre"> estamos diciendo que el atributo se llamará "Nombre". Y con la línea <xsl:value-of select="Nombre"/> indicamos que el valor del atributo será el contenido del elemento "Nombre".

Lo mismo ocurre con el atributo "Apellido".

AÑADIR ELEMENTOS HIJO

Si necesitamos seguir el camino inverso al del ejemplo anterior, podemos hacerlo con en el siguiente ejemplo. Partimos del resultado generado en el ejemplo anterior.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" > <xsl:template match="/"> <Personas> <xsl:apply-templates select="/Personas/Persona" /> </Personas> </xsl:template> <xsl:template match="Persona"> <xsl:copy> <xsl:element name="Nombre"> <xsl:value-of select="@Nombre"/> </xsl:element> <xsl:element name="Apellido"> <xsl:value-of select="@Apellido"/> </xsl:element> </xsl:copy> </xsl:template> </xsl:stylesheet>

Si observamos el código, se vuelve a repetir más o menos lo mismo que en el anterior. Tenemos un template con match a "/".

También tenemos un elemento "xsl:apply-templates" con select a "/Personas/Persona". Para este "xsl:apply-templates" hay un template (cuyo atributo match vale "Persona") que indica cómo procesar cada nodo elemento "Persona".

Con el primer <xsl:copy>, copiamos al árbol resultado el nodo elemento "Persona". Dejamos abierto el elemento <xsl:copy>, porque dentro colocaremos otros elementos.

Dentro del elemento <xsl:copy> creamos nuevos elementos, con el elemento <xsl:element>. A cada elemento le asignamos un nombre. Por ejemplo con "<xsl:element name="Nombre">" indicamos que se debe crear un un nuevo nodo elemento llamado Nombre.

A su vez, dentro de estos nuevos elementos, colocamos elementos de tipo xsl:value-of que recuperan el contenido de cada atributo. Por ejemplo, la línea <xsl:value-of select="@Apellido"/> recupera el valor del atributo "Apellido".

EL ELEMENTO XSL:COPY-OF

Este elemento realiza una copia en profundidad. Es decir, copia un nodo, junto con todos sus nodos atributo y nodos descendientes.

<Envío> <Origen>Ametsis</Origen> <Destino>Seragul</Destino> <Dirección> <Calle>Lamentos,5</Calle> <Ciudad>Gotham</Ciudad> <País>ES</País> <CP>54321</CP> </Dirección> </Envío> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" > <xsl:template match="/"> <Notificación> <xsl:apply-templates select="/Envío/Destino" /> <xsl:apply-templates select = "/Envío/Origen" /> <xsl:apply-templates select="/Envío/Dirección" /> </Notificación> </xsl:template> <xsl:template match="Destino"> <xsl:element name="Origen"><xsl:value-of select="." /></xsl:element> </xsl:template> <xsl:template match="Origen"> <xsl:element name="Destino"><xsl:value-of select="." /></xsl:element> </xsl:template> <xsl:template match="Dirección"> <xsl:copy-of select="." /> </xsl:template> </xsl:stylesheet>

Como podemos ver, hemos utilizado el elemento "copy-of" dentro de un "template" aplicado al nodo "Dirección". Es decir, hemos copiado el nodo Dirección, así como a todos sus descendientes. De este modo podemos integrar toda esta zona del árbol en el árbol resultado.

ELIGIENDO EL TIPO DE SALIDA

Con XSLT se pueden generar documentos XML, HTML o de texto. Podemos elegir de qué tipo será el resultado mediante el elemento <xsl:output method="tipo de documento a generar"/>, donde tipo de documento a generar puede ser "xml", "html" o "text".

Por ejemplo, en el ejemplo anterior, podemos agregar al documento XSLT, justo debajo del elemento "stylesheet", el siguiente elemento:

<xsl:output method="html" version="4.0" encoding="iso-8859-1" indent="yes"/>

Actividad 3. Modifica el documento xml siguiente, para obtener el documento xml mostrado más abajo.

<?xml version="1.0" encoding="ISO-8859-1"?> <compra> <comprador> Jose Perez</comprador> <fecha>6/6/10</fecha> <articulo> <referencia>2342</referencia> <nombre>Conector rj45</nombre> <cantidad>100</cantidad> </articulo> <direccion> C/Lamentos nº PI, Gotham, Espana. CP 234324 </direccion> </compra>

El documento generado será el siguiente:

<purchase id="2342" date="6/6/10" quantity="100"> <purchaser> Jose Perez</purchaser> <address> C/Lamentos nº PI, Gotham, Espana. CP 234324 </address> </purchase>

Actividad 4. Repetir el ejercicio anterior, pero con los siguientes documentos:

<?xml version="1.0" encoding="UTF-8"?> <compras> <compra> <comprador> José Pérez</comprador> <fecha>6/6/10</fecha> <artículo> <referencia>2342</referencia> <nombre>Conector rj45</nombre> <cantidad>100</cantidad> </artículo> <dirección> C/Lamentos nº PI, Gotham, España. CP 234324 </dirección> </compra> <compra> <comprador> Antonio Pérez</comprador> <fecha>6/6/10</fecha> <artículo> <referencia>2343</referencia> <nombre>Conector rj46</nombre> <cantidad>100</cantidad> </artículo> <dirección> C/Suspiros nº PI, Gotham, España. CP 234324 </dirección> </compra> </compras>

Documento generado

<?xml version="1.0" encoding="utf-8"?> <adquisiciones> <compra fecha-compra="6/6/10" comprador="José Pérez"> <artículo> <referencia>2342</referencia> <nombre>Conector rj45</nombre> <cantidad>100</cantidad> </artículo> </compra> <compra fecha-compra="6/6/10" comprador="Antonio Pérez"> <artículo> <referencia>2343</referencia> <nombre>Conector rj46</nombre> <cantidad>100</cantidad> </artículo> </compra> </adquisiciones>

Guarda el ejercicio en un archivo llamado Act4-xslt.xsl