Sei sulla pagina 1di 58

JSTL

Alejandro Ramírez [mailto:jano@1x4x9.info]


Este documento se publica bajo la licencia "Creative Commons Attribution Li-
cense". Para ver una copia de la licencia visita ht-
tp://creativecommons.org/licenses/by/1.0/ o envía una carta a Creative Commons,
559 Nathan Abbott Way, Stanford, California 94305, USA.
04 abril 2004
Revision History
Revision 1 04 abril 2004
alpha JSTL 1.0
Revision 2 25 mayo 2004
alpha JSTL 1.1

Tutorial y referencia de la especificación JavaServer Pages Standard Tag Library


[http://www.jcp.org/en/jsr/detail?id=52] (JSTL) versión 1.1.

Table of Contents
Introducción ......................................................................................................... 1
Introducción ................................................................................................. 1
¿Que es JSTL? ............................................................................................. 3
JSTL es fácil ................................................................................................ 4
Historia de JSTL ........................................................................................... 4
Instalar JSTL ................................................................................................ 4
Expression Language (EL) ...................................................................................... 8
EL .............................................................................................................. 8
Operadores .................................................................................................10
Literales .....................................................................................................11
Objetos implícitos ........................................................................................12
Funciones EL ..............................................................................................15
Etiquetas ............................................................................................................19
Core ..........................................................................................................19
Bases de datos .............................................................................................28
I18n y formateo ...........................................................................................34
XML .........................................................................................................44
Validadores de bibliotecas (TLVs) ..........................................................................50
¿Que es un TLV? .........................................................................................50
TLVs de JSTL .............................................................................................51
Repaso a XPath ...................................................................................................52
¿Que es XPath? ...........................................................................................52
Selección ....................................................................................................52
Expresiones XPath .......................................................................................55
Métodos .....................................................................................................55

Introducción
Introducción
JSP
¿Que es JSP?

1
JSTL

• JSP significa Java Server Pages (Páginas Java en el Servidor).

• JSP es una tecnología Java para escribir programas que se ejecutan en el servidor.

• Existen muchos servidores capaces de ejecutar páginas JSP: Tomcat


[http://jakarta.apache.org/tomcat/], JBoss, Resin, etc.

¿Que es una página JSP?

• Una página JSP es un fichero de texto.

• Una página JSP es HTML convencional al que se le añaden instrucciones JSP ejecutables.

• Las instrucciones JSP están formadas por etiquetas similares a las del código HTML.

• Una página JSP tiene la extensión .jsp.

• Este es un ejemplo de página JSP:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>


<jsp:useBean id="now" class="java.util.Date" />
<html>
<body>
Hoy es <fmt:formatDate value="${now}" dateStyle="full" />
</body>
</html>

y su resultado

Figure 1.

¿Como se ejecuta?

• Si el usuario pide una página con extensión .html el servidor se la envía.

• Si el usuario pide una página con extensión .jsp el servidor ejecuta el JSP y añade el resultado
al HTML original de la página.

• Para ejecutar una página JSP, el servidor realiza internamente varias operaciones:

• Convierte la página JSP en código Java.

• Compila el código Java.

• Ejecuta el código Java.

¿Para que sirve?

• Programar con instrucciones JSP es más rápido porque no necesitamos compilar.

• JSP permite crear páginas dinámicas (o sea, páginas cuyo contenido varia en cada ejecución).

2
JSTL

• Con JSP podemos responder a peticiones o información que el usuario nos envía.

• Con JSP podemos acceder a bases de datos o realizar cualquier operación posible con Java.

• JSP puede incluir instrucciones JSP y/o código en Java pero este último no es aconsejable
porque produce páginas complicadas de mantener.

JSTL
¿Que es JSTL?

• JSTL significa Java Standard Template Library (biblioteca de etiquetas estándar para Java).

• JSTL es un subconjunto de las etiquetas disponibles en JSP 2.0.

• JSTL no contiene código Java.

• JSTL es sencillo.

¿Qué requiere?

• Conocimientos básicos acerca del desarrollo de aplicaciones Web en Java.

• Un servidor capaz de ejecutar JSP 2.0.

• Instalar una implementación de JSTL: jstl-1.0.2.jar


[http://www.ibiblio.org/maven/jstl/jars/jstl-1.0.2.jar] (20k), standard-1.0.4.jar
[http://www.ibiblio.org/maven/taglibs/jars/standard-1.0.4.jar] (503k).

¿Que es JSTL?
JSTL es una biblioteca que implementa funciones de uso frecuente en aplicaciones JSP. En con-
creto, JSTL proporciona

• Cinco bibliotecas de etiquetas JSP:

• Funciones comunes de iteración sobre datos, operaciones condicionales, e importación de


otras páginas.

• Internacionalización y formateo de texto.

• Funciones de manipulación de cadenas.

• Procesamiento de XML.

• Acceso a bases de datos.

• Un lenguaje de expresión para referenciar objetos y sus propiedades sin necesidad de código
Java.

• Validadores de bibliotecas de etiquetas (Tag Library Validators, TLVs).

JSTL requiere un contenedor de JSP 2.0.

3
JSTL

JSTL es fácil
Por su simplicidad, JSTL solo requiere conocimientos rudimentarios de Java, JSP, y aplicaciones
Web. Cualquier desarrollador puede comenzar a usarlo de forma casi inmediata.

JSTL facilita la referencia a objetos:

<%-- con JSP --%>


<%= session.getAttribute("username").getFirstName()%>
<%-- con JSTL --%>
${sessionScope.username.firstName}

[PENDIENTE] más ejemplos.

Historia de JSTL
Con JSTL se pretendía recopilar las etiquetas JSP más usadas en una biblioteca estándar que pudiera
usarse en todos los contenedores JSP

La especificación JSTL se desarrollo bajo el auspicio del JCP [http://www.jcp.org/en/home/index]


(Java Community Process, Proceso Comunitario Java). El JCP es un proceso supervisado por SUN
pero abierto a empresas, e individuos particulares, que guía el desarrollo y aprobación de los
estándares para el lenguaje Java. En la actualidad (mayo 2004) el JCP cuenta con 700 participantes.

Las iniciativas para crear un estándar dentro del proceso JCP se conocen como JSR (Java Specifica-
cion Request, Petición de Especificación Java). La JSR nº 52 [http://www.jcp.org/jsr/detail/52.jsp]
se llamó "A Standard Tag Library for JavaServer Pages", o abreviadamente JSTL. Fue solicitada
originalmente por Eduardo Pelegri-Llopart y Anil Vijendran, empleados de SUN. En su desarrollo
participaron individuos como Jason [http://today.java.net/cs/user/print/au/8?x-t=full.view]Hunter
[http://www.javahispano.org/text.viewer.action?file=jason_hun_es], y representantes de varias or-
ganizaciones (ASF, Adobe, BEA, y otras).

La especificación JSTL 1.0 fue terminada el 11 de julio de 2002. Unos días después apareció la
primera implementación [http://jakarta.apache.org/taglibs/doc/standard-1.0-doc/intro.html ] creada
por miembros del proyecto Taglibs [http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html] de
la fundación Apache. La última versión de JSTL a día de hoy (mayo de 2004) es la 1.1, imple-
mentada por el proyecto Taglibs.

JSTL es opcional en J2EE 1.4.

Instalar JSTL
Descargar el software
Para trabajar con JSTL necesitamos

• Un kit de desarrollo java como el Java Standard Edition (J2SE)


[http://java.sun.com/j2se/index.jsp] de Sun.

• Un servidor que ejecute Servlets y JSP como Tomcat [http://jakarta.apache.org/tomcat/]. JSTL


1.0 necesita JSP 1.2 y Servlets 2.3 implementadas por Tomcat 4. JSTL 1.1 requiere JSP 2.0 y
Servlets 2.4, implementadas por Tomcat 5. O dicho de otro modo, si vas a trabajar con la última
versión de JSTL (la 1.1) usa Tomcat 5.

• Una implementación de JSTL como la proporcionada por el proyecto Taglibs de Apache


[http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html]. La distribución (jakarta-
taglibs-standard-1.1.0.zip
[http://apache.rediris.es/jakarta/taglibs/standard/binaries/jakarta-taglibs-standard-1.1.0.zip]) con-
tiene documentación, ejemplos, la implementación en sí, y varios jars de dependencias. Si qui-

4
JSTL

eres ahorrar tiempo baja solo los jars siguientes: jstl-1.0.2.jar


[http://www.ibiblio.org/maven/jstl/jars/jstl-1.0.2.jar] (20k), standard-1.0.4.jar
[http://www.ibiblio.org/maven/taglibs/jars/standard-1.0.4.jar] (503k).

• Si vas a trabajar con expresiones XPath necesitaras jaxen-full.jar, y saxpath.jar, de la


distribución de Jaxen [http://jaxen.org/], el motor XPath escogido por Sun para JSTL. Jaxen es
un interfaz XPath para evaluar expresiones en DOM, JDOM, dom4j, o EXML. Esta presente en
el Web Services Developer Pack de Sun.

El fichero jar jstl-1.0.2.jar contiene clases javax.servlet.jsp.jstl.* con la API de JSTL


[http://java.sun.com/webservices/docs/1.0/api/index.html]. El fichero standard-1.0.4.jar contiene los
paquetes [http://jakarta.apache.org/taglibs/doc/standard-doc/standard/index.html] con la
implementación de JSTL.

Instalar Tomcat
Para instalar Tomcat

• Usamos un paquete especifico de nuestro sistema operativo, o simplemente bajamos la


distribución en zip o tar.gz y la descomprimimos donde nos plazca.

• Establecemos la variable de entorno CATALINA_HOME apuntando al directorio de instalación.

Con la distribución en zip/tar.gz el resultado es similar a este:

Figure 2. Tomcat 5 en Windows

Cada directorio tiene un propósito, pero por ahora solo necesitamos saber que en bin están los
scripts de arranque del servidor, y en webapps las aplicaciones Web.

Crear una aplicación de ejemplo


En Tomcat, cada aplicación Web se añade en un subdirectorio de CATALINA_HOME/webapps.
Además el estándar requiere que tenga cierta estructura de directorios. Sin entrar en detalles, neces-
itaremos una estructura como esta:

$CATALINA_HOME/webapps/miAplicacion
####WEB-INF
####classes
####lib
commons-logging-1.0.3.jar
jstl-1.0.2.jar
standard-1.0.4.jar

Observa que web.xml no es obligatorio según la especificación Servlet


[http://jcp.org/aboutJava/communityprocess/final/jsr154/index.html], y tampoco necesitamos crearlo
para declarar los descriptores de etiquetas, porque desde JSP 1.2 es posible (y aconsejable) em-
paquetarlos con la propia implementación binaria. En JSTL los descriptores están en el fichero
standard-1.0.1.jar.

En cualquier caso, no esta de más añadir un web.xml. Se coloca bajo el directorio WEB-INF:

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


<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com
version="2.4">

5
JSTL

<description>JSTL test</description>
<display-name>JSTL test</display-name>
</web-app>

Si reiniciamos Tomcat, la aplicación será accesible en http://localhost:8080/miAplicacion


[http://localhost:8080/myApp/], pero no veremos nada a menos que añadamos alguna página JSP.

Crear una página JSP con JSTL


Siguiendo con la aplicación Web de la sección anterior, vamos a crear una página JSTL.

En toda página JSP hay que declarar la biblioteca a la que pertenece cada etiqueta que usemos.
Puesto que son varias líneas, lo más comodo es hacer las declaraciones en un fichero aparte, y luego
incluir dicho fichero en nuestras páginas JSP. Este sistema evita repetir el mismo texto en todas las
páginas, y si en el futuro añadimos más bibliotecas, solo tendremos que modificar un único fichero.

• Añade una página $CATALINA_HOME/webapps/miAplicacion/taglibs.jsp con las


siguientes declaraciones:

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>


<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jstl/xml" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

• Añade una página $CATALINA_HOME/webapps/miAplicacion/index.jsp que im-


porte la anterior usando una directiva include:

<%@include file="taglibs.jsp" %>


<html>
<body>
<c:out value="Hola mundo"/>
</body>
</html>

En este ejemplo hemos usado la etiqueta c:out de la librería core para mostrar un mensaje.

Generar un proyecto JSTL con Maven


En la sección anterior creamos un proyecto de ejemplo directamente sobre el servidor Tomcat. Vale
como prueba, pero en proyectos complejos resulta más práctico crear la aplicación en un directorio
aparte para no mezclar el entregable (proyecto terminado), con el código fuente original.

Herramientas como Ant o Maven, nos permiten automatizar la construcción y despliegue de una
aplicación a partir de su código fuente. Normalmente comenzamos un proyecto escribiendo un
script, pero si somos usuarios de Maven podemos generar automáticamente una aplicación de ejem-
plo que tomaremos como punto de partida.

Warning
Maven es una herramienta similar a Ant pero más flexible y compleja. Si eres principiante
probablemente te traiga más complicaciones que beneficios.

Maven permite generar proyectos de ejemplo (script incluido) para varias tecnologías usando el plu-
gin genapp [http://maven.apache.org/reference/plugins/genapp/goals.html]. Por ahora existen plan-
tillas para JSTL, Struts, Struts+JSTL, EJB, y otros. A continuación se explica como.

Genapp necesita XDoclet [http://xdoclet.sourceforge.net/], así que primero instalamos el plugin


Maven-XDoclet. Maven descargará automaticamente las de Internet las dependencias necesarias.

6
JSTL

$ maven plugin:download -DartifactId=maven-xdoclet-plugin -DgroupId=xdoclet -Dve


__ __
| \/ |__ _Apache__ ___
| |\/| / _` \ V / -_) ' \ ~ intelligent projects ~
|_| |_\__,_|\_/\___|_||_| v. 1.0-rc2
Intentando descargar junit-3.8.1.jar.
................
.
Intentando descargar servletapi-2.3.jar.
...........
.
Intentando descargar jstl-1.0.2.jar.
....
.
Intentando descargar standard-1.0.4.jar.
.......................................................................
.
Intentando descargar cactus-13-1.6dev-20040115.jar.
...................................
.
Intentando descargar commons-logging-1.0.3.jar.
......
.
Intentando descargar xdoclet-1.2.jar.
....................
.
Intentando descargar xdoclet-web-module-1.2.jar.
......
Intentando descargar xdoclet-ejb-module-1.2.jar.
............................
.
Intentando descargar xjavadoc-1.0.2.jar.
..................................
.
Intentando descargar httpunit-1.5.4.jar.
.................................................
.
Intentando descargar jtidy-4aug2000r7-dev.jar.
....................
.
Intentando descargar commons-jelly-tags-xml-20030211.142705.jar.
....
.
build:start:
plugin:download-artifact:
[mkdir] Created dir: C:\.maven\repository\xdoclet\plugins
[echo] repo is 'http://www.ibiblio.org/maven'
[echo] trying to download http://www.ibibl....ins/maven-xdoclet-plugin-1.2.j
.....
plugin:download:
[delete] Deleting 1 files from D:\java\apache\maven\plugins
[delete] Deleting 9 files from C:\.maven\plugins
[delete] Deleted 2 directories from C:\.maven\plugins
[copy] Copying 1 file to D:\java\apache\maven\plugins
BUILD SUCCESSFUL
Total time: 1 minutes 43 seconds
$

Ya podemos generar nuestra aplicación de ejemplo. Nos situamos en un directorio cualquiera y


hacemos esto:

$ maven genapp
__ __
| \/ |__ _Apache__ ___
| |\/| / _` \ V / -_) ' \ ~ intelligent projects ~

7
JSTL

|_| |_\__,_|\_/\___|_||_| v. 1.0-rc2


Intentando descargar commons-jelly-tags-interaction-20030211.143817.jar.
..
.
Enter a project template to use: [default]
web-jstl
Please specify an id for your application: [app]
Please specify a name for your application: [Example Application]
Please specify the package for your application: [example.web]
build:start:
genapp:
[copy] Copying 1 file to D:\desarrollo\myApp\src\java\example\web
[copy] Copying 1 file to D:\desarrollo\myApp\src\test\example\web
[copy] Copying 2 files to D:\desarrollo\myApp\src\test-cactus\example\web
[copy] Copying 2 files to D:\desarrollo\myApp
[copy] Copying 5 files to D:\desarrollo\myApp
BUILD SUCCESSFUL
Total time: 25 seconds
Finished at: Sun Apr 25 18:52:22 CEST 2004

El proyecto resultante incluye las dependencias para usar Cactus, HttpUnit, y JUnit (de ahí que tarde
tanto en descargarse).

Expression Language (EL)


EL
Antes de JSTL, JSP usaba Java para referenciar atributos dinámicos. Con JSTL ya no es necesario.
Compara por ejemplo, la lectura de un parametro:

<%-- con JSP --%>


<%= request.getParameter("login") %>
<%-- con JSTL --%>
${param.login}

En JSTL se evita el uso de Java proporcionando un lenguaje de expresiones llamado EL (expression


language). EL no es un lenguaje de programación en sí mismo, su único propósito es

• referenciar objetos y sus propiedades,

• y escribir expresiones simples.

EL se basa en las siguientes normas:

• Las expresiones JSTL comienzan con ${ y terminan con }. Lo que hay en medio es tratado
como una expresión.

• Las expresiones se componen de

• Identificadores. Hay once identificadores reservados que corresponden a once objetos


implícitos (los veremos luego). El resto de identificadores sirven para crear variables.

• Literales. Son números, cadenas delimitadas por comillas simples o dobles, y los valores

8
JSTL

true, false, y null.

• Operadores. Permiten comparar y operar con identificadores y literales.

• Operadores de acceso. Se usan para referenciar propiedades de los objetos.

• Podemos usar expresiones en cualquier parte del documento, o como valores de los atributos de
etiquetas JSTL, exceptuando los atributos var y scope, que no aceptan expresiones.

• En cualquier sitio donde sea valido colocar una expresión, también será válido colocar más de
una. Por ejemplo: value="Hola ${nombre} ${apellidos}".

• Las expresiones pueden contener operaciones aritméticas, comparaciones, operaciones


booleanas, y agruparse mediante paréntesis. También pueden decidir cuando una variable existe
o no (usando empty).

• Para acceder al campo de un bean java, o a un elemento de una colección (array, o Map), se usa
el operador punto, o el operador corchete:

${bean.propiedad}
${map.elemento}
${header['User-Agent']}

Si un campo de un bean es otro bean, podemos encadenar puntos para acceder a una propiedad
del segundo bean:

${bean1.bean2.propiedad}

• Las expresiones pueden aparecer como parte del valor de un atributo de una etiqueta:

<c:out value="${2+2}"/>
<c:out value="${nombre}"/>
<c:if test="${tabla.indice % 2 == 0}">es par</c:if>

O independientemente junto a texto estático como el HTML:

<input type="text" name="usuario" value="${requestScope.usuario.nombre}"/>

EL es opcional en JSTL 1.0. Es por ello que cada una de las cuatro bibliotecas de JSTL tiene dos
versiones: [PENDIENTE]

• Versión EL: usa expresiones EL. Sus directivas taglib correspondientes son

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>


<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jstl/xml_rt" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql_rt" %>

• Versión RT: usa expresiones del entorno de ejecución de JSP. Sus directivas taglib correspondi-
entes son

<%@ taglib prefix="c_r" uri="http://java.sun.com/jstl/core" %>


<%@ taglib prefix="fmt_r" uri="http://java.sun.com/jstl/fmt" %>
<%@ taglib prefix="x_r" uri="http://java.sun.com/jstl/xml" %>
<%@ taglib prefix="sql_r" uri="http://java.sun.com/jstl/sql" %>

Si tenemos acceso a JSTL 1.1 es preferible la versión EL.

9
JSTL

Operadores
Los operadores y sus significados son los mismos que en otros lenguajes de programación.

Table 1. Resumen de operadores


Operador Descripción
. Acceso a propiedad o elemento de un Map.
[] Acceso a elemento de un array o de un List.
() Agrupación de expresiones.
: ? Expresión condicional: condición ? val-
orSiCierto : valorSiFalso
+, -, *, / (o div), % (o mod) Suma, resta, multiplicación, división, resto.
== (o eq), != (o ne), < (o lt), > (o gt), <= (o Igualdad, desigualdad, menor que, mayor, menor
le), >= (o ge) o igual que, mayor o igual que.
&& (o and), || (o or), ! (o not) Operadores lógicos and, or, y not.
empty Comprueba si una colección (array, Map, Col-
lection) es null o vacía.
función(argumentos) Llamada a una función.

Table 2. Resumen de precedencia de operadores [PENDIENTE: función,


empty, : ?]
[], .
()
- unario, not, !, empty
*, /, div, %, mod
+, - binario
(), <, >, <=, >=, lt, gt, le, ge
==, !=, eq, ne
&& (o and)
|| (o or)

Acceso a datos
El operador punto (.) permite recuperar la propiedad de un objeto por su nombre. Ejemplo:

${libro.paginas}

Las propiedades se recuperan usando las convenciones de los JavaBeans. Por ejemplo, en el código
anterior, invocábamos el método libro.getPaginas() del objeto libro.

El operador corchete ([]) permite recuperar una propiedad con nombre o indexada por número.
Ejemplo:

${libro["paginas"]}
${libro[0]}
${header['User-Agent']}

Dentro del corchete puede haber una cadena literal, una variable, o una expresión.

10
JSTL

Operadores aritméticos

Table 3.
Operador Descripción
+ suma
- resta
* multiplicación
/ div división
% mod resto

Operadores lógicos

Table 4.
Operador Descripción
&& and true si ambos lados son ciertos
|| or true si alguno de los lados son ciertos
! not true si la expresión es falsa

Operadores relacionales

Table 5.
Operador Descripción Ejemplo Resultado
== eq comprobación de ${5 == 5} true
igualdad
!= ne comprobación de ${5 != 5} false
desigualdad
< lt menor que ${5 < 7} true
> gt mayor que ${5 > 7} false
<= le menor o igual que ${5 le 5} true
>= ge mayor o igual que ${5 ge 6} false

Operador empty
El operador empty comprueba si una colección o cadena es vacía o nula. Ejemplo: ${empty
param.login}

Otra manera de hacerlo es usando la palabra clave null: ${param.login == null}

Literales
En expresiones EL podemos usar números, caracteres, booleanos (palabras clave true, false), y
nulls (palabra clave null).

11
JSTL

Objetos implícitos
Ciertos objetos son automáticamente accesibles a cualquier etiqueta JSP.

A través de ellos es posible a cualquier variable de los ámbitos page, request, session, ap-
plication, a parametros HTTP, cookies, valores de cabeceras, contexto de la página, y
parámetros de inicialización del contexto. Todos, excepto pageContext, están implementados
usando la clase java.util.Map.

Table 6. Objetos implicitos


Objetos implicitos contiene
pageScope Variables de ámbito página.
requestScope Variables de ámbito request.
sessionScope Variables de ámbito session.
applicationScope Variables de ámbito application.
param Parametros del request como cadenas.
paramValues Parametros del request como array de cadenas.
header Cabeceras del request HTTP como cadenas.
headerValues Cabeceras del request HTTP como array de ca-
denas.
cookie Valores de las cookies recibidas en el request.
initParam Parametros de inicialización de la aplicación
Web.
pageContext El objeto PageContext de la página actual.

Ejemplo:

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>


<%-- ACCESO A TODOS LOS ELEMENTOS --%>
<c:forEach items="${header}" var="item">
<c:out value="${item}"/><br/>
</c:forEach>
<br/>
<%-- ACCESO POR NOMBRE CON PUNTO: objeto.propiedad --%>
Host: <c:out value="${header.Host}"/> <br/>
<%-- ACCESO POR NOMBRE CON CORCHETES: objeto['propiedad']
Usar este formato evita que se interprete el nombre como una expresión.
Por ejemplo: queremos la propiedad "Accept-Language" no una resta entre
las variables Accept y Language.
--%>
Host: <c:out value="${header['Host']}"/> <br/>
Accept-Language: <c:out value="${header['Accept-Language']}"/> <br/>

El resultado es

accept-encoding=gzip, deflate
cache-control=no-cache
connection=Keep-Alive
referer=http://127.0.0.1:8080/sampleJSTL/
host=127.0.0.1:8080
accept-language=es
user-agent=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.
cookie=JSESSIONID=E58368E8FFA066A654750C4CED08AA88
accept=*/*

12
JSTL

Host: 127.0.0.1:8080
Host: 127.0.0.1:8080
Accept-Language: es

pageContext
Aquí se listan algunos de los valores disponibles en el contexto de la página. Existen otros que po-
demos consultar en el javadoc. Por ejemplo, pageContext.request.authType esta
ejecutando el método HttpServletRequest.getAuthType()
[http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getAuthType()].
De igual modo podemos acceder al resto de métodos.

Table 7. pageContext
Expresión Descripción Ejemplo
${pageContext.excepti Devuelve una descripción del "Algo ha ido mal"
on.message} error cuando la página en curso
es una página de error JSP.
${pageContext.errorDa Información de un error JSP.
ta}
${pageContext.request Tipo de autentificación usado BASIC
.authType} en la página.
${pageContext.request Identificador del usuario fulano
.remoteUser} (cuando esta en uso la
autentificación del contenedor).
${pageContext.request Nombre (también llamado con- /apuntes-jstl
.contextPath} texto) de la aplicación.
${pageContext.request Array de cookies.
.cookies}
${pageContext.request Método HTTP usado para ac- GET
.method} ceder a la página.
${pageContext.request Query de la página (el texto de p1=valor&p2=valor
.queryString} la URL que viene despues del
PATH)
${pageContext.request URL usada para acceder a la ht-
.requestURL} página. tp://localhost/app/pa
gecontext.jsp
${pageContext.session Contiene true si la sesión es true
.new} nueva, false si no lo es.
${pageContext.servlet Información sobre el contene- Tomcat 5.0.1
Context.serverInfo} dor JSP.

Pruebalo tu mismo, añade la página pageContext.jsp a tu aplicación con este contenido:

<%@include file="taglibs.jsp" %>


<html>
<body>
authType: <c:out value="${pageContext.request.authType}"/> <br/>
remoteUser: <c:out value="${pageContext.request.remoteUser}"/> <br/>
contextPath: <c:out value="${pageContext.request.contextPath}"/> <br/>
cookies: <c:out value="${pageContext.request.cookies}"/> <br/>
method: <c:out value="${pageContext.request.method}"/> <br/>
queryString: <c:out value="${pageContext.request.queryString}"/> <br/>
requestURL: <c:out value="${pageContext.request.requestURL}"/> <br/>
session.new: <c:out value="${pageContext.session.new}"/> <br/>

13
JSTL

serverInfo: <c:out value="${pageContext.servletContext.serverInfo}"/> <br/>


message: <c:out value="${pageContext.exception.message}"/>
</body>
</html>

Cuando visites http://127.0.0.1:8080/myApp/pageContext.jsp aparecerá algo como

authType:
remoteUser:
contextPath: /sampleJSTL
cookies: [Ljavax.servlet.http.Cookie;@1add463
method: GET
queryString:
requestURL: http://127.0.0.1:8080/sampleJSTL/pageContext.jsp
session.new: false
serverInfo: Apache Tomcat/4.1.29
message:

Vemos que varios valores aparecen en blanco:

• authType y remoteUser porque no estamos usando autentificación.

• queryString porque no hay parametros, prueba con pageCon-


text.jsp?var1=valor1&var2=valor2
[http://127.0.0.1:8080/myApp/pageContext.jsp?var1=valor1&var2=valor2].

• message porque no es una página de error, y por tanto no existe una excepción en el contexto
de página.

pageContext.errorData
En JSP 2.0, cuando se produce un error la excepción ocurrida está disponible en el ámbito re-
quest con el nombre javax.servlet.error.exception. Ademas, se adjunta al contexto
de la página, información adicional en forma de bean con nombre errorData. Este bean tiene las
siguientes propiedades:

Table 8.
Propiedad Tipo Java Descripción
requestURI String URI de la petición fallida.
servletName String Nombre de la página o servlet
que lanzó la excepción.
statusCode int Código HTTP del fallo.
throwable Throwable La excepción que produjo el
fallo.

Para declarar una página de error JSP que responda a un código o excepción, podemos usar el
web.xml:

<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
<error-page>
<exception-code>500</exception-code>
<location>/error.jsp</location>
</error-page>

14
JSTL

o una declaración para una página concreta:

<%@ page errorPage="/error2.jsp" contentType="text/html" %>

Ejemplo de página de error:

<%@ page isErrorPage="true" contentType="text/html" %>


<pre>
URI de la petición fallida: ${pageContext.errorData.requestURI}
Quien lanzo el error: ${pageContext.errorData.servletName}
Código del fallo: ${pageContext.errorData.statusCode}
Excepción: ${pageContext.errorData.throwable}
La misma excepción anterior: ${requestScope['javax.servlet.error.exception']}
</pre>

Para probarla podemos emplear esta otra página que lanza intencionadamente una excepción:

<%@ page errorPage="error.jsp" contentType="text/html" %>


<% if (true) throw new Exception("just do it!"); %>

El resultado será este:

URI de la petición fallida: /sampleJSTL/null.jsp


Quien lanzo el error: jsp
Código del fallo: 500
Excepción: java.lang.Exception: just do it!
La misma excepción anterior: java.lang.Exception: just do it!

Funciones EL
Las funciones representan un modo de extender la funcionalidad del lenguaje de expresiones. Se
usan dentro de cualquier expresión EL, ejemplo:

Mi nombre de usuario tiene ${fn:length(username)} letras.

En el descriptor de la biblioteca de funciones, se establece una correspondencia entre el nombre de


la función y un método estático de una clase Java: [PENDIENTE: explicar mejor como definir fun-
ciones de usuario]

<function>
<description>
Returns the number of items in a collection
or the number of characters in a string.
</description>
<name>length</name>
<function-class>
org.apache.taglibs.standard.functions.Functions
</function-class>
<function-signature>
int length(java.lang.Object)
</function-signature>
</function>

En JSTL 1.1 existen 16 funciones de manipulación de cadenas:

• Alternar una cadena entre mayúsculas/minúsculas: toLowerCase, toUpperCase.

• Obtener una subcadena: substring, substringAfter, substringBefore.

• Eliminar el espacio en blanco en ambos extremos de una cadena: trim.

15
JSTL

• Reemplazar caracteres en una cadena: replace.

• Comprobar si una cadena contiene a otra: indexOf, startsWith, endsWith, contains,


containsIgnoreCase.

• Convertir una cadena en array (split), o un array en cadena (join).

• Codificar los caracteres especiales del XML: escapeXml.

• Obtener la longitud de una cadena: length.

La función length también puede aplicarse a instancias de java.util.Collection, caso en


el cual, devolverá el número de elementos de una colección.

Todas las funciones EL interpretan las variables no definidas o definidas con valor igual a null,
como cadenas vacías.

fn:contains
Devuelve true si una cadena contiene a otra, false en caso contrario.

fn:contains(string, substring) # boolean

Si la cadena a buscar es vacía, siempre existirá coincidencia.

Ejemplo:

<%-- Muestra un mensaje si la variable query contiene la cadena 'sex' --%>


<c:if test="${fn:contains('sex', query)}">
Access control configuration prevents your request from being allowed.
Offending word: sex
</c:if>

fn:containsIgnoreCase
Devuelve true si una cadena contiene a otra sin distinguir entre minúsculas/mayúsculas, false
en caso contrario.

fn:containsIgnoreCase(string, substring) # boolean

Si la cadena a buscar es vacía, siempre existirá coincidencia.

Ejemplo:

<%-- Muestra un mensaje si 'james stratchan' es subcadena de username


sin distinguir entre mayúsculas o minúsculas. --%>
<c:set var="username" value="James Stratchan"/>
<c:if test="${fn:containsIgnoreCase('james stratchan', username)}">
Hi James Stratchan!
</c:if>

fn:endsWith
Devuelve true si una cadena termina con el sufijo indicado, false en caso contrario.

fn:endsWith(string, suffix) # boolean

Si la cadena a buscar es vacía, siempre existirá coincidencia.

Ejemplo:

16
JSTL

<c:set var="username" value="James Stratchan"/>


<c:if test="${fn:endsWith(username, 'tratchan')}">
Hi James Stratchan!
</c:if>

fn:escapeXml
Codifica los caracteres que podrían ser interpretados como parte de las etiquetas XML.

fn:escapeXml(string) # String

Es equivalente a c:out con atributo xmlEscape="true".

fn:indexOf
Devuelve el índice (empezando desde cero) dentro de una cadena donde comienza otra cadena espe-
cificada.

fn:indexOf(string, substring) # int

Si la cadena a buscar es vacía devuelve cero (comienzo de la cadena). Si la cadena a buscar no se


encuentra devuelve -1.

fn:join
Convierte en cadena los elementos de un array. El separador se usa para separar los elementos en la
cadena resultante.

fn:join(array, separator) # String

Si el array es nulo devuelve la cadena vacía.

fn:length
Devuelve el número de caracteres en una cadena, o de elementos en una colección.

fn:length(input) # integer

Devuelve cero para cadenas vacías.

fn:replace
Recorre una cadena (inputString) reemplazando todas las ocurrencias de una cadena (be-
foreSubstring) por otra (afterSubstring).

fn:replace(inputString, beforeSubstring, afterSubstring) # String

El texto reemplazado no es vuelto a procesar para realizar más reemplazos. Si afterSubstring


es vacía se eliminan todas las ocurrencias de beforeSubstring.

fn:split
Divide una cadena en subcadenas, usando como separador cualquier carácter de otra cadena. Los ca-
racteres de la segunda cadena no forman parte del resultado.

fn:split(string, delimiters) # String[]

17
JSTL

No se realiza reemplazo alguno cuando:

• La cadena a dividir es vacía (se devuelve la cadena vacía).

• La cadena de delimitadores es vacía (se devuelve la cadena original).

fn:startsWith
Comprueba si una cadena comienza por otra.

fn:startsWith(string, prefix) # boolean

Devuelve true si la cadena a buscar es vacía.

fn:substring
Devuelve un subconjunto de una cadena. Los índices comienzan en cero. La cadena resultante comi-
enza en beginIndex y llega hasta el caracter en endIndex-1 (incluido). La longitud de la ca-
dena es endIndex-beginIndex.

fn:substring(string, beginIndex, endIndex) # String

• Si beginIndex es menor que cero se ajusta su valor a cero.

• Si beginIndex es mayor que la longitud de la cadena se ajusta su valor a la longitud de la ca-


dena.

• Si endIndex es menor que cero o mayor que la longitud de la cadena, se ajusta su valor a la
longitud de la cadena.

• Si endIndex es menor que beginIndex se devuelve una cadena vacía.

fn:substringAfter
Devuelve la porción de una cadena que viene a continuación de cierta subcadena. La cadena
devuelta comienza en el siguiente caracter tras la subcadena buscada.

fn:substringAfter(string, substring) # String

Si no se encuentra la subcadena o si esta es vacía se devuelve la cadena original.

fn:substringBefore
Devuelve la porción de una cadena que viene antes de cierta subcadena. La cadena devuelta va
desde el primer carácter hasta el carácter anterior a la subcadena buscada.

fn:substringBefore(string, substring) # String

Si no se encuentra la subcadena o si esta es vacía se devuelve la cadena original.

fn:toLowerCase
Convierte todos los caracteres a minúsculas.

fn:toLowerCase(string) # String

18
JSTL

fn:toUpperCase
Convierte todos los caracteres a mayúsculas.

fn:toUpperCase(string) # String

fn:trim
Elimina el espacio en blanco en los extremos de una cadena.

fn:trim(string) # String

Etiquetas
Core
Etiquetas para iteración sobre datos, operaciones condicionales, e importación de datos de otras
páginas

c:out
Muestra el resultado de una expresión. Su funcionalidad es equivalente a la de <%= %>.

Table 9.
Atributo Descripción Requerido Por defecto
value información a mostrar sí ninguno
default información a mostrar no cuerpo
por defecto
escapeXml true si debe convertir no true
caracteres especiales a
sus correspondientes
entidades (por ejemplo,
&gt; para <).

Ejemplos:

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>


<c:out value="Hola mundo"/>
<c:out value="${variableInexistente}" default="la expresión fallo"/>
<c:out value="${variableInexistente}">
la expresión fallo
</c:out>

Para evitar que un nombre sea confundido con una expresión lo ponemos entre comillas:

<c:out value="${header['User-Agent']}" default="navegador no especificado"/>

Hemos usado comillas simples en User-Agent para que no se confundan con las comillas dobles
que delimitan el valor del atributo, también podríamos haber usado \"User-Agent\":

Ejemplo de creación dinámica de un documento XSL: [PENDIENTE: demasiado complejo para es-

19
JSTL

tar aqui?]

<c:import url="/xsl/main.xsl" var="main"/>


<c:set var="xsl">
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
<c:out value="${main}" escapeXml="false"/>
</xsl:stylesheet>
</c:set>

c:set

Table 10.
Atributo Descripción Requerido Por defecto
value Información a grabar. no cuerpo
target Nombre de la variable no ninguno
cuya propiedad será
modificada
property Propiedad a modificar no ninguna
var Nombre de la variable no ninguno
en la que guardar.
scope Ámbito de la variable no page
en la que grabar la
información (page,
request, session,
o application)

Ejemplos:

<%-- graba la variable cuatro=4 en el ámbito page --%>


<c:set var="cuatro" value="${2 + 2}"/>
<%-- equivalente al anterior pero con ámbito session --%>
<c:set var="cuatro" scope="session">
4
</c:set>
<%-- equivalente al anterior --%>
<c:set var="cuatro" scope="session">
<c:out value="4"/>
</c:set>

Si colocamos el valor en el cuerpo de la etiqueta, se suprimen los espacios del comienzo y final del
cuerpo.

c:remove

Table 11.
Atributo Descripción Requerido Por defecto
var Nombre de la variable a sí --
quitar.

20
JSTL

Atributo Descripción Requerido Por defecto


scope Ámbito de la variable a no todos los ámbitos
quitar.

Cuando no se especifica ámbito, la etiqueta busca en todos los ámbitos por turno, yendo del más es-
pecifico al más general (page, request, session, application), hasta encontrar una vari-
able con ese nombre. Si la variable no se encuentra, la etiqueta termina sin error.

c:if

Table 12.
Atributo Descripción Requerido Por defecto
test Condición a evaluar. sí --
Solo procesa el cuerpo
si es true.
var Nombre del atributo no ninguno
con el que grabar el res-
ultado booleano de la
condición.
scope Ámbito en el que expo- no page
ner el atributo anterior.

En el cuerpo es posible colocar otras etiquetas, incluyendo otras <c:if>. Es útil guardar el res-
ultado de evaluar la condición para evitar repetir los cálculos.

Ejemplos:

<c:if test="${pageContext.request.remoteUser == 'hpetra'}">päivää Petra!</c:if>

<%-- establece una variable a null,


que es lo mismo que no haberla definido --%>
<c:set var="nulo" value="${null}"/>
<%-- devuelve la cadena vacia --%>
<c:out value="${nulo}"/>
<%-- la condición es true en ambos casos --%>
<c:if test="${nulo == null}">la cadena es nula o no definida</c:if>
<c:if test="${nulo == variableNoDefinida}">la cadena es nula o no definida</c:if

c:choose, c:when, c:otherwise


No tiene atributos. Acepta como hijos uno o más <c:when>.

<c:when> tiene un atributo:

Table 13.
Atributo Descripción Requerido Por defecto
test Condición a evaluar sí --

<c:otherwise> no tiene atributos.

21
JSTL

Ejecuta el cuerpo de la primera etiqueta when cuya condición evalúe a true, o el cuerpo de la
etiqueta otherwise (si existe).

Ejemplos:

<c:choose>
<c:when test="${hour>=7 && hour<=12}"> morning </c:when>
<c:when test="${hour>12 && hour<=17}"> afternoon </c:when>
<c:when test="${hour>17 && hour<22}"> evening </c:when>
<c:otherwise>night</c:otherwise>
</c:choose>

c:forEach
Permite iterar sobre los elementos siguientes:

• Arrays de objetos o tipos primitivos.

• Instancias de java.util.Collection, java.util.Map, java.util.Iterator,


java.util.Enumeration.

• Cadenas delimitadas por comas.

• Instancias de javax.servlet.jsp.jstl.sql.Result (resultantes de una consulta SLQ


con JSTL).

Es posible anidar varias etiquetas c:forEach.

Table 14.
Atributo Descripción Requerido Por defecto
items Colección sobre la que no ninguno
iterar.
begin Elemento con el que no 0
empezar (0=primero).
end Elemento con el que no último
terminar (0=primero).
step Procesa solo cada step no 1 (todos)
elementos.
var Nombre del atributo no ninguno
con el que exponer el
elemento actual.
varStatus Nombre de la variable no ninguno
con la que exponer el
estado de la iteración.

La variable varStatus tiene propiedades que describen el estado de la iteración:

Table 15. Propiedades de la variable varStatus


Atributo Tipo Requerido
begin número El valor del atributo begin.
current número El elemento actual.
end número El valor del atributo end.

22
JSTL

Atributo Tipo Requerido


index número Índice del elemento actual den-
tro de la colección.
count número Número de iteración
(empezando en 1).
first boolean Indica si estamos en la primera
iteración.
last boolean Indica si estamos en la última
iteración.
step número El valor del atributo step.

Ejemplos:

<c:forEach items="${informe.filas}" var="fila">


<c:out value="${fila}"/>
</c:forEach>

Si se omite el atributo items, se itera sobre números:

<c:forEach begin="1" end="24" step="1" var="hour" varStatus="status">


<c:out value="${hour}"/>
<c:if test="${status.count == 19}">here comes your 19nth nervous breakdown!</c
<br/>
</c:forEach>

c:forTokens
Permite descomponer una cadena en tokens.

Analizar una cadena se llama parsing. Las partes en las que se descompone una cadena se llaman
tokens.

Table 16.
Atributo Descripción Requerido Por defecto
items Cadena sobre la que it- sí ninguno
erar
delims Caracteres delimita- sí ninguno
dores
var Nombre del atributo no ninguno
con el que exponer el
token actual

Los delimitadores que aparecen uno tras otro son tratados como si solo existiera uno.

Ejemplos:

<ul>
<c:forTokens items="Tinky Winki,Dipsy,Laa-Laa,Po" delims="," var="teletubbie">
<li><c:out value="${teletubbie}"/></li>
</c:forTokens>
</ul>

La salida de lo anterior es

23
JSTL

<ul>
<li>Tinky Winki</li>
<li>Dipsy</li>
<li>Laa-Laa</li>
<li>Po</li>
</ul>

Esto devuelve Dipsy,Laa-Laa que son los tokens con índice 2, y 3:

<c:forTokens items="Tinky Winki,Dipsy,Laa-Laa,Po" delims="," var="teletubbie"


begin="2" end="4">
<c:out value="${teletubbie}"/>
</c:forTokens>

Esto muestra el classpath de TOMCAT para esta aplicación web:

<c:forTokens items="${applicationScope['org.apache.catalina.jsp_classpath']}"
delims=";"
var="item">
<c:out value="${item}"/><br/>
</c:forTokens>

c:import, c:param
c:import
c:import proporciona toda la funcionalidad de jsp:include y añade otras:

• Permite incluir páginas de otros servidores.

• Permite guardar el texto leído en una variable.

Table 17.
Atributo Descripción Requerido Por defecto
url URL para importar la sí --
página. Es válido cu-
alquier protocolo so-
portado por
java.net.URL. Es
decir, al menos HTTP,
HTTPS, FTP, file, y
JAR.
context Barra (/) seguido del no contexto actual
nombre de la aplicación
local
var Nombre del atributo no muestra en página
con el que exponer el
texto importado.
scope Ámbito del atributo an- no page
terior.
charEncoding Juego de caracteres con no ISO-8859-1
el que importar los da-
tos.
varReader Nombre de una variable no ninguno
con la que exponer el

24
JSTL

Atributo Descripción Requerido Por defecto


java.io.Reader con que
se lee la URL.

En HTML, la URL relativa /images/smiley.jpg lee un fichero de la raiz del servidor web,
pero en JSTL, esa misma URL lee el fichero de la raíz de nuestra aplicación web. Si quisieramos
que la URL fuera relativa a otra aplicación Web usariamos

<c:import context="/otraApplicacion" url="/directorio/pagina.jsp"/>

Cuando dos páginas están en la misma aplicación web, comparten el mismo ámbito request,
session, y application. Si las páginas estan en diferente aplicación y son accedidas mediante
c:import, ambas comparten el ámbito request.

c:param
c:import puede tener hijos c:param, que se usan para pasar parametros a la URL a recuperar.
Los atributos de c:param son

Table 18.
Atributo Descripción Requerido Por defecto
name nombre del parametro sí --
value valor del parametro no cuerpo

Si quieres que un bean sea accesible en otra página, seria engorroso convertirlo en una cadena de
texto, es mejor usar c:set para guardar esta información.

Ejemplos
Cuando queremos reutilizar un texto lo grabamos en una variable:

<c:import url="http://creativecommons.org/licenses/by/1.0/ "


var="licencia"/>
<c:out value="${licencia}"/>

Podemos hacer que los contenidos leídos sirvan de entrada a otra etiqueta colocando c:import en
el cuerpo de dicha etiqueta (suponiendo que esta última lo admita):

<string:lowerCase>
<c:import url="pagina.jsp"/>
</string:lowerCase>

El siguiente c:import recupera la URL ht-


tp://www.universalmusic.fi/tiktak/index.php?id=tuotanto:

<c:import url="http://www.universalmusic.fi/tiktak/index.php">
<c:param name="id" value="tuotanto"/>
</c:import>

Página pagina1.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>


<html>
<body>
<c:import url="weather.jsp">
<c:param name="city" value="Madrid"/>

25
JSTL

</c:import>
El tiempo meteorológico fue importado de la página weather.jsp.
</body>
</html>

Página weather.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>


<c:import url="http://localhost:8080/weatherService.rest">
<c:param name="id" value="${param.city}"/>
</c:import>

c:redirect
Ejecuta un forward. Es decir, se para la ejecución de la página actual (no se ejecuta nada de lo que
este por debajo de esta instrucción) y el navegador es enviado a otra URL.

Sus atributos son

Table 19.
Atributo Descripción Requerido Por defecto
url URL a la que redirigir. sí --
context Barra (/) seguido del no contexto actual
nombre de una
aplicación local.

Ejemplos:

<c:redirect url="weatherPopUp.jsp"/>
<c:param name="city" value="Madrid"/>
</c:redirect>

<c:redirect context="/myOtherApp" url="/somePage.jsp">

c:url
Sirve para mostrar una URL o para grabarla en una variable. Sus atributos son:

Table 20.
Atributo Descripción Requerido Por defecto
value Base URL a mostrar o sí --
almacenar.
context Barra (/) seguido del no contexto actual
nombre de una
aplicación local.
var Nombre del atributo en no ningúno
el que exponer la URL.
scope Ámbito del atributo an- no page
terior.

Admite parámetros mediante c:param igual que en c:import.

26
JSTL

Esta etiqueta es útil por dos motivos:

• Preserva la información de sesión codificada en la URL.

• Permite usar URLs relativas a la aplicación web, no a la raíz del servidor.

Ejemplos:

<img src="<c:url value="/imagenes/smiley.gif"/>"/>

c:catch
Normalmente los errores en una página JSP interrumpen la ejecución de la página y se envían al
contenedor, que a su vez muestra un mensaje de error. La etiqueta c:catch permite capturar y
tratar los errores.

La alternativa a c:catch es usar páginas de error con JSP convencional.

Table 21.
Atributo Descripción Requerido Por defecto
var Variable para exponer no ninguno
información sobre el er-
ror.

Si hay un error en alguna sentencia del cuerpo de la etiqueta se interrumpe la ejecución y se con-
tinua después del catch.

Aquí intentamos parsear el número FDJ34rm4 pero obviamente se produce un error:

<%@include file="taglibs.jsp" %>


<c:catch var="error">
<fmt:parseNumber var="total" value="FDJ34rm4"/>
<%-- nunca llega aquí --%>
...
</c:catch>
<c:if test="${not empty error}">
I'm sorry Dave, Im afraid I can't parse that.
Error details: <c:out value="${error}"/>
</c:if>

Para que una página redirija a otra en caso de fallar su procesamiento basta con colocar esta dir-
ectiva en ella:

<%@ page errorPage="error.jsp" session="false" %>

Luego tendremos que crear la página de error, que deberá comenzar con esta línea:

<%@ page isErrorPage="true" %>

Un ejemplo de página de error con JSTL:

<%@ page isErrorPage="true" %>


<%@include file="taglibs.jsp" %>
</html>
<head>Incidencia en el sistema</head>
<body>

27
JSTL

El error fue..<br/>
<c:out value="${pageContext.exception.message}"/>
</body>
</html>

Bases de datos
Warning
Una aplicación es más mantenible si separa las capas de presentación, lógica, y acceso a
datos. Acceder a datos desde el JSP solo es recomendable para prototipos.

sql:DataSource

Table 22.
Atributo Descripción Requerido Por defecto
dataSource Base de datos a usar. no ningúno
driver Nombre de la clase JD- no ningúno
BC a usar como driver.
url URL de la base de da- no ningúno
tos.
user Nombre del usuario de no ningúno
la base de datos.
password Password del usuario no ningúno
de la base de datos.
var Nombre de la variable no ningúno
que representa la base
de datos.
scope Ámbito de la variable no page
anterior.

Si no usamos var o scope, el datasource declarado reemplaza al datasource por defecto. Esta
etiqueta no implementa pooling de conexiones, pero con ella podremos referenciar un dataSource
preexistente que sí lo implemente.

Para usar el driver de un fabricante, obviamente necesitaremos colocar en el classpath dicho driver.
Normalmente descargamos un archivo jar y lo colocamos en el WEB-INF/lib. Como ejemplo,
aqui están el de mysql [http://dev.mysql.com/downloads/connector/j/3.0.html], oracle
[http://otn.oracle.com/software/tech/java/sqlj_jdbc/index.html], y HSQL
[http://hsqldb.sourceforge.net/].

Ejemplo: Establecer un dataSource por defecto:

<sql:setDataSource driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test"
user="alicia"
password="secreto"/>

Ejemplos para otras bases de datos:

// Orace con driver JDBC tipo 4


<sql:setDataSource driver="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@maquina:puerto:instancia"
...

28
JSTL

// MySQL
<sql:setDataSource driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://maquina:puerto/baseDeDatos"
...
// HSQL
<sql:setDataSource driver="org.hsqldb.jdbcDriver"
url="jdbc:hsqldb:."
...
// Puente JDBC-ODBC de SUN con driver de SUN. No recomendado para producción.
// Usa el formato jdbc:odbc:<data-source-name>[;<attribute-name>=<attribute-valu
<sql:setDataSource driver="sun.jdbc.odbc.JdbcOdbcDriver"
url="jdbc:odbc:nombreDsn;UID=uid;PWD=password"
...

Creamos un dataSource y lo guardamos en una variable:

<sql:setDataSource driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test"
user="alicia"
password="secreto"
var="development1"/>

Cambiamos el dataSource por defecto al grabado en la variable anterior [TODO: request es el


ámbito por defecto?]:

<sql:setDataSource dataSource="${development1}"
scope="request" />

sql:query
Se usa para consultar la base de datos.

Table 23.
Atributo Descripción Requerido Por defecto
sql Consulta SQL a no si ponemos el SQL cuerpo
ejecutar. en el cuerpo de la
etiqueta
dataSource Proveedor de conex- no
iones.
startRow Primeras filas a ignorar no 0 (primero)
(ej: 10=ignora las diez
primeras filas).
maxRows Máximo número de no
filas.
var Variable con la que ex- sí ningúno
poner el resultado.
scope Ámbito de la anterior no page
variable.

Esta etiqueta no muestra datos, solo los graba en la variable indicada por var.

El atributo maxRows indica el número por defecto de filas a recuperar. Podemos asignar un valor a
este atributo para cambiar el límite de filas, o asignar -1 si no queremos límite.

29
JSTL

Las propiedades disponibles son:

• columnName: Lista de nombres de columnas. Podemos acceder a ella con paréntesis cuadrados
o iterando sobre ella.

• limitedByMaxRows: Booleano que indica si el resultado contenía más de las filas indicadas
por maxRows.

• rows: Acceso a filas usando por nombre.

• rowsByIndex: Acceso a filas por índice.

• rowCount: Número de filas.

Ejemplo:

<sql:query var="users">
SELECT * FROM USERS
</sql:query>

Forma equivalente a la anterior:

<sql:query var="users" sql="SELECT * FROM USERS"/>

Suponiendo que el SQL este en una variable:

<sql:query var="users" sql="${sql}"/>

Podemos usar otras etiquetas para proporcionar una consulta SQL en el cuerpo de la etiqueta.
Supongamos que por algún motivo te interesa mantener todas las consultas en un fichero XML y
quieres recuperar la consulta que devuelve todos los usuarios:

<x:parse var="doc">
<query>
<getAllUsers>
SELECT * FROM users
</getAllUsers>
</query>
<x:parse>
<sql:query var="doc">
<x:out select="$doc/query/getAllUsers"/>
</sql:query>

Vamos a acceder por nombre a la primera columna y por índice a la segunda:

<sql:query var="savvyUsers">
SELECT name, phone_extension FROM USERS WHERE CLUE > 0
</sql:query>
<ul>
<c:forEach items="${savvyUsers.rows}" var="row">
<li>
<c:out value="${row.name}"/>,
<c:out value="${row[1]}"/>
</li>
</c:forEach>
</ul>

Almacena un máximo de 10 resultados e indica si había más de 10 resultados:

30
JSTL

<sql:query var="users" maxRows="10">


SELECT * FROM USERS
</sql:query>
<c:if test="${users.limitedByMaxRows}">
El resultado contiene más filas de las mostradas.
</c:if>

sql:update
Se usa para modificar la base de datos.

Table 24.
Atributo Descripción Requerido Por defecto
sql consulta SQL a ejecutar no cuerpo
dataSource proveedor de conex- no
iones
var variable para guardar el no ningúno
número de filas actual-
izadas
scope ámbito de la anterior no page
variable

Varios ejemplos:

<sql:update>
INSERT INTO citas
SET cita = "es reinventar el tornillo, digo.. la rueda, bueno, y el tornillo
autor = "Luis"
date = "2004-03-03";
</sql:update>
<sql:update sql="DELETE FROM citas WHERE autor = 'Luis'"/>
<sql:update var="n">
DELETE FROM citas
WHERE autor = 'Luis'
</sql:update>
Hemos borrado <c:out value="${n}"/> filas.

sql:param
Se usa para pasar parámetros a las consultas ajustando la codificación de caracteres de forma segura.

Table 25.
Atributo Descripción Requerido Por defecto
value valor del parámetro no cuerpo

La etiqueta sql:param sustituirá los caracteres ? de las sentencias SQL. Los caracteres ?
únicamente pueden usarse para sustituir un valor (string, número, u otro) en un comando SQL.

Ejemplo:

<sql:update>

31
JSTL

INSERT INTO PEOPLE(NAME, AGE, WEIGHT) VALUES(?,?,?)


<sql:param value="${userName}"/>
<sql:param value="${userAge}"/>
<sql:param>
<x:out select="${userWeight}"/>
</sql:param>
</sql:update>

¿Porque es importante?
Al pasar parametros a una consulta es importante ajustar la codificación de caracteres de forma se-
gura para evitar el problema de inyección de código SQL.

Supongamos la típica página de login/password que traslada directamente el valor de los campos del
formulario a la sentencia SQL:

SELECT FROM users WHERE user='fulano' AND password='secreto';

¿Pero que ocurre si en ponemos una comilla simple en el campo usuario? No he encontrado un
ejemplo real en JSP para ilustrar este comportamiento, pero valga esta Web en ASP:

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'


[Microsoft][ODBC SQL Server Driver][SQL Server]
Comilla no cerrada antes de la cadena de caracteres '' AND Passwd =''.
/login.asp, línea 30

La sentencia es incorrecta, y además el mensaje de error muestra datos sobre las interioridades de la
aplicación. Si volvemos a probar introduciendo esta cadena en el campo usuario

' OR Passwd<>'

El resultado de la query será

SELECT FROM xxxxx WHERE xxxxx='' OR Passwd<>'' AND Passwd='';

Observa que he puesto xxxxx en los campos que no conozco, pero tampoco me importa porque con
gracias al OR, estoy forzando a devolver el contenido completo de la tabla. Probablemente el pro-
grama lea el primer usuario de la lista devuelta y asuma que esa es nuestra identidad, lo que puede
propiciar actos criminales, y multas por no proteger adecuadamente los datos de los usuarios del sis-
tema.

sql:dateParam

Table 26.
Atributo Descripción Requerido Por defecto
value fecha a sustituir en el sí --
carácter ?
type time, date, o timestamp no timestamp

Ejemplo:

<sql:query>
SELECT * FROM USERS

32
JSTL

WHERE BIRTHDAY < ?


<sql:dateParam value="${myBirthday}"/>
</sql:query>

sql:transaction
Se usa para lanzar actualizaciones y consultas bajo una transacción. Para ello las sentencias
sql:update y sql:query se colocan como cuerpo de esta etiqueta. Todas las sentencias en una
transacción tienen éxito o fallan como unidad, es decir si alguno de ellos falla se realiza un rollback
de todos, y la base de datos queda como antes de comenzar la transacción.

En el cuerpo también podemos poner texto estático, o cualquier etiqueta JSP. Si ocurre algún error
en alguna etiqueta del cuerpo, la transacción realiza un rollback.

Table 27.
Atributo Descripción Requerido Por defecto
dataSource DataSource proveedor no
de conexiones.
isolation Nivel de aislamiento. no

El dataSource de esta etiqueta será usado por todas las etiquetas contenidas en el cuerpo, independi-
entemente de que en ellas se especifique un dataSource diferente. Esto es así porque las transac-
ciones están vinculadas por definición a una única conexión.

Los niveles de aislamiento son los mismos que en JDBC:

Table 28.
nivel dirty read? nonrepeatable reads? phantom reads?
read_uncommitted -- -- --
read_committed evitado -- --
repeatable_read evitado evitado --
serializable evitado evitado evitado

• dirty read es una lectura de filas que aun no han sido confirmadas (commited) por otra
transacción.

• nonrepeatable read ocurre cuando el mismo SELECT devuelve resultados diferentes


dentro de una misma transacción.

• phantom read es como una nonrepeatable read, pero solo ocurre respecto a filas que
han sido añadidas desde la primera lectura, no en filas que hayan sido modificadas.

El modo serializable ofrece la mayor protección pero a mayor protección, menor rendimiento.

Ejemplo:

<%--
Adding New User Accounts to MySQL
http://dev.mysql.com/doc/mysql/en/Adding_users.html
--%>
<sql:setDataSource driver="com.mysql.jdbc.Driver"

33
JSTL

url="jdbc:mysql://localhost:3306/test"
user="alicia"
password="secreto"
var="testDatabase"/>
<sql:transaction dataSource="${testDatabase}">
<sql:update>
GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost'
IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
</sql:update>
<sql:update>
GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%'
IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
</sql:update>
</sql:transaction>

I18n y formateo
La internacionalización (i18n) consiste en preparar una aplicación para que funcione en distintos
idiomas (incluyendo formateo de fecha y moneda).

i18n
fmt:bundle
Permite cargar recursos de mensajes específicos solo para una zona de la página. Ver
fmt:message.

Table 29.
Atributo Descripción Requerido Por defecto
basename Nombre del recurso a sí ninguno
usar.
prefix Cadena a usar como no ninguno
prefijo de cada clave.

Ejemplo:

<fmt:bundle basename="ApplicationResources">
<fmt:message key="welcome.user"/>
</fmt:bundle>

fmt:message
Acepta una clave y devuelve el resultado correspondiente a la clave en el fichero de recursos espe-
cificado.

Table 30.
Atributo Descripción Requerido Por defecto
key Clave. no cuerpo
bundle Recurso. no
var Variable en la que no ninguno
guardar el resultado.
scope Ámbito de la variable no page
anterior.

34
JSTL

El recurso consiste en un fichero de texto accesible a través del classpath que contiene pares
nombre=valor como los usados en la clase java.util.Properties. Por ejemplo:

welcome.user = Hola ${0}!


label.password = contraseña

La cadena ${0} es un parametro que podemos pasar a la cadena leída para personalizar el mensaje.
Para ello se usa la etiqueta fmt:param que veremos más adelante. Por ejemplo, suponiendo un ob-
jeto usuario con un campo nombre, podríamos obtener la cadena Hola Jano! (suponiendo que
Jano es el valor del campo nombre) con el siguiente código:

<fmt:message key="welcome.user">
<fmt:param value="${usuario.nombre}"/>
</fmt:message>

El nombre del recurso debe establecerse

• con la etiqueta fmt:setBundle,

• etiqueta fmt:bundle,

• o añadiéndolo como parametro del web.xml con clave


javax.servlet.jsp.jstl.fmt.localizationContext.

El nombre del fichero cargado por esta será nombre_XX.properties, donde XX es el locale
activo. Es decir, si el nombre es ApplicationResources, y el locale activo es en, se intentará
cargar el fichero ApplicationResources_en.properties del classpath, y si no se encuen-
tra, se probará con el nombre por defecto ApplicationResources.properties.

Ejemplo de uso estableciendo un fichero de recursos por defecto:

<fmt:setBundle basename="ApplicationResources"/>
<fmt:message key="label.password"/>

Ejemplo de uso estableciendo temporalmente un fichero de recursos:

<fmt:bundle basename="ApplicationResources">
<fmt:message key="label.password"/>
</fmt:bundle>

Ejemplo de uso estableciendo un fichero de recursos por defecto en el web.xml:

<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>ApplicationResources</param-value>
</context-param>

<fmt:message key="label.password"/>

fmt:param
Algunos mensajes aceptan parámetros, de forma parecida a los PreparedStatement de SQL.
Ver fmt:message.

Table 31.

35
JSTL

Atributo Descripción Requerido Por defecto


value Parametro a añadir. no cuerpo

Ejemplo:

<fmt:message key="welcome.user">
<fmt:param value="${usuario.nombre}"/>
</fmt:message>

fmt:setBundle
Permite cargar recursos de mensajes específicos. Ver fmt:message.

Table 32.
Atributo Descripción Requerido Por defecto
basename Nombre del recurso a sí ninguno
usar.
var Variable en la que gra- no ninguno
bar el recurso.
scope Ámbito de la variable no page
anterior.

Ejemplo:

<fmt:setBundle basename="ApplicationResources"/>
<fmt:message key="welcome.user"/>

fmt:setLocale

Table 33.
Atributo Descripción Requerido Por defecto
value Nombre del locale, o sí ninguno
instancia de

36
JSTL

Atributo Descripción Requerido Por defecto


.
variant Variedad, ejemplo: no ninguno
WIN, o MAC.
scope Ámbito de aplicación no page
de esta etiqueta.

El valor del locale se compone del código del lenguaje según el ISO-639
[http://www.loc.gov/standards/iso639-2/englangn.html] y el código del país según el ISO-3166
[http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html] separados
por un carácter de subrayado.

Ejemplo:

<fmt:setLocale value="es_ES" scope="session"/>

Si no establecemos un locale con esta etiqueta, el valor por defecto es el enviado por la cabecera
Accept-Language del navegador. Si tal cabecera no esta presente se toma el locale de la
máquina virtual donde se ejecuta el contenedor JSP.

fmt:requestEncoding ??

Formateo
fmt:formatNumber
Funciona como c:out pero permitiendo más control sobre el formato. Su uso básico es

<fmt:formatNumber value="${variable}"/>

que hace lo mismo que c:out pero comprueba el idioma del navegador (lo lee a través de la
cabecera Accept-Language) para mostrar correctamente la cantidad.

Por ejemplo, este código muestra el idioma preferente del navegador y formatea un número:

<c:out value="${header['Accept-Language']}"/>
<fmt:formatNumber value="1234567.89"/>

el resultado para un navegador español será

es 1.234.567,89

mientras que para uno inglés será

en 1,234,567.89

Table 34.
Atributo Descripción Requerido Por defecto
value Valor numérico a form- no cuerpo
atear.
type Si mostrar números, no number (puede ser
monedas, o porcentajes. number, currency,
o percent)
currencyCode Código de moneda no ningúno
ISO-2417 (ver bsi-

37
JSTL

Atributo Descripción Requerido Por defecto


global.com
[http://www.bsi-global.
com/iso4217currency]).
Solo funciona en
JDK1.4 o superior.
currencySymbol Símbolo de la moneda no ningúno
(por ejemplo $).
groupingUsed Si agrupar o no los no true
dígitos antes del punto
decimal.
maxIntegerDigits Máximo número de no ningúno
dígitos a mostrar.
minIntegerDigits Mínimo número de no ningúno
dígitos a mostrar.
maxFractionDi- Máximo número de no ningúno
gits dígitos fraccionarios a
mostrar.
minFractionDi- Mínimo número de no ningúno
gits dígitos fraccionarios a
mostrar.
pattern Patrón con el formateo no ningúno
del número. Sigue la
convención de
java.util.Decima
lFormat.
var Variable en la que gra- no ningúno
bar el resultado.
scope Ámbito de la anterior no page
variable.

En JDK 1.4, el atributo currencyCode tiene preferencia sobre el atributo currencySymbol.


En versiones anteriores ocurre al contrario.

Ejemplos para tipos de valores

<fmt:formatNumber value="1234567.89" type="number"/>


1,234,567.89
<fmt:formatNumber value="1234567.89" type="currency"/>
$1,234,567.89
<fmt:formatNumber value="1234567.89" type="percent"/>
123,456,789%

Ejemplos para valores de tipo moneda:

<fmt:formatNumber value="1234567.89" type="currency"/>


$123,456,789
<fmt:setLocale value="es"/>
<fmt:formatNumber value="1234567.89" type="currency"/>
¤123,456,789
<fmt:formatNumber value="1234567.89" type="currency" currencySymbol="€"/>
€1,234,567.89
<fmt:formatNumber value="1234567.89" type="currency" currencyCode="EUR"/>
EUR1,234,567.89

38
JSTL

<fmt:formatNumber value="1234567.89" type="currency" currencyCode="EUR" currency


EUR1,234,567.89

Ejemplos para agrupación y número de dígitos:

<fmt:formatNumber value="1234567.89" groupingUsed="true"/>


1,234,567.89
<fmt:formatNumber value="1234567.89" groupingUsed="no"/>
1234567.89

Ejemplos para número de dígitos:

<fmt:formatNumber value="1234567.89" maxIntegerDigits="5"/>


34,567.89
<fmt:formatNumber value="1234567.89" minIntegerDigits="10"/>
0,001,234,567.89
<fmt:formatNumber value="1234567.89" maxFractionDigits="1"/>
1,234,567.9
<fmt:formatNumber value="1234567.89" minFractionDigits="5"/>
1,234,567.89000

Ejemplo de patrón:

1.2345679E6
<fmt:formatNumber value="1234567.89" pattern="##0.#####E0"/>

El formato de los patrones es el mismo que el empleado en la clase DecimalFormat


[http://java.sun.com/j2se/1.4.2/docs/api/java/text/DecimalFormat.html].

fmt:formatDate
No acepta valores en el cuerpo. Requiere un atributo value con una variable que represente una
fecha (conviene usar fmt:parseDate). Un modo rápido de crear una variable con una fecha es
instanciar java.util.Date como bean:

<jsp:useBean id="ahora" class="java.util.Date"/>


<fmt:formatDate value="${ahora}"/>

Table 35.
Atributo Descripción Requerido Por defecto
value Fecha a mostrar. sí ningúno
type Si mostrar fechas, horas no date (puede ser
o ambos. date, time, o both)
dateStyle Estilo preferido para la no default (puede ser
fecha. default, short,
medium, long)
timeStyle Estilo preferido para el no default (puede ser
tiempo. default, short,
medium, long)
timeZone Zona horaria usada para no Posibles valores
formatear la fecha. [http://www.timeanddat
e.com/library/abbreviati
ons/timezones/]

39
JSTL

Atributo Descripción Requerido Por defecto


pattern Patrón de formateo. no Ninguno. Ver SimpleD-
ateFormat
[http://java.sun.com/j2s
e/
1.4.2/docs/api/java/text/
SimpleDate-
Format.html].
var Variable en la que gra- no ningúno
bar el resultado.
scope Ámbito en el que gra- no page
bar la variable anterior.

El atributo timeZone permite especificar la zona horaria de una fecha. Puede tomar como valor
cualquier abreviatura de las zonas horarias
[http://www.timeanddate.com/library/abbreviations/timezones/].

Ejemplos para tipo de fecha:

<jsp:useBean id="now" class="java.util.Date"/>


Sep 5, 2004
<fmt:formatDate value="${now}" type="date"/>
5:00:30 PM
<fmt:formatDate value="${now}" type="time"/>
Sep 5, 2004 5:00:30 PM
<fmt:formatDate value="${now}" type="both"/>

Ejemplos para estilo de fecha:

<jsp:useBean id="now" class="java.util.Date"/>


Sep 5, 2004
<fmt:formatDate value="${now}" type="date" dateStyle="default"/>
9/5/04
<fmt:formatDate value="${now}" type="date" dateStyle="short"/>
Sep 5, 2004
<fmt:formatDate value="${now}" type="date" dateStyle="medium"/>
September 5, 2004
<fmt:formatDate value="${now}" type="date" dateStyle="long"/>

Ejemplos para estilo de hora:

5:25:33 PM
<fmt:formatDate value="${now}" type="time" timeStyle="default"/>
5:25 PM
<fmt:formatDate value="${now}" type="time" timeStyle="short"/>
5:25:33 PM
<fmt:formatDate value="${now}" type="time" timeStyle="medium"/>
5:25:33 PM CEST
<fmt:formatDate value="${now}" type="time" timeStyle="long"/>

El atributo pattern sigue la convención fijada para la clase SimpleDateFormat


[http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html]:

40
JSTL

Table 36.
Caracter Descripción Ejemplo
yy Año corto. 02
yyyy Año completo. 2002
M Número del més. 4
MM Número de més con dos dígitos. 04
MMM Nombre corto del més. Apr
MMMM Nombre del més. April
d Día del mes. 5
dd Día del més con dos dígitos. 05
EE Nombre corto del día. Fri
EEEE Nombre del día. Friday
H Hora en formato militar. 21
HH Hora en formato militar con dos 21
dígitos.
h Hora (1-12). 9
hh Hora (1-12) con dos dígitos. 09
m Minuto. 4
mm Minuto con dos dígitos. 04
s Segundo. 6
ss Segundo con dos dígitos. 06
S Milisegundo. 249
a AM / PM PM
zz Nombre corto de zona horaria. EST
zzzz Zona horaria. Eastern Standard Time
Z Descripción de zona horaria. -0500
'cadena' Cadena a incluir. 'cadena'

Ejemplos de patrones:

Table 37.
Patrón Resultado
yyyy.MM.dd G 'at' HH:mm:ss z 2004.09.05 AD at 18:06:56 CEST
EEE, MMM d, ''yy Sun, Sep 5, '04
h:mm a 6:06 PM
hh 'o''clock' a, zzzz 06 o'clock PM, Central European
Summer Time
K:mm a, z 6:06 PM, CEST
yyyyy.MMMMM.dd GGG hh:mm aaa 02004.September.05 AD 06:06 PM
EEE, d MMM yyyy HH:mm:ss Z Sun, 5 Sep 2004 18:06:56 +0200
yyMMddHHmmssZ 040905180656+0200

fmt:parseNumber

41
JSTL

Interpreta cadenas como números. Es necesario para pasar valores numéricos a algunas etiquetas
como sql:param, fmt:formatNumber, y otras.

Table 38.
Atributo Descripción Requerido Por defecto
value Cadena a interpretar no cuerpo
como número.
type Como interpretarlo. no number (puede ser
number, currency,
o percent)
integerOnly Si descartar decimales. no false
pattern Patrón de formato. no ningúno. Ver SimpleD-
ateFormat
[http://java.sun.com/j2s
e/
1.4.2/docs/api/java/text/
SimpleDate-
Format.html].
parseLocale Locale a usar. no
var Variable en la que gra- no ningúno
bar el resultado.
scope Ámbito de la variable no page
anterior.

Ejemplo:

java.util.Date.getTime() devuelve el número de milisegundos


transcurridos desde 1 enero 1970 00:00:00 GMT, que son ahora:
<jsp:useBean id="date" class="java.util.Date" />
<fmt:formatNumber value="${date.time}" />

fmt:parseDate
Interpreta cadenas como fechas. Usa el locale del contenedor JSP.

Table 39.
Atributo Descripción Requerido Por defecto
value Fecha a mostrar. no cuerpo
type Si mostrar fechas, horas no date
o ambos.
dateStyle Estilo preferido para la no default (puede ser
fecha. default, short,
medium, long)
timeStyle Estilo preferido para el no default (puede ser
tiempo. default, short,
medium, long)
timeZone Zona horaria usada para no Ningúno. Posibles
formatear la fecha. valores
[http://www.timeanddat
e.com/library/abbreviati
ons/timezones/].
pattern Patrón de formateo. no Ningúno. Ver SimpleD-

42
JSTL

Atributo Descripción Requerido Por defecto


ateFormat
[http://java.sun.com/j2s
e/
1.4.2/docs/api/java/text/
SimpleDate-
Format.html].
parseLocale Locale a usar. no
var Variable en la que gra- no ningúno
bar el resultado.
scope Ámbito en el que gra- no page
bar la variable anterior.

Ver los identificadores de zonas horarias en ht-


tp://java.sun.com/j2se/1.4/docs/api/java/util/TimeZone.html.

fmt:setTimeZone
Permite cambiar la zona horaria:

Table 40.
Atributo Descripción Requerido Por defecto
value Identificador de la zona sí Ninguno. Posibles
horaria, o instancia de valores
java.util.TimeZo [http://www.timeanddat
ne. e.com/library/abbreviati
ons/timezones/].
var Variable en la que no ningúno
guardar la zona horaria.
scope Ámbito de la variable. no page

Los posible valores del atributo value son los correspondientes al método estático
java.util.TimeZone.getAvailableIDs().

Ejemplo:

<fmt:setTimeZone value="GMT"/>

fmt:timeZone
Permite cambiar temporalmente la zona horaria. Se usa colocando en el cuerpo de la etiqueta, las in-
strucciones que queremos que se ejecuten en la nueva zona horaria.

Table 41.
Atributo Descripción Requerido Por defecto
value Identificador de la zona sí Ningúno. Posibles
horaria. valores
[http://www.timeanddat
e.com/library/abbreviati
ons/timezones/].

Ejemplo:

43
JSTL

<fmt:timeZone value="GMT">
<jsp:useBean id="ahora" class="java.util.Date"/>
<fmt:formatDate value="${ahora}"/>
</fmt:timeZone>

XML
XPath en JSTL
La librería XML de JSTL usa XPath para obtener partes de los documentos XML con que opera. Si
no conoces XPath, hay un pequeño tutorial en la última sección de este documento.

En JSTL, cuando una expresión XPath devuelve algún nodo, se considera true, si no, false.

Una variable XPath tiene el formato $nombre, o el formato $nombre1:nombre2. Por ejemplo:
$sessionScope:usuario. En JSTL podemos usar los siguientes espacios de nombres para las
variables:

Table 42.
Prefijo Significado
pageScope variables de ámbito página
requestScope variables de ámbito request
sessionScope variables de ámbito session
applicationScope variables de ámbito application
param parametros del request como cadenas
header cabeceras del request http como cadenas
initParam parametros de inicialización del contexto
cookie valores de las cookies

x:parse
Antes de poder usar un fichero XML debemos interpretarlo, o dicho en spanglish, parsearlo. Parsear
es el proceso de analizar la sintaxis de la información y convertirla a un formato más manejable.

Para parsear un documento xml en JSTL se usa x:parse.

Table 43.
Atributo Descripción Requerido Por defecto
xml Texto XML a parsear. no cuerpo
Debe ser una cadena o
una instancia de
java.io.Reader.
var Nombre de la variable no ningúno
con la que exponer el
documento. El objeto
resultante cumple el in-
terfaz
org.w3c.dom.Docu
ment.
scope Ámbito con el que ex- no page
poner la variable anteri-

44
JSTL

Atributo Descripción Requerido Por defecto


or.
systemId URI del documento ori- no ningúno
ginal con la que resolv-
er las entidades.
filter Instancia de no ningúno
org.xml.sax.XMLF
ilter para filtrar el
documento.
varDom Nombre de la variable no ningúno
con la que exponer el
documento DOM.
scopeDom Ámbito con el que ex- no ningúno
poner la variable anteri-
or.

Si usamos el atributo xml, el cuerpo de la etiqueta debe estar vacío.

Normalmente importaremos el XML:

<c:import var="noticias" url="http://www.javahispano.org/noticias.rdf"/>


<x:parse xml="${noticias}" var="noticiasRDF"/>

Este es un método equivalente a lo anterior:

<x:parse var="noticiasRDF">
<c:import url="http://www.javahispano.org/noticias.rdf"/>
</x:parse>

Tras ejecutar el c:import anterior aparece un documento XML en el cuerpo. Tambien podemos
escribirlo explicitamente:

<x:parse var="transmision">
<correo>
<de>hal9000@discovery.gov</de>
<mensaje>All these worlds are yours except europa.</mensaje>
</correo>
<x:parse>

Para referirnos al elemento mensaje del XML anterior usariamos


$transmision/correo/mensaje. En general, podemos usar cualquier variable conteniendo
un documento XML seguida de cualquier expresión XPath.

x:out
Evalúa y muestra el resultado de una expresión XPath.

Table 44.
Atributo Descripción Requerido Por defecto
select Expresión XPath. sí --
escapeXml Muestra ciertos carac- no true
teres como entidades.

Ejemplo:

45
JSTL

<x:parse var="mailfeed">
<mail>
<received>
<from>mta04ps.bigpond.com</from>
<by>smtp01-01.mesa1.secureserver.net</by>
</received>
<received>
<from>lerc-daemon.mta04ps.email.bigpond.com</from>
<by>mta04ps.email.bigpond.com</by>
</received>
<subject>[SPAM] CONGRATULATION LUCKY WINNER</subject>
</mail>
</x:mail>

Para mostrar el contenido del elemento subject usamos:

<x:out select="$mailfeed/mail/subject"/>

x:set
Guarda el resultado de una expresión XPath en una variable.

Table 45.
Atributo Descripción Requerido Por defecto
select Expresión XPath. sí --
var Variable en la que no ningúno
guardar el resultado de
la expresión XPath.
scope Ámbito en el que expo- no page
ner la variable anterior.

Ejemplo:

<x:parse var="DecentralizingREST">
<dissertation>
<title>
Extending the REpresentational State Transfer (REST)
Architectural Style for Decentralized Systems
</title>
<author>
<first>Rohit</first>
<last>Kare</last>
</author>
</dissertation>
</x:parse>
<x:set var="autor" select="$DecentralizingREST/dissertation/author"/>

La variable autor contiene el siguiente subconjunto del documento anterior:


<author><first>Rohit</first><last>Kare</last></author>.

x:if

Table 46.

46
JSTL

Atributo Descripción Requerido Por defecto


select Expresión XPath a sí --
evaluar. El cuerpo solo
se procesa si resulta
true.
var Variable en la que no ningúno
guardar el resultado
booleano de la
expresión XPath.
scope Ámbito en el que expo- no page
ner la variable anterior.

Hay motivos por los que es útil guardar la expresión en una variable:

• Para no perder tiempo reevaluando la condición.

• Cuando la condición va a cambiar y queremos conservar el resultado.

Ejemplo:

<x:parse var="RESTpapers">
<paper>
<dissertation>
<title>
Extending the REpresentational State Transfer (REST)
Architectural Style for Decentralized Systems
</title>
<author>
<first>Rohit</first>
<last>Kare</last>
</author>
</dissertation>
</paper>
</x:parse>
<x:if select="$RESTpapers/paper//author/last[text()='Kare'">
At least one paper from Rohit Kare.
</x:if>

x:choose, x:when, x:otherwise


Funcionan de modo similar a sus equivalentes de la librería core.

<c:when> tiene un atributo:

Table 47.
Atributo Descripción Requerido Por defecto
select Expresión XPath a sí ninguno
evaluar. Si es true
procesa el cuerpo.

En el ejemplo que vimos en la etiqueta anterior, usariamos este código para mostrar un mensaje
según el autor de cada documento:

<x:choose>
<x:when select="$RESTpapers/paper//author/last[text()='Kare'">

47
JSTL

Rohit Kare is a random guy from Caltech


</x:when>
<x:when select="$RESTpapers/paper//author/last[text()='Stratchan'">
James Stratchan is a folk working on 20+ open source projects. wow.
</x:when>
<x:otherwise>
Unknown
</x:otherwise>
</x:choose>

x:forEach
Se usa para iterar sobre los elementos XML resultantes de ejecutar una expresión XPath.

Table 48.
Atributo Descripción Requerido Por defecto
select Expresión XPath sobre sí ningúno
cuyos resultados vamos
a iterar.
var Nombre de la variable no ningúno
con la que exponer el
nodo actual.

En cada iteración, el elemento correspondiente sirve de contexto respecto al que hacen referencia to-
das las expresiones del cuerpo. Si se anidan las etiquetas x:forEach, las etiquetas internas haran
referencia al contexto de la iteración de la etiqueta externa.

Volviendo al ejemplo de secciones anteriores:

<x:parse var="RESTpapers">
<paper>
<dissertation>
<title>
Extending the REpresentational State Transfer (REST)
Architectural Style for Decentralized Systems
</title>
<author>
<first>Rohit</first>
<last>Kare</last>
</author>
</dissertation>
</paper>
</x:parse>

Mostremos el título de cada documento:

<x:forEach select="$RESTpapers//title">
<p><x:out select="."/></p>
</x:forEach>

En el atributo select de las etiquetas foreach y out podemos usar cualquier expresión XPath.

Ahora un ejemplo que lee muestra una lista con las últimas noticias
[http://www.javahispano.org/noticias.rdf] de javaHispano [http://www.javahispano.org]:

<c:import var="noticias" url="http://www.javahispano.org/noticias.rdf"/>


<x:parse var="doc" xml="${noticias}"/>
<ul>
<x:forEach select="$doc//*[name()='item']">

48
JSTL

<li>
<a href="<x:out select="./*[name()='link']"/>">
<x:out select="./*[name()='title']" />
</a>
</li>
</x:forEach>
</ul>

x:transform
La etiqueta x:trasform sirve para aplicar XSLT al XML.

Table 49.
Atributo Descripción Requerido Por defecto
result ?? [PENDIENTE] ?? ??
scope Ámbito con el que ex- no page
poner la variable anteri-
or.
var Nombre de la variable no ninguno
con la que exponer el
documento resultante.
El objeto resultante
cumple el interfaz
org.w3c.dom.Docu
ment.
xml Documento XML a no cuerpo
transformar. Debe ser
una cadena o una in-
stancia de
java.io.Reader.
xslt Hoja de estilo XSLT a sí --
aplicar.

Si colocamos un objeto javax.xml.transform.Result en el atributo result, y no espe-


cificamos var ni scope, el resultado de la transformación se guardará en un objeto del tipo men-
cionado.

Ejemplo:

<c:import var="xml" url="${urlXML}"/>


<c:import var="xsl" url="${urlXSL}"/>
<x:transform xml="${xml}" xslt="${xsl}"/>

Puedes encadenar transformaciones, por ejemplo, docbook --> javahispano --> XHTML -->
XHTML + CSS :

<x:transform var="javahispano" xml="${docbook}" xslt="${docbook2jh}"/>


<x:transform var="xhtml" xml="${javahispano}" xslt="${jh2xhtml}"/>
<x:transform var="styledXHTML" xml="${xhtml}" xslt="${summerStyle}"/>

Si anidamos las etiquetas no es necesario usar variables temporales:

<x:transform xslt="${summerStyle}">
<x:transform xslt="${jh2xhtml}">
<x:transform xslt="${docbook2jh}" xml="${docbook}"/>
</x:transform>

49
JSTL

</x:transform>

Podemos definir el xml y xsl dentro de la misma página: [PENDIENTE: copiar transformación del
informe]

<c:set var="xml">
...[PENDIENTE]
</c:set>
<c:set var="xsl">
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
...[PENDIENTE]
</xsl:stylesheet>
</c:set>
<x:transform xml="${xml}" xslt="${xsl}"/>

x:param
Permite declarar parametros para su uso en hojas de estilo. Una hoja de estilo XSLT puede declarar
variables con la etiqueta <xsl:param> y también aceptarlos de fuentes externas a la hoja de es-
tilo.

Table 50.
Atributo Descripción Requerido Por defecto
name nombre del parametro sí ninguno
value valor del parametro no cuerpo

Los parámetros permiten personalizar hojas de estilo. Como ejemplo, estos son los posibles
parámetros [http://docbook.sourceforge.net/release/xsl/current/doc/html/] de las hojas de estilo Doc-
book XSL. Normalmente, los parametros XSL se añaden incluyendo una hoja de estilo que los con-
tiene. Aqui, como en otras ocasiones, JSTL se revela adecuado solo para un uso improvisado.

Ejemplo:

<x:param name="draft.mode" value="no"/>

Una forma equivalente a la anterior:

<x:param name="draft.mode">no</x:param>

Validadores de bibliotecas (TLVs)


¿Que es un TLV?
Los TLVs (Tag Library Validators) son validadores asociados a bibliotecas de etiquetas. Antes de
ejecutar cada etiqueta, el contenedor ejecuta automáticamente los TLV que tenga asociados (si ex-
iste alguno).

¿Como funciona?

• Antes de compilar un JSP, el contenedor transforma la página JSP en un documento JSP, que es

50
JSTL

la versión equivalente en XML. Ver JSP 2.0 The New Deal Part 3
[http://www.onjava.com/pub/a/onjava/2004/04/21/JSP2part3.html] acerca de esto.

• El documento XML se crea con un elemento jsp:id por cada elemento de la página. Cada uno de
estos ids esta referenciado desde un Map, que les asocia información (fichero, línea, y columna)
que permite identificar su origen en la página JSP.

• Si alguna de las etiquetas del documento JSP tiene asociado un TLV, el contenedor ejecuta di-
cho TLV.

• Si el TLV detecta un error, le indica al contenedor el id del elemento erróneo. A continuación el


contenedor adjunta información adicional sobre ese elemento (el fichero, línea, y columna).

TLVs de JSTL
Si hemos instalado JSTL, los dos TLVs que proporciona estarán disponibles. Su implementación es-
ta en el paquete javax.servlet.jsp.jstl.tlv
[http://java.sun.com/webservices/docs/1.0/api/javax/servlet/jsp/jstl/tlv/package-summary.html]. Son
estos:

• ScriptFree: Permite restringir los elementos de scripting de una página JSP. Sus parametros son:

Table 51. Parametros de ScriptFree


parametro restringe valor por defecto
allowRTExpressions Valores dependientes del re- true
quest. Ejemplo: <c:out
value="<%=request%>
"/>
allowExpressions Expresiones: <%= ... %> true
allowScriptlets Scriptlets: <% ... %> true
allowDeclarations Declaraciones: <%! ... true
%>

Su implementación es la clase ScriptFreeTLV


[http://java.sun.com/webservices/docs/1.0/api/javax/servlet/jsp/jstl/tlv/ScriptFreeTLV.html], y
se define en el fichero tld scriptfree.tld. En JSP 2.0 también es posible usar el elemento
scripting-invalid para impedir el uso de código java en las páginas JSP.

• PermittedTaglibs: Permite restringir los tld a importar en una página. Su implementación es la


clase PermittedTaglibsTLV
[http://java.sun.com/webservices/docs/1.0/api/javax/servlet/jsp/jstl/tlv/PermittedTaglibsTLV.ht
ml], y se define en el fichero tld permittedTaglibs.tld. Acepta un único parametro que
contiene las uris permitidas separadas por un espacio. En el fichero permit-
tedTaglibs.tld tiene esta configuración:

<validator>
<validator-class>
javax.servlet.jsp.jstl.tlv.PermittedTaglibsTLV
</validator-class>
<init-param>
<param-name>permittedTaglibs</param-name>
<param-value>
http://java.sun.com/jstl/core
http://java.sun.com/jstl/fmt
http://java.sun.com/jstl/sql
http://java.sun.com/jstl/xml
</param-value>

51
JSTL

<description>
Whitespace-separated list of taglib URIs to permit.
This example TLD for the Standard Taglib allows
only JSTL 'el' taglibs to be imported.
</description>
</init-param>
</validator>

Si queremos usarlos en nuestra biblioteca de etiquetas, podemos indicarlo en el su fichero taglib, o


directamente en la página adjuntando la directiva taglib correspondiente. Por ejemplo:

<%@ taglib prefix="scriptfree" uri="http://jakarta.apache.org/taglibs/standard/s

Con la línea anterior indicamos el uso de ScriptFreeTLV con los parametros que figuran en el
fichero scriptfree.tld (todo a false). Si queremos personalizarlo podemos editar ese .tld y co-
piar el elemento validator al tld de nuestras etiquetas, ajustando los parametros según nos convenga.

Las bibliotecas JSTL tienen sus propios TLVs, que no tiene sentido reutilizar pues están diseñados
especificamente para validar etiquetas JSTL. Por ejemplo, la librería core usa el TLV Jstl-
CoreTLV. Podemos verlo leyendo el fichero c.tld contenido en el jar
standard-1.0.4.jar:

...
<validator>
<validator-class>
org.apache.taglibs.standard.tlv.JstlCoreTLV
</validator-class>
<description>
Provides core validation features for JSTL tags.
</description>
</validator>
...

Observese que carece de parametros, porque no esta pensado para su uso por el usuario.

Repaso a XPath
Esta sección es un repaso rápido a XPath. Si quieres experimentar mientras estudias, puedes usar
XPath Explorer [http://www.purpletech.com/xpe/index.jsp] de Alex Chaffe.

¿Que es XPath?
• XPath es la especificación de una sintaxis con la que referirse a partes de un documento XML.

• XPath se usa en XSLT, XPointer, y en software de interpretación (parsing) de XML.

• XPath incluye funciones para trabajar con cadenas, números, y expresiones booleanas.

• XPath fue publicado por el W3C con categoría de “tecnología recomendada” en Noviembre de
1999.

Selección
Seleccionar nodos
Hay varias similitudes entre el sistema de ficheros unix y los documentos XML:

52
JSTL

• Todo documento XML tiene estructura de árbol.

• El separador entre padres e hijos es el caracter (/).

• Una referencia absoluta a un elemento comienza con el carácter (/), una referencia relativa no.

• El nodo actual se referencia con punto (.).

• El nodo padre se referencia con dos puntos (..).

• Para seleccionar un elemento sin tener en cuenta su nombre usamos asterisco (*).

Tomemos como ejemplo el siguiente documento XML:

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


<email>
<from>Pedro</from>
<to>Jano</to>
<tema>Re:Parrillada en la montaña</tema>
<cuerpo>
<p color="azul">
Dile a la montaña que yo no voy.
</p>
Saludos, <a href="mailto:pedro@xxxxx.com">Pedro</a>
</cuerpo>
</email>

Table 52.
expresión selecciona
/email/cuerpo/p El primer elemento párrafo (p) hijo de cuerpo.
/email/cuerpo/../cuerpo/p Lo mismo dando un rodeo.
./p Lo mismo suponiendo que cuerpo sea el nodo
actual.
/email/cuerpo/* Todos los hijos del cuerpo.
/email/*/p Todos los párrafos nietos del elemento email.
/*/*/p Todos los párrafos nietos de la raíz.
//* Todos los elementos.

Seleccionar a cualquier nivel


Podemos usar el operador de descenso recursivo // para referirnos a cualquier descendiente.

Table 53.
expresión selecciona
//p Cualquier elemento p descendiente de la raíz.
/email/cuerpo//p Cualquier elemento p descendiente del cuerpo.

Combinar varias búsquedas


Pueden combinarse varias expresiones de búsqueda con |. El resultado será todos los nodos que
cumplan alguna de las dos condiciones.

Ejemplo:

53
JSTL

Table 54.
expresión selecciona
//p | //a Todos los párrafos y enlaces a cualquier nivel.

Filtrar con []
Podemos usar paréntesis cuadrados para especificar criterios que deben satisfacer los elementos a
buscar.

Table 55.
expresión selecciona
/email/cuerpo/p[1] Primer párrafo hijo de cuerpo. En XPath el
primer elemento es uno, no cero como en java.
/email/cuerpo/p[last()] Último párrafo hijo de cuerpo (hemos usado una
función XPath).
/email/cuerpo[p] Todos los elementos cuerpo hijos de email y con
un elemento p.
/email[to=Jano] Los elementos email con hijo to igual a Jano.
/email[to=Jano]/to Todos los elementos to con contenido Jano.

Seleccionar atributos con @


En XPath los atributos se preceden con el carácter @. Para especificar los atributos de los elementos
que queremos seleccionar usamos elemento[@atributo].

Table 56.
expresión selecciona
//p[@color="azul"] todos los párrafos con atributo color igual a rojo
//p[@*] todos los párrafos con cero o más atributos
//p[@color] todos los párrafos con atributo color
//@color todos los atributos color

Resumen de operadores

Table 57.
Operador Función
* Selecciona todos sus elementos sin tener en
cuenta su nombre.
. Nodo actual.
.. Nodo padre.
@ Selecciona todos los atributos sin tener en cuenta
su nombre.
/ Separador entre elementos. Cuando aparece al
principio indica que los hijos deben ser selec-

54
JSTL

Operador Función
cionados a partir del nodo raíz.
// Especifica una búsqueda sobre cualquier descen-
diente.
[condicion] Desprecia los elementos seleccionados que no
cumplen la condición dada.

Ejemplos varios

Table 58.
Ejemplo Resultado
. Nodo actual.
.. Padre del nodo actual.
p Hijo p del nodo actual.
//p Todos los hijos p del nodo raíz.
* Cualquier hijo del nodo actual.
*/p Todos los nietos p del nodo actual.
@* Cualquier atributo del nodo actual.
../@href Atributo href del padre del nodo actual.
text() todos los nodos de texto del nodo actual
p[1] Segundo hijo p del nodo actual (segundo hijo, no
el nieto).
p[last()] Último hijo p del nodo actual.
/email/cuerpo/p[1]/a[2] Segundo enlace del primer párrafo hijo del ele-
mento cuerpo.
a[@href="#N101AF"] Enlace hijo del nodo actual con atributo href
igual a #N101AF.
div[@id="noticia"][2] Segundo hijo div del nodo actual con atributo
id igual a noticia.
div[@user="jano" or Todos los hijos div del nodo actual con atribute
@user="jano-r"] user igual a jano o jano-r.

Expresiones XPath
Son las compuestas con los operadores +, –, *, div, mod, = (igualdad), !=, <, <=, >, >=, or, and.

Métodos
Funciones Node Set

Table 59.
Nombre Descripción
count() Devuelve el número de elementos seleccionados.
id() Selecciona elementos por su id único.
last() Devuelve un número igual al tamaño del con-

55
JSTL

Nombre Descripción
texto donde se evalua la expresión.
local-name() Devuelve la parte local del nombre expandido
del nodo en el conjunto de nodos del argumento
que es el primero en el orden del documento.
name() Devuelve el nombre de un elemento.
namespace-uri() Devuelve la URI del espacio de nombres del
nombre expandido del nodo en el conjunto de
nodos del argumento que es el primero en el or-
den del documento.
position() Devuelve un número igual a la posición del con-
texto desde el contexto de la expresión evaluada.

Funciones de cadena

Table 60.
Atributo Descripción Ejemplo Resultado
concat() Devuelve la concat('hola',' hola mundo
concatenación de sus ','mundo')
argumentos
contains() Devuelve true si la contains('hola true
primera cadena con- mundo','hola')
tiene la segunda;
false en caso con-
trario.
normalize- Quita espacios al comi- normalize- hola mundo
space() enzo y final. space(' hola
mundo ')
starts-with() Devuelve true si la starts- true
primera cadena comi- with('hola
enza con la segunda, o mundo','hol')
false en caso con-
trario.
starts-with() Convierte un objeto a string(123.45) 123,45
cadena.
string-length() Devuelve el número de string- 10
caracteres de una ca- length('hola
dena. mundo')
substring() Devuelve una sub- substring('hola hola
cadena. mundo',1,4)
substring- Devuelve la subcadena substring- mundo
after() tras otra subcadena. after('hola
mundo',' ')
substring-be- Devuelve la subcadena substring-be- hola
fore() anterior a otra sub- fore('hola
cadena. mundo',' ')
translate() Reemplaza una cadena translate('hola hol4 mundo
por otra. mundo','a','4')

Funciones numéricas

56
JSTL

Table 61.
Atributo Descripción Ejemplo Resultado
ceiling() Devuelve el entero más ceiling(12.3) 13
pequeño y no menor
que el argumento.
floor() Devuelve el entero más floor(12.3) 12
grande pero no mayor
que el argumento.
number() Devuelve el número number(4) 4
correspondiente a su ar-
gumento.
round() Devuelve el entero más round(12.3) 12
próximo al argumento.
sum() Devuelve la suma res- sum(.)
ultante de sumar el con-
junto de nodos que
pasamos como para-
metro.

Funciones booleanas

Table 62.
Atributo Descripción Ejemplo Resultado
boolean() Convierte su argumento
a boolean.
false() Devuelve false false() false
true() Devuelve true.
false() Devuelve true si el not(false()) true
argumento es false y
viceversa.
true() Devuelve true. true() true

Espacios de nombres
Supongamos un documento como

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


<email:email>
<email:tema>Re:Parrillada en la montaña</email:tema>
<email:cuerpo>
Dile a la montaña que yo no voy.
<binary:attachment>GIF89ahÈ00WW¤3u¸Côéð...</binary:attachment>
</email:cuerpo>
</email:email>

¿Cómo accedemos a binary:attachment?

• /email/cuerpo/attachment no es correcto porque ignora el espacio de nombres

• /email:email/email:cuerpo/email:attachment no es correcto porque los espa-

57
JSTL

cios de nombres (que son sinónimos de sus respectivas URIs) los usa internamente el documento
pero no podemos usarlos nosotros.

• Una manera sencilla es //*[name()='attachment']

• Otra manera más especifica es /


*[name()='email']/*[name()='cuerpo']/*[name()='attachment']

58

Potrebbero piacerti anche