Si Java es el lenguaje portable por excelencia e independiente de la máquina, XML representa el equivalente a Java en cuanto a almacenamiento de datos. Ser capaz de almacenar datos estructurados, pero en formato de "texto plano" nos da la posibilidad de almacenar información compleja de manera portable. Esta capacidad se usa en muchos lugares: por ejemplo como formato de exportación/importación de bases de datos, como formato para ficheros de configuración en toda la plataforma J2EE, o como lenguaje de definición de páginas web. Es en este último contexto donde mejor podemos combinar la capacidad de procesamiento de JSP con la portabilidad de XML. No obstante, JSP y XML se pueden combinar de diversos modos en aplicaciones web.
Caben diversas posibilidades a la hora de combinar JSP con XML. Algunas de ellas son:
J2EE nos proporciona dos herramientas fundamentales para conseguir estos fines:
Se trata de utilizar código Java que llame al API JAXP para procesar el XML. Como se ve en el módulo de XML y Java de este curso, JAXP permite procesar documentos XML (reorganizarlos, filtrarlos, cambiar su estructura) mediante los APIs estándar SAX y DOM y además aplicar hojas de estilo XSLT para transformarlos a cualquier formato.
En el contexto de una aplicación web, que es donde vamos a usar JSP, el código Java puede ejecutarse en el servidor, on line en cada petición HTTP (mediante un filtro) o bien off-line.
Como ejemplo, podéis bajaros la aplicación MiniamazonXML en formato WAR (la "diminuta" tienda web de discos y libros pero ahora desarrollada en JSP con XML en lugar de HTML). Un ejemplo de página de MiniamazonXML es la página de datos de un producto, masinfo.jsp:
<?xml version="1.0" encoding="ISO-8859-1" ?> <jsp:useBean id="prod" class="beans.prodBean"/> <producto> <titulo> <jsp:getProperty name="prod" property="titulo"/> </titulo> <% for (int i=0; i<prod.getNumAutores(); i++) { %> <autor> <jsp:setProperty name="prod" property="numAutor" value="<%=i%>"/> <jsp:getProperty name="prod" property="autor"/> </autor> <% } %> <descripcion> <jsp:getProperty name="prod" property="descripcion"/> </descripcion> </producto>
Obsérvese que la página no es un documento XML bien formado, por "culpa" del código Java que contiene. Como ya hemos visto en el tema 3, el código de la página se podría eliminar utilizando etiquetas JSTL, aunque en algunos casos extremos no habrá forma de evitarlo. No obstante, esto no importa, porque antes de procesar el XML con JAXP lo procesará el contenedor JSP (en nuestro caso Tomcat) que "eliminará" el código Java, dejando únicamente XML.
Si se visualiza la página de algún producto desde el navegador, introduciendo en la URL
http://localhost:8080/miniamazonxml/main?accion=masinfo&cod=0001
se obtendrá el documento XML perteneciente al producto solicitado. El Explorer muestra el documento en forma de árbol, mientras que otros navegadores, como Netscape, muestran simplemente el texto sin las etiquetas.
Para obtener el documento en otros formatos (por ejemplo HTML) necesitamos
una hoja de estilo XSLT y un proceso que la aplique. En MiniamazonXML hay implementado
un filtro (la clase FiltroXML, ver el fichero de configuración
de la aplicación) que postprocesa el resultado devuelto por el contenedor
JSP aplicándole una hoja de estilo XSLT. El filtro se activa si en el
resultado devuelto por Tomcat aparece una instrucción de procesamiento
denominada xslt. A esta instrucción se le debe poner como parámetro
el nombre de la hoja de estilo a aplicar y el nombre del navegador ante el que
hay que aplicar la hoja (recordemos que los navegadores se identifican mediante
la cabecera HTTP User-Agent
). Por ejemplo:
<? xslt cliente="Mozilla" xsl="masinfo-html.xsl" ?>
Volved a probar la solicitud HTTP anterior introduciendo esta línea en el fichero XML y comprobar el resultado. El navegador recibirá el código HTML producto de la transformación del documento original XML. Desarrollando distintas plantillas XSLT podemos ofrecer distintos formatos a distintos clientes web (navegadores, PDAs, móviles WAP,...).
Como ya se ha visto en el tema 3, JSTL dispone de etiquetas para procesamiento de documentos XML. De este modo no es necesario programar código Java para trabajar con XML, sino que se puede hacer más fácilmente con etiquetas.
Las etiquetas dedicadas a XML están divididas en tres grupos, atendiendo a la función que cumplen:
Función | Etiquetas |
---|---|
Core |
|
Control de flujo |
when otherwise
|
Transformación |
|
Como se ve, la mayoría de etiquetas core y de control de flujo tienen el mismo nombre que en las otras áreas de JSTL. La razón es que tienen la misma función, aunque orientada a XML. La diferencia principal es el soporte de expresiones XPath.
Estas etiquetas proporcionan las funcionalidades básicas para analizar XML y acceder a nodos dentro del documento.
La etiqueta parse analiza el documento XML especificado con el atributo
xml
y guarda el resultado en la variable especificada por el atributo
var
. Por ejemplo:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"%>
<%@ taglib prefix="x" uri="http://java.sun.com/jstl/xml" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Ejemplo de parse</title>
</head>
<body>
<c:set var="discos">
<disco>
<titulo> O sea </titulo>
<interprete> Enrique Iglesias </interprete>
</disco>
</c:set>
<x:parse var="analizado" xml="${discos}" /> <!-- sacar el título --> título disco: <x:out select="$analizado//titulo"/>
<!-- meter el título en una variable para sacarlo con c:out --> <x:set var="tit" select="string($analizado//titulo)"/>
título disco: <c:out value="${tit}"/> <br>
</body>
</html>
Primero metemos un "documento XML" empotrado en la página
web en la variable discos
(podríamos haberlo tomado de una
URL cualquiera con un c:import
). Luego analizamos el documento
con parse
, y a partir de este momento podemos acceder a cualquiera
de sus nodos con una expresión XPath.
La etiqueta x:out toma una expresión XPath (un conjunto de nodos),
la convierte a String
automáticamente y la inserta en la
salida. La etiqueta x:set es el equivalente a c:set, pero admite
expresiones XPath.
Como en el caso anterior, su característica principal es que admiten
expresiones XPath. Como ejemplo, veremos el uso de la etiqueta forEach
,
las otras son similares.
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jstl/xml" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Ejemplo de x:forEach</title>
</head>
<body>
<c:set var="discos">
<discos>
<disco>
<titulo> O sea </titulo>
<interprete> Enrique Iglesias </interprete>
</disco>
<disco>
<titulo> Money for Nothing </titulo>
<interprete> Dire Straits </interprete>
</disco>
</discos>
</c:set><h2> Titulos del mes </h2>
<x:parse xml="${discos}" var="analizado"/>
<x:forEach var="tit" select="$analizado//titulo">
<x:out select="$tit"/> <br>
</x:forEach>
</body>
</html>
Como se ve, es equivalente a un c:forEach
, solo que admite expresiones
XPath en el atributo select
.
la etiqueta transform
aplica una plantilla XSLT. Por ejemplo,
suponiendo que hubiéramos definido el documento XML "empotrado"
discos
del ejemplo anterior, podríamos añadir el
siguiente código:
... ... <c:set var="hojaxsl">
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="titulo">
<br/> <b> <xsl:value-of select="."/> </b> <br/>
</xsl:template>
</xsl:stylesheet>
</c:set> <x:transform xml="${discos}" xslt="${hojaxsl}"/>