Uso de taglibs en XSP
Las XSPs permiten, al igual que las JSPs asociar código con una etiqueta xml. Por
ejemplo, podría asociarse: <myPreffix:getDate format="yy/MM/dd hh:mm:ss aa"/> con el
código para obtener una fecha, de forma que cuando se genere el fuente de la XSP aparezca
éste en el lugar donde estaba la etiqueta.
Estas etiquetas pueden ser agrupadas formando librerías de etiquetas. A estas librerías
las llamaremos taglibs.
En las XSP las taglibs se definen como hojas de transformación XSL.
Ventajas del uso de taglibs
- Potencian la reutilización de código usado frecuentemente.
- Permiten limpiar de código las XSP sustituyendo la mayoría del código embebido por
etiquetas. Esto mejora el mantenimiento y la legibilidad de las páginas.
- Permiten separar más los papeles en el desarrollo de XSP. Véase el apartado Workflow con
XSP. Esto permite un mayor paralelismo en el trabajo.
- Cuando ya se disponga de una buena biblioteca de taglibs se acelerará el desarrollo de
páginas.
- Debido a que están basadas en XSL permiten, además de simplemente añadir código a la
página, transformarla con gran potencia. Un ejemplo de las ventajas de que proporciona el
hecho de que sean hojas de transformación XSL es que podemos definir etiquetas para
invocar de forma sencilla métodos con signaturas complejas. Si preparamos valores por
defecto para cada argumento podemos comprobar que atributos se nos pasan en la
etiqueta y para los que falten colocar el valor por defecto.
Así, para un método longMethod(a1, a2, a3, a4, a5, a6, a7, a8) donde la
mayoría de sus argumentos son usado habitualmente con los mismos argumentos podemos
preparar una etiqueta que admita todos los argumentos en forma de atributos pero que si
falta alguno ponga un valor típico:
En la XSP se escribirá:
MyClass myVar = <myPreffix:longMethod a1=a1Value a6=this /> ;
Con la taglib adecuada, en el código fuente aparecerá:
MyClass myVar = longMethod( a1Value,
null,
System.currentTimeMillis(),
"",
-1,
this,
null,
null);
Si quisiésemos dar una facilidad semejante desde Java tendríamos que definir una
signatura por cada combinación de argumentos.
Otro ejemplo de potencia es que una etiqueta se puede sustituir por más etiquetas de otra
taglib, o incluso eliminar contenido XML.
Cómo funcionan las taglibs
En Cocoon existe un mapeo entre espacios de nombres XML y hojas de transformación
XSL.
Cuando se invoca una XSP por primera vez esta tiene que ser compilada a un productor
de XML (actualmente una clase Java que extiende XSPPage.). Es durante este proceso cuando
se usan las taglibs.
La primera fase es generar el código fuente. Para ello se le aplican transformaciones
XSL. Si en la XSP aparecen etiquetas con espacios de nombres se comprueba si están
mapeados con una hoja de transformación XSL ( taglib ). Si es así se le aplica esta
transformación, si no se considera que es contenido estático de la página y se conserva tal cual.
Cuando todos los espacios de nombres están procesados se realiza la última
transformación que traduce el XML al código Java encargado de generarlo (si se ha especificado
Java como lenguaje en la cabecera de la XSP).
Cómo usar taglibs ya instaladas
Para ver las librerías instaladas podemos examinar el fichero de configuración de Cocoon
cocoon.properties. En su sección referente al XSP Processor se pueden ver líneas de
este estilo:
processor.xsp.logicsheet.util.java =
resource://org/apache/cocoon/processor/xsp/library/java/util.xsl
En esta línea se especifica que para el lenguaje Java, la hoja de transformación asociada al
espacio de nombres "util" es
//org/apache/cocoon/processor/xsp/library/java/util.xsl.
Si queremos usar alguna etiqueta definida en esta taglib deberemos declarar en el elemento
raíz de la xsp el espacio de nombres util. Lo podemos copiar de la declaración de espacios de
nombres de la taglib. En este caso del archivo util.xsl.
<xsp:page language="java"
xmlns:xsp="http://www.apache.org/1999/XSP/Core"
xmlns:util="http://www.apache.org/1999/XSP/Util >
Una vez hecho esto ya se puede usar cualquiera de las etiquetas definidas en la taglib. Por
ejemplo vamos a incluir una fecha en nuestra página:
Esta es la definición de lo que se hace con la etiqueta en la taglib.
<xsl:template match="util:time">
<xsl:variable name="format">
<xsl:choose>
<xsl:when test="@format">"<xsl:value-of select="@format"/>"</xsl:when>
<xsl:when test="util:format">
<xsl:call-template name="get-nested-content">
<xsl:with-param name="content" select="util:format"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsp:expr>
XSPUtil.formatDate(
new Date(),
String.valueOf(<xsl:copy-of select="$format"/>).trim()
)
</xsp:expr>
</xsl:template>
En la XSP escribiremos:
<util:time format=yy/MM/dd hh:mm:ss aa/>
O en este caso si analizamos el código xsl vemos que también admite el parámetro como
elemento en lugar de sólo como atributo:
<util:time>
<util:format>yy/MM/dd hh:mm:ss aa</util:format>
</util:time>
Cómo definir una nueva etiqueta
Por un lado debemos construir la XSL para tratar la etiqueta. Debe estar diseñada
cuidadosamente para que respete el contenido de la página y sólo afecte a las etiquetas
adecuadas, o de lo contrario se podría modificar contenido que en principio no tiene relación
con la etiqueta. Este es, bajo mi punto de vista, el principal problema que plantean las taglibs
definidas como hojas de transformación. A veces tanta potencia puede convertirse en un arma
de doble filo.
Para ello podemos fijarnos en la estructura de cualquiera de las XSL que incluye
Cocoon.
En esta XSL debemos declarar el espacio de nombres de las etiquetas que vayamos a
tratar.
Conviene definir un xsl:template por cada etiqueta para que sea más fácil de leer para
otros desarrolladores que la quieran usar. Y documentar al principio para que sirve y que
parámetros se le pueden pasar y cómo.
Si nuestra etiqueta admite parámetros debemos pensar en el tipo de información que
va a contener el parámetro. Lo más cómodo es recibir los parámetros en un atributo de la
etiqueta, pero si por ejemplo va a ser un texto extenso o va a incluir caracteres tales como
comillas conviene recibirlo en otra etiqueta interna. En el ejemplo del apartado anterior, la
etiqueta <util:time> admite el formato de fecha especificado
dentro de un atributo format o dentro de un elemento interno
<util:format>.
Una vez hayamos concluido la xsl, tenemos que instalarla en Cocoon. Para ello
debemos colocarla en algún lugar del classpath donde se esté ejecutando Cocoon y añadir otra
línea al cocoon.properties de la siguiente forma:
processor.xsp.logicsheet.myNewPreffix.java =
resource:path_to_my_taglib/my_new_taglib.xsl
Reiniciamos Cocoon y ya está lista para ser usada.
Si realizamos algún cambio futuro en la XSL, posiblemente tengamos que eliminar los archivos
.java generados a partir de las XSP que la usen para forzar una recompilación. En las versiones
actual (v1.82) y anteriores no se detectan los cambios en las taglibs y debemos hacer este
pequeño "truco" para usar los nuevos cambios.