ndice.
1. Introduccin............................................................................................ 4
1.1. Por qu necesitamos XQuery?. ......................................................................... 5
2. Definicin de XQuery. ........................................................................... 7
2.1. Requerimientos tcnicos de XQuery. ................................................................. 7
2.2. Coleccin de datos de ejemplo. .......................................................................... 8
3. Consultas en XQuery............................................................................ 11
3.1. Reglas generales................................................................................................ 14
3.2. Diferencias entre las clusulas for y let. ........................................................... 15
3.3. Funciones de entrada. ....................................................................................... 17
3.4. Expresiones condicionales. ............................................................................... 17
3.5. Cuantificadores existenciales:........................................................................... 19
3.6. Operadores y funciones principales. ................................................................. 20
3.7. Comentarios. ..................................................................................................... 23
3.8. XQueryX........................................................................................................... 24
3.9. Ejemplos de consultas....................................................................................... 25
4. XQuery y Java. ..................................................................................... 31
4.1. XQEngine. ........................................................................................................ 31
4.2. Ejecutando consultas con XQEngine................................................................ 31
4.3. Embebiendo XQEngine en una aplicacin Java. .............................................. 35
4.4. Otros motores XQuery open-source. ................................................................ 37
4.5. Otras herramientas relacionadas con XQuery................................................... 37
5. Conclusiones......................................................................................... 39
6. Referencias y enlaces. .......................................................................... 40
Apndice I. Parses SAX y DOM.............................................................. 41
SAX. ........................................................................................................................ 41
DOM. ....................................................................................................................... 41
Apndice II. XML Binding ...................................................................... 42
Apndice III. Xpath. ................................................................................. 44
Apndice IV. Conjunto de documentos que describen XQuery y XPath.47
1. Introduccin.
Extensible Markup Language[1] (ms conocido como XML) es un formato para
almacenar datos extremadamente verstil, utilizado para representar una gran cantidad
distinta de informacin como, por ejemplo, pginas web (XHTML), mensajes web entre
aplicaciones (SOAP), libros y artculos, datos de negocio, representacin de bases de
datos relacionales, interfaces de usuario (XUL), transacciones financieras y bancarias,
partidas de ajedrez, recetas de cocina, trazas del sistema, grficos vectoriales (SVG),
sindicacin de contenidos (RSS), archivos de configuracin, documentos de texto
([Link]) y manuscritos en griego clsico.
Un conjunto de datos expresados en XML es una cadena de texto donde cada
uno de los datos est delimitado por etiquetas de la forma <T> ... </T> o se incluye
como atributo de una etiqueta de la forma <T A=...> ... </T>. Mediante esta
representacin es posible expresar tambin la semntica de cada uno de los datos.
A continuacin se muestra un conjunto de datos en XML que contiene
informacin sobre un libro titulado TCP/IP Illustrated, escrito por Stevens, W.,
editado por Addison-Wesley y cuyo precio es 69.95.
<bib>
<libro>
<titulo>TCP/IP Illustrated</titulo>
<autor>
<apellido>Stevens</apellido>
<nombre>W.</nombre>
</autor>
<editorial>Addison-Wesley</editorial>
<precio> 65.95</precio>
</libro>
</bib>
En XML las etiquetas se estructuran en forma de rbol n-rio. En la figura 1 se
muestra la estructura en rbol del conjunto de datos referidos al libro.
<bib>
<libro>
<titulo>
<autor>
<apellido>
<editorial>
<precio>
<nombre>
Figura 1. Representacin en forma de rbol de un conjunto de etiquetas XML.
1.1. Por qu necesitamos XQuery?.
Actualmente, XML se ha convertido en una herramienta de uso cotidiano en los
entornos de tratamiento de informacin y en los entornos de programacin. Sin
embargo, a medida que se emplea en un mayor nmero de proyectos de complejidad y
tamao crecientes y la cantidad de datos almacenados en XML aumenta, se comprueba
que, las herramientas ms habituales para manipular desde un programa un rbol con un
conjunto de datos en XML, los parsers SAX y DOM1, no son prcticas para manejar
grandes y complejas colecciones de datos en XML.
El principal problema a la hora de procesar colecciones de datos en XML a bajo
nivel mediante parsers DOM y SAX es la necesidad de escribir una gran cantidad de
cdigo para realizar el procesamiento. Este cdigo consiste, bsicamente, en recorrer un
rbol, para un parser DOM, o detallar una lista de acciones segn la etiqueta que se
encuentre para parser SAX.
Posteriormente a los parsers DOM y SAX, ha aparecido una nueva familia de
herramientas conocidas genricamente como bindings2, que, si bien en ciertos aspectos
son tremendamente tiles y ahorran una gran cantidad de trabajo, no son tiles en todas
las situaciones en las que se puede utilizar XML.
Otra solucin existente en la actualidad es el estndar XSLT[3] que permite
definir transformaciones sobre colecciones datos en XML en otros formatos, como
HTML o PDF y las herramientas que le dan soporte. Sin embargo XSLT slo es
aplicable en los casos en los que desee obtener una representacin distinta de los datos,
no cuando se desea localizar una informacin concreta dentro de dicho conjunto de
datos.
Un ejemplo de un escenario donde no es aplicable ninguna de las herramientas
comentadas hasta ahora (parsers, binding y XSLT) lo encontramos a la hora de
consultar la informacin en los actuales servidores de bases de datos que ya incorporan
1
Para una descripcin del modo de trabajo y caractersticas principales de los parsers SAX y DOM
consultar el apndice I.
2
Para ms informacin sobre la manera de trabajar y un listado de herramientas de binding consultar el
apndice II.
funciones para poder obtener los datos en XML o bases de datos XML nativas (Native
XML Database). El escenario de uso ms comn se da cuando tenemos que realizar
alguna bsqueda en un documento o conjunto de documentos con gran cantidad de
datos en XML, o bien hemos de trabajar slo sobre un subconjunto de todos los datos
XML y queremos obtener dicho subconjunto de una forma sencilla, para evitar trabajar
con toda la coleccin de datos.
Dar solucin a este escenario de uso mediante cdigo escrito con la ayuda de un
parser SAX es rpido y sencillo de desarrollar si la consulta y la estructura de la
informacin no tienen una gran complejidad. A medida que la consulta va ganando en
complejidad, es necesario definir comportamientos ms complejos a ejecutar cuando se
encuentre una etiqueta y se necesita un mayor nmero de almacenamientos temporales
de datos. Otro problema es que el cdigo est fuertemente ligado a la estructura de los
datos en XML, por lo que cualquier cambio en la consulta o en la estructura de los datos
obliga a volver a escribir el cdigo. Adems el cdigo resultante es muy poco
parametrizable y reutilizable por lo que para desarrollar una consulta similar habra que
volverla a escribir desde el principio, sin poder aprovechar nada de lo escrito. Dar
solucin a este escenario de uso mediante cdigo escrito con la ayuda un parser DOM
aade, a los problemas de reusabilidad, complejidad y fuerte acoplamiento anteriores, la
exigencia de tener cargar los datos en memoria antes de comenzar el recorrido, lo cual
puede resultar imposible para grandes volmenes de datos.
Las herramientas de bindings favorecen la sencillez en el proceso de carga en
memoria de los datos, pero, aplicadas a este escenario de uso, no facilita la tarea a la
hora de escribir una consulta. Primero, muchos bindings necesitan los documentos de
definicin de los documentos XML (DTDs o XML-Schemas) para poder generar las
clases y el cdigo de vinculacin, por lo que si no se tienen y la estructura de la
informacin es compleja puede resultar que el tiempo que ganamos con el uso de estas
herramientas lo perdamos escribiendo el DTD o XML-Schemas correspondiente.
Tambin existen herramientas que pueden trabajar sin los DTD o XML-Schemas, pero
entonces es necesario escribir a mano todas las clases necesarias para almacenar la
coleccin de datos en XML. Adems estas herramientas siguen teniendo el problema de
que requieren cargar en memoria todos los datos. Ms an, lo que estamos haciendo es
cambiar un conjunto de datos expresados mediante etiquetas XML por un conjunto de
datos expresados por los atributos de un conjunto de objetos, por lo que sigue siendo
necesario escribir la algoritmia necesaria para esa consulta, algoritmia poco reutilizable
en posteriores consultas.
A la vista de todo lo comentado hasta ahora, se hace necesaria la aparicin de un
lenguaje que permita definir de forma rpida y compacta, consultas o recorridos
complejos sobre colecciones de datos en XML los cuales devuelvan todos los nodos que
cumplan ciertas condiciones. Este lenguaje debe ser, adems, declarativo, es decir,
independientemente de la forma en que se realice el recorrido o de donde se encuentren
los datos. Este lenguaje ya existe y se llama XQuery.
A lo largo de este artculo vamos a mostrar, con profusin de ejemplos, las
caractersticas principales de este lenguaje y vamos a mostrar como utilizar uno de los
motores open-source existentes para incorporar capacidad de procesado de consulta
XQuery en nuestras aplicaciones.
2. Definicin de XQuery.
De manera rpida podemos definir XQuery con un smil en el que XQuery es a
XML lo mismo que SQL es a las bases de datos relacionales.
XQuery[4][5] es un lenguaje de consulta diseado para escribir consultas sobre
colecciones de datos expresadas en XML. Abarca desde archivos XML hasta bases de
datos relacionales con funciones de conversin de registros a XML. Su principal
funcin es extraer informacin de un conjunto de datos organizados como un rbol nrio de etiquetas XML. En este sentido XQuery es independiente del origen de los
datos.
XQuery es un lenguaje funcional, lo que significa que, en vez de ejecutar una
lista de comandos como un lenguaje procedimental clsico, cada consulta es una
expresin que es evaluada y devuelve un resultado, al igual que en SQL. Diversas
expresiones pueden combinarse de una manera muy flexible con otras expresiones para
crear nuevas expresiones ms complejas y de mayor potencia semntica.
XQuery est llamado a ser el futuro estndar de consultas sobre documentos
XML. Actualmente, XQuery es un conjunto de borradores3 en el que trabaja el grupo
W3C[20]. Sin embargo, a pesar de no tener una redaccin definitiva ya existen o estn
en proceso numerosas implementaciones de motores y herramientas que lo soportan.
2.1. Requerimientos tcnicos de XQuery.
El grupo de trabajo en XQuery del W3C[20] ha definido un conjunto de
requerimientos tcnicos para este lenguaje. Los ms importantes se detallan a
continuacin.
XQuery debe ser un lenguaje declarativo. Al igual que SQL hay que
indicar que se quiere, no la manera de obtenerlo.
XQuery debe ser independiente del protocolo de acceso a la coleccin de
datos. Una consulta en XQuery debe funcionar igual al consultar un
archivo local que al consultar un servidor de bases de datos que al
consultar un archivo XML en un servidor web.
Las consultas y los resultados deben respetar el modelo de datos XML
Las consultas y los resultados deben ofrecer soporte para los namespace4.
Debe ser capaz de soportar XML-Schemas y DTDs y tambin debe ser
capaz de trabajar sin ninguno de ellos.
XQuery debe poder trabajar con independencia de la estructura del
documento, esto es, sin necesidad de conocerla.
XQuery debe soportar tipos simples, como enteros y cadenas, y tipos
complejos, como un nodo compuesto por varios nodos hijos.
Las consultan deben soportar cuantificadores universales (para todo) y
existenciales (existe).
3
Para ver el conjunto completo de borradores y sus URLs consultar el apndice IV.
Un namespace[1] es un espacio de definicin de etiquetas que permite que dos diseadores puedan
utilizar el mismo nombre de etiqueta con dos significados semnticos distintos sin que entren en
conflicto. Dos etiquetas con el mismo nombre declaradas en namespaces diferentes se consideran dos
etiquetas diferentes.
4
Las consultas deben soportar operaciones sobre jerarquas de nodos y
secuencias de nodos.
Debe ser posible en una consulta combinar informacin de mltiples
fuentes.
Las consultas deben ser capaces de manipular los datos
independientemente del origen de estos.
Mediante XQuery debe ser posible definir consultas que transformen las
estructuras de informacin originales y debe ser posible crear nuevas
estructuras de datos.
El lenguaje de consulta debe ser independiente de la sintaxis, esto es,
debe ser posible que existan varias sintaxis distintas para expresar una
misma consulta en XQuery.
Aunque XQuery y SQL puedan considerarse similares en casi la totalidad de sus
aspectos, el modelo de datos sobre el que se sustenta XQuery es muy distinto del
modelo de datos relacional sobre el que sustenta SQL, ya que XML incluye conceptos
como jerarqua y orden de los datos que no estn presentes en el modelo relacional. Por
ejemplo, a diferencia de SQL, en XQuery el orden es que se encuentren los datos es
importante y determinante, ya que no es lo mismo buscar una etiqueta <B> dentro de
una etiqueta <A> que todas las etiquetas <B> del documento (que pueden estar
anidadas dentro de una etiqueta <A> o fuera).
XQuery ha sido construido sobre la base de Xpath[3]. Xpath5 es un lenguaje
declarativo para la localizacin de nodos y fragmentos de informacin en rboles XML.
XQuery se basa en este lenguaje para realizar la seleccin de informacin y la iteracin
a travs del conjunto de datos.
2.2. Coleccin de datos de ejemplo.
En los ejemplos de consultas que veremos a lo largo de este trabajo, vamos a
trabajar con un conjunto de datos compuesto por fichas de varios libros almacenadas en
un archivo local llamado [Link], cuyo contenido se muestra a continuacin.
<?xml version="1.0" encoding="ISO-8859-1"?>
<bib>
<libro ao="1994">
<titulo>TCP/IP Illustrated</titulo>
<autor>
<apellido>Stevens</apellido>
<nombre>W.</nombre>
</autor>
<editorial>Addison-Wesley</editorial>
<precio> 65.95</precio>
</libro>
<libro ao="1992">
<titulo>Advan Programming for Unix environment</titulo>
<autor>
5
Para ms informacin sobre XPath consultar el apndice III y el apndice IV.
<apellido>Stevens</apellido>
<nombre>W.</nombre>
</autor>
<editorial>Addison-Wesley</editorial>
<precio>65.95</precio>
</libro>
<libro ao="2000">
<titulo>Data on the Web</titulo>
<autor>
<apellido>Abiteboul</apellido>
<nombre>Serge</nombre>
</autor>
<autor>
<apellido>Buneman</apellido>
<nombre>Peter</nombre>
</autor>
<autor>
<apellido>Suciu</apellido>
<nombre>Dan</nombre>
</autor>
<editorial>Morgan Kaufmann editorials</editorial>
<precio>39.95</precio>
</libro>
<libro ao="1999">
<titulo> Economics of Technology for Digital TV</titulo>
<editor>
<apellido>Gerbarg</apellido>
<nombre>Darcy</nombre>
<afiliacion>CITI</afiliacion>
</editor>
<editorial>Kluwer Academic editorials</editorial>
<precio>129.95</precio>
</libro>
</bib>
A continuacin se muestra el contenido del DTD correspondiente al archivo
"[Link]".
<!ELEMENT
<!ELEMENT
<!ATTLIST
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
bib (libro* )>
libro (titulo,(autor+ | editor+ ),editorial, precio )>
libro year CDATA #REQUIRED >
autor (apellido, nombre )>
editor (apellido, nombre, afiliacion )>
titulo (#PCDATA )>
apellido (#PCDATA )>
nombre (#PCDATA )>
afiliacion (#PCDATA )>
editorial (#PCDATA )>
<!ELEMENT precio (#PCDATA )>
En algunas consultas tambin necesitaremos combinar la informacin contenida
en el archivo [Link] con la informacin contenida en el archivo
[Link]. El contenido de este archivo se muestra a continuacin.
<?xml version="1.0" encoding="ISO-8859-1"?>
<comentarios>
<entrada>
<titulo>Data on the Web</titulo>
<precio>34.95</precio>
<comentario>
Un libro muy bueno sobre bases de datos.
</comentario>
</entrada>
<entrada>
<titulo>Advanced Programming in the Unix
environment</titulo>
<precio>65.95</precio>
<comentario>
Un libro claro y detallado de programacin en UNIX.
</comentario>
</entrada>
<entrada>
<titulo>TCP/IP Illustrated</titulo>
<precio>65.95</precio>
<comentario>
Uno de los mejores libros de TCP/IP
</comentario>
</entrada>
</comentarios>
A continuacin se muestra el contenido del DTD correspondiente al archivo
"[Link]".
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
comentarios (entrada*)>
entrada
(titulo, precio, comentario)>
titulo
(#PCDATA)>
precio
(#PCDATA)>
comentario (#PCDATA)>
10
3. Consultas en XQuery.
Una consulta en XQuery[4][5] es una expresin que lee una secuencia de datos
en XML y devuelve como resultado otra secuencia de datos en XML.
Un detalle importante es que, a diferencia de lo que sucede en SQL, en XQuery
las expresiones y los valores que devuelven son dependientes del contexto. Por ejemplo
los nodos que aparecern en el resultado dependen de los namespaces, de la posicin
donde aparezca la etiqueta raz del nodo (dentro de otra, por ejemplo), etc.
En XQuery las consultas pueden estar compuestas por clusulas de hasta cinco
tipos distintos. Las consultas siguen la norma FLWOR (ledo como flower), siendo
FLWOR las siglas de For, Let, Where, Order y Return. A continuacin, en la tabla 1, se
describe la funcin de cada bloque:
For
Let
Where
Order by
Return
Vincula una o ms variables a expresiones escritas en XPath,
creando un flujo de tuplas en el que cada tupla est vinculada a
una de las variable.
Vincula una variable al resultado completo de una expresin
aadiendo esos vnculos a las tuplas generadas por una clusula
for o, si no existe ninguna clusula for, creando una nica tupla
que contenga esos vnculos.
Filtra las tuplas eliminando todos los valores que no cumplan las
condiciones dadas.
Ordena las tuplas segn el criterio dado.
Construye el resultado de la consulta para una tupla dada,
despus de haber sido filtrada por la clusula where y ordenada
por la clusula order by.
Tabla 1. Posibles clusulas en una consulta XQuery.
En XQuery, cuando usamos el trmico tupla, nos estamos refiriendo a cada uno
de los valores que toma una variable.
A continuacin, en la figura 2, se muestra grficamente el orden en que se
ejecuta cada clusula de una consulta y los resultados de cada una:
11
D a to s X M L
< b ib >
< lib ro >
< titu lo >
< au to r>
< ap e llid o >
< e d ito ria l>
< p re c io >
< n o m b re>
For y Let
C re a n la s tu p la s
W h e re
F iltra la s tu p la s
O rd e r b y
O rd e n a la s tu p la s
R e tu rn
T ra n fo rm a la s tu p la s
R e s u lta d o X M L
< b ib >
< lib ro >
< titu lo >
< au to r>
< ap e llid o >
< e d ito ria l>
< p re c io >
< n o m b re>
Figura 2. Orden de ejecucin y resultado de las cinco clusulas posibles.
En el siguiente ejemplo de clusula for, la variable $b tomar como valor cada
uno de los nodos libros que contenga en archivo [Link]. Cada uno de esos nodos
libros, ser una tupla vinculada a la variable $b.
for $b in document("[Link])//bib/libro
12
A continuacin se muestra un ejemplo de una consulta donde aparecen las 5
clausulas. La siguiente consulta devuelve los ttulos de los libros que tengan ms de dos
autores ordenados por su ttulo.
for $b in doc("[Link]")//libro
let $c := $b//autor
where count($c) > 2
order by $b/titulo
return $b/ titulo
El resultado de esta consulta se muestra a continuacin.
<title>Data on the Web</title>
Las barras: // no indican comentarios, sino que son parte de la expresin
XPath que indica la localizacin de los valores que tomar la variable $b. En esta
consulta la funcin count() hace la misma funcin que en SQL, contar el nmero de
elementos, nodos en este caso, referenciados por la variable $c. La diferencia entre la
clusula for y la clusula let se explica con ms detalle en un punto posterior.
Una expresin FLWOR vincula variables a valores con clusulas for y let y
utiliza esos vnculos para crear nuevas estructuras de datos XML.
A continuacin se muestra otro ejemplo de consulta XQuery. La siguiente
consulta devuelve los ttulos de los libros del ao 2.000. Como ao es un atributo y no
una etiqueta se le antecede con un carcter @.
for $b in doc("[Link]")//libro
where $b/@ao = "2000"
return $b/titulo
El resultado de la consulta anterior se muestra a continuacin.
<title>Data on the Web</title>
A continuacin, en la figura 3, se muestra de forma grfica como se ejecutara la
consulta anterior y los resultados parciales de cada una de sus clusulas:
13
For y Let
<libro ao="1994"> <titulo>TCP/IP Illustrated</titulo> [..] </libro>
<libro ao="1992"> <titulo>Advan Programming ...</titulo> [..] </libro>
<libro ao="2000"> <titulo>Data on the Web</titulo> [..] </libro>
<libro ao="1999"> <titulo> Economics of ...</titulo> [..] </libro>
Where
<libro ao="2000"> <titulo>Data on the Web</titulo> [..] </libro>
Order by
No
Return
<titulo>Data on the Web</titulo>
Figura 3. Ejecucin de una consulta XQuery con los resultados de cada clusula.
3.1. Reglas generales.
A continuacin, enunciamos una serie de reglas que debe cumplir cualquier
consulta escrita en XQuery[4][5]:
For y let sirven para crear las tuplas con las que trabajar el resto de las
clusulas de la consulta y pueden usarse tantas veces como se desee en
una consulta, incluso dentro de otras clusulas. Sin embargo solo puede
declararse una nica clusula where, una nica clusula order by y una
nica clusula return.
Ninguna de las clusulas FLWOR es obligatoria en una consulta
XQuery. Por ejemplo, una expresin XPath, como la que se muestra a
continuacin, es una consulta vlida y no contiene ninguna de las
clusulas FLWOR.
doc("[Link]")/bib/libro/titulo[/bib/libro/autor/apellido='St
evens']
Esta expresin XPath, que tambin es una consulta XQuery vlida, devuelve los
ttulos de los libros que tengan algn autor de apellido Stevens.
Es posible especificar varios criterios de ordenacin en la clusula order by,
separndolos por comas. Los criterios de ordenacin se aplican por orden de izquierda a
derecha.
14
3.2. Diferencias entre las clusulas for y let.
Para ver claramente la diferencia entre una clusula for y una clusula let vamos
a comenzar estudiando una misma consulta que muestre los ttulos de todos los libros
almacenados en el archivo [Link], primero con una clusula for y, a continuacin,
con una clusula let y vamos a detallar que diferencia hay en la informacin obtenida.
La consulta con una clusula for se muestra a continuacin.
for $d in doc("[Link]")/bib/libro/titulo
return
<titulos>{ $d }</titulos>
El resultado de esta consulta se muestra a continuacin:
<titulos>
<titulo>TCP/IP Illustrated</titulo>
</titulos>
<titulos>
<titulo>Advan Programming for Unix environment</titulo>
</titulos>
<titulos>
<titulo>Data on the Web</titulo>
</titulos>
<titulos>
<titulo> Economics of Technology for Digital TV</titulo>
</titulos>
A continuacin repetimos la misma consulta sustituyendo la clusula for una
clusula let.
let $d := doc("[Link]")/bib/libro/titulo
return
<titulos>{ $d }</titulos>
El resultado de esta consulta se muestra a continuacin.
<titulos>
<titulo>TCP/IP Illustrated</titulo>
<titulo>Advan Programming for Unix environment</titulo>
<titulo>Data on the Web</titulo>
<titulo> Economics of Technology for Digital TV</titulo>
</titulos>
15
Como se puede ver comparando los resultados obtenidos por ambas consultas, la
clusula for vincula una variable con cada nodo que encuentre en la coleccin de datos.
En este ejemplo la variable $d va vinculndose a cada uno de los ttulos de todos los
libros del archivo "[Link]", creando una tupla por cada ttulo. Por este motivo
aparece repetido el par de etiquetas <titulos>...</titulos> para cada ttulo. La clusula
let, en cambio, vincula una variable con todo el resultado de una expresin. En este
ejemplo, la variable $d se vincula a todos los ttulos de todos los libros del archivo
"[Link]", creando una nica tupla con todos esos ttulos. Por este motivo solo
aparece el par de etiquetas <titulos>...</titulos> una nica vez.
Si una clusula let aparece en una consulta que ya posee una o ms clusulas for,
los valores de la variable vinculada por la clusula let se aaden a cada una de las tuplas
generadas por la clusula for. Un ejemplo se muestra en la siguiente consulta:
for $b in doc("[Link]")//libro
let $c := $b/autor
return
<libro>{ $b/titulo, <autores>{ count($c) }</autores>}</libro>
Esta consulta devuelve el ttulo de cada uno de los libros de archivo "[Link]"
junto con el nmero de autores de cada libro. El resultado de esta consulta se muestra a
continuacin:
<libro>
<titulo>TCP/IP Illustrated</titulo>
<autores>1</autores>
</libro>
<libro>
<titulo>Advanced Programming in the UNIX
Environment</titulo>
<autores>1</autores>
</libro>
<libro>
<titulo>Data on the Web</titulo>
<autores>3</autores>
</libro>
<libro>
<titulo>The Economics of Technology and Content for
Digital TV</titulo>
<autores>0</autores>
</libro>
Si en la consulta aparece ms de una clusula for (o ms de una variable en una
clsula for), el resultado es el producto cartesiano de dichas variables, es decir, las
tuplas generadas cubren todas las posibles combinaciones de los nodos de dichas
variables. Un ejemplo se muestra en la siguiente consulta, la cual devuelve los ttulos de
todos los libros contenidos en el archivo [Link] y todos los comentarios de cada
libro contenidos en el archivo [Link].
16
for $t in doc("[Link]")//titulo,
$e in doc("[Link]")//entrada
where $t = $e/titulo
return <comentario>{ $t, $e/comentario }</comentario>
El resultado de esta consulta se muestra a continuacin.
<comentario>
<titulo>Data on the Web</titulo>
<comentario>Un libro muy bueno sobre bases de
datos.</comentario>
</comentario>
<comentario>
<titulo>Advanced Programming in the Unix
environment</titulo>
<comentario>Un libro claro y detallado de programacin en
UNIX.</comentario>
</comentario>
<comentario>
<titulo>TCP/IP Illustrated</titulo>
<comentario>Uno de los mejores libros de
TCP/IP.</comentario>
</comentario>
3.3. Funciones de entrada.
XQuery utiliza las funciones de entrada en las clusulas for o let o en
expresiones XPath para identificar el origen de los datos. Actualmente el borrador de
XPath y XQuery define dos funciones de entrada distintas, doc(URI) y collection(URI).
La funcin doc(URI) devuelve el nodo documento, o nodo raz, del documento
referenciado por un identificador universal de recursos (URI). Esta es la funcin ms
habitual para acceder a la informacin almacenada en archivos.
La funcin collection(URI) devuelve una secuencia de nodos referenciados por
una URI, sin necesidad de que exista un nodo documento o nodo raz. Esta es la funcin
ms habitual para acceder a la informacin almacenada en una base de datos que tenga
capacidad para crear estructuras de datos XML.
3.4. Expresiones condicionales.
Adems de la clusula where, XQuery tambin soporta expresiones
condicionales del tipo if-then-else con la misma semntica que en los lenguajes de
programacin ms habituales (C, Java, Delphi, etc..). Por ejemplo, la siguiente consulta
devuelve los ttulos de todos los libros almacenados en el archivo "[Link]" y sus dos
primeros autores. En el caso de que existan ms de dos autores para un libro, se aade
un tercer autor "et al.".
17
for $b in doc("[Link]")//libro
return
<libro>
{ $b/titulo }
{
for $a at $i in $b/autor
where $i <= 2
return <autor>{string($a/last), ", ",
string($a/first)}</autor>
}
{
if (count($b/autor) > 2)
then <autor>et al.</autor>
else ()
}
</libro>
El resultado de esta consulta se muestra a continuacin.
<libro>
<titulo>TCP/IP Illustrated</titulo>
<autor>Stevens, W.</autor>
</libro>
<libro>
<titulo>Advanced Programming in the Unix
Environment</titulo>
<autor>Stevens, W.</autor>
</libro>
<libro>
<titulo>Data on the Web</titulo>
<autor>Abiteboul, Serge</autor>
<autor>Buneman, Peter</autor>
<autor>et al.</autor>
</libro>
La clusula where de una consulta permite filtrar las tuplas que aparecern en el
resultado, mientras que una expresin condicional nos permite crear una u otra
estructura de nodos en el resultado que dependa de los valores de las tuplas filtradas.
A diferencia de la mayora de los lenguajes, la clusula else es obligatoria y debe
aparecer siempre en la expresin condicional. El motivo de esto es que toda expresin
en XQuery debe devolver un valor. Si no existe ningn valor a devolver al no cumplirse
la clusula if, devolvemos una secuencia vaca con else (), tal y como se muestra en el
ejemplo anterior.
18
3.5. Cuantificadores existenciales:
XQuery soporta dos cuantificadores existenciales llamados some y every, de
tal manera que nos permite definir consultas que devuelva algn elemento que satisfaga
la condicin (some) o consultas que devuelvan los elementos en los que todos sus
nodos satisfagan la condicin (every). Por ejemplo, la siguiente consulta devuelve los
ttulos de los libros en los que al menos uno de sus autores es W. Stevens.
for $b in doc("[Link]")//libro
where some $a in $b/autor
satisfies ($a/last="Stevens" and $a/first="W.")
return $b/titulo
El resultado de esta consulta se muestra a continuacin
<title>TCP/IP Illustrated</title>
<title>Advanced Programming in the Unix Environment</title>
La siguiente consulta devuelve todos los ttulos de los libros en los que todos los
autores de cada libro es W. Stevens.
for $b in doc("[Link]")//libro
where every $a in $b/autor
satisfies ($a/last="Stevens" and $a/first="W.")
return $b/titulo
El resultado de esta consulta se muestra en el siguiente prrafo.
<titulo>TCP/IP Illustrated</titulo>
<titulo>Advanced Programming in the Unix Environment</titulo>
<titulo>The Economics of Technology and Content for Digital
TV</titulo>
El ltimo ttulo devuelto como resultado de la consulta es un libro que no tiene
autores. Cuando un cuantificador universal se aplica sobre un nodo vaco, siempre
devuelve cierto, como se ve en el ejemplo anterior.
Otro ejemplo. La siguiente consulta devuelve los ttulos de los libros que
mencionen Unix y programing en el mismo prrafo. Si el libro tiene ms de un
prrafo solo es necesario que aparezca en, al menos, uno de ellos. Esto lo indicamos con
la palabra reservada some justo a continuacin de where.
19
for $b in doc("[Link]")//libro
where some $p in $b//parrafo satisfies
(contains($p,"Unix") AND contains($p,"programing"))
return $b/title
Otro ejemplo. La siguiente consulta devuelve el ttulo de todos los libros que
mencionen programing en cada uno de los prrafos de los libros almacenados en
[Link].
for $b in doc("[Link]")//libro
where every $p in $b// parrafo satisfies
contains($p,"programing")
return $b/title
Esta consulta es distinta de la anterior ya que no es suficiente que programing
aparezca en al menos uno de los prrafos, sino que debe aparecer en todos los prrafos
que existan. Esto lo indicamos con la palabra reservada every justo a continuacin de
where.
3.6. Operadores y funciones principales.
El conjunto de funciones y operadores soportado por XQuery 1.0 es el mismo
conjunto de funciones y operadores utilizado en XPath 2.0 y XSLT 2.0.
XQuery soporta operadores y funciones matemticas, de cadenas, para el
tratamiento de expresiones regulares, comparaciones de fechas y horas, manipulacin de
nodos XML, manipulacin de secuencias, comprobacin y conversin de tipos y lgica
booleana. Adems permite definir funciones propias y funciones dependientes del
entorno de ejecucin del motor XQuery. Los operadores y funciones ms importantes se
muestran en la tabla 2 y se detallan a lo largo de este apartado.
Matemticos:
Comparacin:
Secuencia:
Redondeo:
Funciones de agrupacin:
Funciones de cadena:
Uso general:
+, -, *, div(*), idiv(*), mod.
=, !=, <, >, <=, >=, not()
union (|), intersect, except
floor(), ceiling(), round().
count(), min(), max(), avg(), sum().
concat(),
string-length(),
startswith(),
ends-with(),
substring(),
upper-case(), lower-case(), string()
distinct-values(), empty(), exits()
Tabla 2. Principales operadores y funciones de XQuery
20
(*)
La divisin se indica con el operador div ya que el smbolo / es necesario
para indicar caminos. El operador idiv es para divisiones con enteros en las que se
ignora el resto.
El resultado de un operador aritmtico en el que uno, o ambos, de los operandos
sea una cadena vaca es una cadena vaca. Como regla general el funcionamiento de las
cadenas vacas en XQuery es anlogo al funcionamiento de los valores nulos en SQL.
El operador unin recibe dos secuencias de nodos y devuelve una secuencia con
todos los nodos existentes en las dos secuencias originales. A continuacin se muestra
una consulta que usa el operador unin para obtener una lista ordenada de apellidos de
todos los autores y editores:
for $l in distinct-values(doc("[Link]")
//(autor | editor)/apellido)
order by $l
return <apellidos>{ $l }</apellidos>
El resultado de esta consulta se muestra en el siguiente prrafo:
<apellidos>Abiteboul</apellidos>
<apellidos>Buneman</apellidos>
<apellidos>Gerbarg</apellidos>
<apellidos>Stevens</apellidos>
<apellidos>Suciu</apellidos>
El operador de interseccin recibe dos secuencias de nodos como operandos y
devuelve una secuencia conteniendo todos los nodos que aparezcan en ambos
operandos.
El operador de sustraccin (except) recibe dos secuencias de nodos como
operandos y devuelve una secuencia conteniendo todos los nodos del primer operando
que no aparezcan en el segundo operando. A continuacin se muestra una consulta que
usa el operador sustraccin para obtener un nodo libro con todos sus nodos hijos salvo
el nodo <precio>.
for $b in doc("[Link]")//libro
where $b/titulo = "TCP/IP Illustrated"
return
<libro>
{ $b/@* }
{ $b/* except $b/precio }
</libro>
El resultado de esta consulta se muestra a continuacin.
21
<libro year = "1994">
<title>TCP/IP Illustrated</title>
<author>
<apellidos>Stevens</apellidos>
<first>W.</first>
</author>
<publisher>Addison-Wesley</publisher>
</libro>
La funcin distinct-values() extrae los valores de una secuencia de nodos y crea
una nueva secuencia con valores nicos, eliminando los nodos duplicados. Por ejemplo,
la siguiente consulta devuelve todos los apellidos distintos de los autores.
for $l in distinct-values(doc("[Link]")//autor/apellidos)
return <apellidos>{ $l }</apellidos>
El resultado de esta consulta se muestra en el siguiente prrafo.
<apellidos>Stevens</apellidos>
<apellidos>Abiteboul</apellidos>
<apellidos>Buneman</apellidos>
<apellidos>Suciu</apellidos>
La funcin empty() devuelve cierto cuando la expresin entre parntesis est
vaca. Por ejemplo, la siguiente consulta devuelve todos los nodos libro que tengan al
menos un nodo autor.
for $b in doc("[Link]")//libro
where not(empty($b/autor))
return $b
El resultado de esta consulta se muestra a continuacin.
<libro ao="1994">
<titulo>TCP/IP Illustrated</titulo>
<autor>
<apellido>Stevens</apellido>
<nombre>W.</nombre>
</autor>
<editorial>Addison-Wesley</editorial>
<precio> 65.95</precio>
</libro>
22
<libro ao="1992">
<titulo>Advan Programming for Unix environment</titulo>
<autor>
<apellido>Stevens</apellido>
<nombre>W.</nombre>
</autor>
<editorial>Addison-Wesley</editorial>
<precio>65.95</precio>
</libro>
<libro ao="2000">
<titulo>Data on the Web</titulo>
<autor>
<apellido>Abiteboul</apellido>
<nombre>Serge</nombre>
</autor>
<autor>
<apellido>Buneman</apellido>
<nombre>Peter</nombre>
</autor>
<autor>
<apellido>Suciu</apellido>
<nombre>Dan</nombre>
</autor>
<editorial>Morgan Kaufmann editorials</editorial>
<precio>39.95</precio>
</libro>
La funcin opuesta a empty() es exists(), la cual devuelve cierto cuando una
secuencia contiene, al menos, un elemento. Por ejemplo, como la consulta anterior tiene
una clusula where que comprueba una negacin sobre empty(), podemos rescribirla
usando la funcin exists() tal y como se muestra a continuacin:
for $b in doc("[Link]")//libro
where exists($b/autor)
return $b
El resultado de esta consulta es el mismo que el resultado de la consulta anterior.
3.7. Comentarios.
Los comentarios en XQuery, a diferencia de XML, van encerrados entre caras
sonrientes, tal y como se muestra a continuacin.
(: Esto es un comentario, y parece muy feliz :)
23
La sintaxis de comentario usada en XML no es aplicable a XQuery salvo que la
consulta se escriba con la sintaxis XQueryX, como se ver ms adelante.
3.8. XQueryX.
Como hemos visto, uno de los requerimientos de XQuery es que debe permitir
utilizar diferentes sintaxis para redactar las consultas. XQueryX es un ejemplo de
sintaxis alternativa para XQuery.
XQueryX es la especificacin de una sintaxis alternativa para XQuery que
permite definir una consulta XQuery mediante etiquetas XML. Con una sintaxis basada
en XML es ms sencillo analizar las consultas mediante el uso de herramientas
estndares y generar y consultar los contenidos de la consulta. Esto es til, por ejemplo,
para optimizaciones a nivel de cdigo fuente que dependen de la capacidad de
inspeccionar de forma rpida y sencilla el cdigo de una consulta.
Sin embargo, el borrador de XQueryX no ha sido actualizado desde su creacin
en el ao 2.001, ni el grupo de trabajo de XQuery ha hecho ningn comentario al
respecto sobre esta sintaxis, por lo que su futuro es bastante incierto.
Como ejemplo vamos a ver una sencilla consulta que devuelve la lista de todos
los autores de libros. Con la sintaxis de XQuery esta consulta se escribira como se
muestra a continuacin:
let $autores := /libro/autor
return
<autores>
{
$autores
}
</autores>
A continuacin se muestra la misma consulta escrita con la sintaxis XQueryX.
<q:query xmlns:q="[Link]
<q:flwr>
<q:letAssignment variable="$autores">
<q:step axis="CHILD">
<q:identifier/>
<q:step axis="CHILD">
<q:identifier>libro</q:identifier>
<q:identifier>autor</q:identifier>
</q:step>
</q:step>
</q:letAssignment>
<q:return>
<q:elementConstructor>
<q:tagName>
<q:identifier>autores</q:identifier>
</q:tagName>
<q:variable>$autores</q:variable>
</q:elementConstructor>
24
</q:return>
</q:flwr>
</q:query>
A continuacin se muestra el resultado de ambas consultas.
<autores>
<autor>
<apellido>Stevens</apellido>
<nombre>W.</nombre>
</autor>
<autor>
</autor>
<autor>
<apellido>Stevens</apellido>
<nombre>W.</nombre>
<apellido>Abiteboul</apellido>
<nombre>Serge</nombre>
</autor>
<autor>
<apellido>Buneman</apellido>
<nombre>Peter</nombre>
</autor>
<autor>
</autor>
</autores>
<apellido>Suciu</apellido>
<nombre>Dan</nombre>
3.9. Ejemplos de consultas
Como ya hemos visto, la consulta ms sencilla posible en XQuery es una
expresin en XPath, por ejemplo:
document("[Link]")//libro[titulo="Ricotta Pie"]
La expresin anterior devuelve todos los nodos <libro> que tengan un hijo
<titulo> con el valor Ricotta Pie del conjunto de datos almacenado en el archivo
[Link]. El orden de los libros ser, por defecto, el mismo orden en que aparecen
en el documento [Link].
Partiendo del conjunto de datos detallados en el apartado 2.2, vamos a escribir
una serie de consultas y a mostrar cuales serian los resultados obtenidos.
Escribir una consulta que obtenga el nombre y el ao de todos los libros
publicados por Addison-Wesley despus de 1991. El cdigo de la consulta ser:
25
<bib>
{
for $b in doc("[Link]")/bib/libro
where $b/editorial = "Addison-Wesley" and $b/@ao > 1991
return
<libro ao="{ $b/@ao }">
{ $b/titulo }
</libro>
}
</bib>
El resultado de esta consulta se muestra a continuacin.
<bib>
<libro ao="1994">
<titulo>TCP/IP Illustrated</titulo>
</libro>
<libro ao="1992">
<titulo>Advanced Programming in the Unix environment
</titulo>
</libro>
</bib>
Escribir una consulta que obtenga el ttulo de los libros cuyo precio est por
debajo de 50.00.
for $b in doc("[Link]")//libro
where $b/precio < 50.00
return $b/titulo
El resultado de esta consulta se muestra a continuacin.
<titulo>Data on the Web</titulo>
Escribir una consulta que, por cada libro almacenado en el archivo "[Link]"
devuelva el ttulo del libro, el precio con que consta dicho libro en el archivo
"[Link]" y el precio con que consta ese libro en el archivo "[Link]".
<libros-con-precios>
{
for $b in doc("[Link]")//libro,
$a in doc("[Link]")//entry
where $b/titulo = $a/titulo
26
return
<libro-con-precios>
{ $b/titulo }
<precio-btienda2>{ $a/precio/text() }
</precio-btienda2>
<precio-btienda1>{ $b/precio/text() }
</precio-btienda1>
</libro-con-precios>
}
</libros-con-precios>
Los resultados de esta consulta se muestran a continuacin.
<libros-con-precios>
<libro-con-precios>
<titulo>TCP/IP Illustrated</titulo>
<precio-btienda2>65.95</precio-btienda2>
<precio-btienda1>65.95</precio-btienda1>
</libro-con-precios>
<libro-con-precios>
<titulo>Advanced Programming in the Unix
environment</titulo>
<precio-btienda2>65.95</precio-btienda2>
<precio-btienda1>65.95</precio-btienda1>
</libro-con-precios>
<libro-con-precios>
<titulo>Data on the Web</titulo>
<precio-btienda2>34.95</precio-btienda2>
<precio-btienda1>39.95</precio-btienda1>
</libro-con-precios>
</libros-con-precios>
Escribir una consulta que, por cada libro con autores, devuelva el ttulo del libro
y sus autores. Si el libro no tiene autores pero s editor, la consulta devolver el ttulo
del libro y la afiliacin del editor.
<bib>
{
for $b in doc("[Link]")//libro[autor]
return
<libro>
{ $b/titulo }
{ $b/autor }
</libro>
}
{
for $b in doc("[Link]")//libro[editor]
return
<referencia>
27
{ $b/titulo }
{$b/editor/afiliacion}
</referencia>
}
</bib>
Los resultados de esta consulta se muestran a continuacin.
<bib>
<libro>
<titulo>TCP/IP Illustrated</titulo>
<autor>
<apellidos>Stevens</apellidos>
<nombre>W.</nombre>
</autor>
</libro>
<libro>
<titulo>Advanced Programming in the Unix
environment</titulo>
<autor>
<apellidos>Stevens</apellidos>
<nombre>W.</nombre>
</autor>
</libro>
<libro>
<titulo>Data on the Web</titulo>
<autor>
<apellidos>Abiteboul</apellidos>
<nombre>Serge</nombre>
</autor>
<autor>
<apellidos>Buneman</apellidos>
<nombre>Peter</nombre>
</autor>
<autor>
<apellidos>Suciu</apellidos>
<nombre>Dan</nombre>
</autor>
</libro>
<referencia>
<titulo>The Economics of Technology and Content for
Digital TV</titulo>
<afiliacion>CITI</afiliacion>
</referencia>
</bib>
Mostrar los pares de ttulos que sean distintos pero tengan el mismo autor o
grupo de autores. Hay que tener en cuenta que el orden de aparicin de los autores
puede variar de un libro a otro.
28
<bib>
{
for $libro1 in doc("[Link]")//libro,
$libro2 in doc("[Link]")//libro
let $aut1 := for $a in $libro1/autor
order by $a/apellidos, $a/nombre
return $a
let $aut2 := for $a in $libro2/autor
order by $a/apellidos, $a/nombre
return $a
where $libro1 << $libro2
and not($libro1/titulo = $libro2/titulo)
and deep-equal($aut1, $aut2)
return
<libro-par>
{ $libro1/titulo }
{ $libro2/titulo }
</libro-par>
}
</bib>
Los resultados de esta consulta se muestran a continuacin.
<bib>
<libro-par>
<titulo>TCP/IP Illustrated</titulo>
<titulo>Advanced Programming in the Unix
environment</titulo>
</libro-par>
</bib>
Esta consulta usa la funcin deep-equal() encargada de comparar secuencias de
nodos. Para la funcin deep-equal() dos consultas son iguales si todos los nodos de la
primera secuencia aparecen en la segunda secuencia en la misma posicin que en la
primera secuencia.
Tambin es posible utilizar XQuery para trasformar datos XML en otros
formatos, como HTML, convirtindose XQuery en una alternativa ms sencilla y rpida
de usar que XSLT. A continuacin, como ejemplo, se muestra una consulta que crea
una tabla HTML con los ttulos de todos los libros contenidos en el archivo
[Link].
<html> <head> <title> </title>
<body> <table>
{
for $b in doc("[Link]")/bib/libro
return
<tr> <td> <I> { string( $b/titulo ) } </I> </td> </tr>
29
}
</table> </body>
</head> </html>
El resultado de la consulta anterior se muestra a continuacin:
<html><head><title> </title>
<body>
<table>
<tr><td><I>TCP/IP Illustrated</I></td></tr>
<tr><td><I>Advan Programming for Unix environment</I></td></tr>
<tr><td><I>Data on the Web</I></td></tr>
<tr><td><I>Economics of Technology for Digital TV</I></td></tr>
</table></body>
</head></html>
A continuacin, en la figura 4, se muestra como se visualizara la pgina anterior
en un navegador web:
Figura 4. Resultado de la conversin de un conjunto de datos XML en HTML.
30
4. XQuery y Java.
A lo largo de este apartado se analizan las caractersticas de un motor XQuery
open-source escrito en la plataforma Java y vamos a ver como utilizarlo desde nuestras
propias aplicaciones. El motor elegido es XQEngine[7], aunque en el punto 4.4 se
comentan brevemente otros motores open-source existentes para la plataforma Java.
4.1. XQEngine.
XQEngine es un motor GPL dedicado al indexado y bsqueda de informacin en
ficheros XML cuya sintaxis de consulta es una implementacin de XQuery. XQEngine
es un componente muy compacto, con un tamao aproximado de 360 KBs, y por lo
tanto, fcilmente integrable dentro de nuestras aplicaciones. La versin actual de esta
herramienta es la 0.63.
XQEngine se distribuye con una sencilla aplicacin de ejemplo
"[Link]" que, adems de mostrar con un caso prctico como utilizar este
componente en nuestros desarrollos, contiene un sencillo interfaz grfico que permite
ejecutar directamente consultas XQuery y obtener sus resultados.
En los siguientes apartados se describe esta aplicacin, la cual es una valiosa
ayuda a la hora de escribir y depurar nuestras consultas y, a continuacin, se analiza
como incluir XQEngine en nuestros programas.
4.2. Ejecutando consultas con XQEngine.
Para ejecutar la aplicacin de ejemplo, simplemente hay que escribir java
SampleApp y obtener as la interfaz de la aplicacin mediante la cual se puede escribir
y ejecutar consultas XQuery y obtener los resultados. Esta interfaz se muestra en la
figura 5.
31
Figura 5. Interfaz de SampleApp
SampleApp carga e indexa un conjunto de archivos XML con datos de
ejemplo para poder ejecutar consultas sobre ellos. Estos ficheros son: "[Link]",
"[Link]",
"[Link]",
"[Link]",
"bib_2.xml",
"nsTest_1.xml",
"nsTest_2.xml", "nsTest_3.xml" y "Bug_10jan04_1.xml" y tambin se distribuyen
junto con XQEngine.
La aplicacin no ofrece ninguna forma de indicar que archivos XML queremos
que se carguen e indexen al inicio. La nica manera de agregar nuestros propios
archivos es modificar directamente el cdigo de la clase [Link].
Concretamente, en el mtodo run() de dicha clase se indica el nombre de los archivos
XML que debe cargar e indexar SampleApp. Para aadir el archivo que venimos usando
como base para los ejemplos, [Link], suponiendo que se encuentra en la misma
carpeta que los archivos anteriores, aadimos a la clase SampleApp la siguiente lnea.
32
public void run()
{
[..]
m_engine.setDocument([Link]);
[..]
}
Ahora, al ejecutar la aplicacin, incluir en su ndice de archivos al archivo
[Link].
Para ejecutar una consulta hay que redactarla en la mitad superior de la ventana.
Una vez completada la consulta es necesario pulsar dos veces la tecla Enter para que
la aplicacin la ejecute y muestre los resultados en la mitad inferior de la ventana. En la
figura 6 se muestra un ejemplo de consulta, en la mitad superior, y de sus resultados, en
la mitad inferior.
Figura 6. Ejemplo de consulta y resultados.
Tanto la mitad de edicin de la consulta como la mitad que muestra los
resultados soportan copiar (CTRL+C) y pegar (CTRL+V), pero no deshacer.
Si la consulta no est bien escrita, en la mitad inferior de la pantalla de la
aplicacin obtendremos un mensaje de: InvalidQueryException. Un mensaje de error
ms descriptivo se enva a la salida estndar. Por ejemplo, en la figura 7 se muestra el
mensaje de error obtenido al intentar ejecutar la consulta anterior sin escribir la clusula
for.
33
Figura 7. Consulta errnea.
Y en la salida estndar obtenemos el siguiente mensaje, bastante ms descriptivo
que el anterior.
[Link]:
Encountered "$" at line 3, column 6
.
Was expecting one of:
"or" ...
"and" ...
"to" ...
"=" ...
"is" ...
"!=" ...
"isnot" ...
"<=" ...
"<<" ...
">=" ...
">>" ...
"eq" ...
"ne" ...
"gt" ...
"ge" ...
"lt" ...
"le" ...
"<" ...
34
">" ...
"[" ...
"," ...
"}" ...
"/" ...
"//" ...
"(" ...
Ni esta aplicacin ni XQEngine soportan la sintaxis XQueryX para la redaccin
de las consultas.
4.3. Embebiendo XQEngine en una aplicacin Java.
Para mostrar como utilizar XQEngine como componente en nuestras
aplicaciones Java vamos a desarrollar un sencillo ejemplo. Este ejemplo ejecutar una
consulta sobre el archivo [Link] y mostrar el resultado de la consulta por
pantalla.
Para implementar el ejemplo vamos a crear una clase llamada
EjemploXQEngine que contenga un nico mtodo main que contendr todo el
cdigo necesario para el ejemplo. El cdigo completo de la clase se muestra a
continuacin.
import [Link];
import [Link];
import [Link].*;
import [Link].*;
import [Link];
public class EjemploXQEngine
{
public static void main(String[] args)
{
String query = "<bib> { "
+ " for $b in doc(\"[Link]\")/bib/libro"
+ " where $b/editorial = \"Addison-Wesley\"
+ and $b/@ao > 1991 "
+ " return "
+ " <libro> { $b/titulo } </libro>"
+ " } </bib> ";
XQEngine engine;
engine = new XQEngine();
SAXParserFactory spf = [Link]();
try
35
SAXParser parser = [Link]();
XMLReader reader = [Link]();
[Link]( reader );
[Link]( "[Link]" );
ResultList results = [Link]( query );
[Link]( [Link]() );
[Link]( ---------------------- );
[Link]( [Link]() );
}
catch( Exception e )
{
[Link]();
}
};
En los siguientes prrafos se detalla el funcionamiento del cdigo anterior.
En primer lugar, crear una instancia del motor XQEngine es tan sencillo como
declarar una variable de tipo XQEngine y crear un nuevo objeto de ese tipo. Sin
embargo, antes de que el motor de XQEngine, pueda funcionar necesita dos elementos:
el primero es un parser SAX para leer los documentos XML. En este ejemplo se ha
optado por usar el parser SAX de SUN por ser el ms difundido ya que viene con la
distribucin de J2EE, pero otros parsers, como el que se incluye en el componente
Xerces[19] de Apache, son perfectamente vlidos.
El segundo elemento que XQEngine necesita es el conjunto de archivos XML
que contienen los datos sobre los que se van a ejecutar las consultas. XQEngine necesita
conocer previamente estos archivos para poder indexarlos antes de realizar ninguna
consulta. En este ejemplo solo utilizamos un archivo [Link] pero, en principio,
XQEngine no impone ninguna limitacin sobre el nmero de archivos que podamos
cargar e indexar.
Una vez obtenido un objeto XQEngine, es posible realizar tantas consultas como
se desee. Al ejecutar una consulta, XQEngine devuelve el resultado en un objeto de tipo
ResultList. El mtodo de este objeto toString() devuelve las estadsticas de la consulta y
el mtodo emitXml() devuelve el resultado como un String .
El resultado de la ejecucin de la clase EjemploXQEngine se muestran a
continuacin.
[Link]():
NumDocuments
= 1
NumTotalItems = 1
NumValidItems = 1
Document id
= -1 ["QUERY_DOCUMENT"]
NumTotalItems = 1
36
NumValidItems = 1
[0][0] <bib> [parent=-1]
---------------------<bib><libro><titulo>TCP/IP
Illustrated</titulo></libro><libro><titulo>Advan Programming fo
r Unix environment</titulo></libro></bib>
4.4. Otros motores XQuery open-source.
En este apartado se enumeran los motores XQuery open-source ms relevantes y
sus caractersticas principales.
Qexo:
Qexo[8] es un motor XQuery escrito en Java y con licencia GPL que se
distribuye integrado dentro del paquete Kawa.
Saxon:
Saxon[10] es otro motor XQuery escrito en Java que se distribuye en dos
paquetes, uno de ellos, Saxon-B es open-source bajo licencia GPL y contiene una
implementacin bsica de XSLT 2.0 y XQuery, mientras que el segundo paquete,
Saxon-SA, contiene un procesador completo XSLT y XQuery pero tiene licencia
propietaria, aunque est disponible una licencia de evaluacin de 30 das.
Qizx/open:
Qizx/open[9] es una implementacin Java de la ltima versin de las
especificaciones XQuery. Implementa todas las caractersticas del lenguaje excepto la
importacin y validacin de XML-Schemas. Actualmente este es el motor con licencia
GPL ms completo que existe.
4.5. Otras herramientas relacionadas con XQuery.
En este apartado se describen brevemente otras herramientas relacionadas con
XQuery.
Xquark Bridge:
XQuark Bridge[16] es una herramienta que permite importar y exportar datos a
bases de datos relacionales utilizando XML. De este modo, XQuark ofrece la
posibilidad de manejar estructuras XML y realizar la transformacin a objetos de la
base de datos, siendo capaz tambin de realizar el paso contrario. Adems de todo esto
XQuark es capaz de respetar todas las restricciones de integridad y transformar las
relaciones implcitas en los documentos XML en relaciones explcitas en la base de
datos y todo ello con un buen rendimiento.
XQuark-Bridge soporta tambin la consulta y manipulacin de los datos en
formato XML utilizando el lenguaje XQuery.
XQuark-Bridge soporta MySQL, Oracle, SQLServer y Sybase, tiene una
licencia LGPL.
37
BumbleBee:
BumbleBee[7] es un entorno de prueba automtico creado con el fin de evaluar
motores de XQuery y validar consultas escritas en sintaxis XQuery. BumbleBee permite
evaluar que grado de satisfaccin de los borradores del estndar y especificaciones
satisface un motor XQuery y comprobar si una versin ms moderna de nuestro motor
permite seguir ejecutando nuestras consultas.
BumbleBee se distribuye con un conjunto de pruebas ya preparadas y, adems,
ofrece un entorno sencillo para redactar y ejecutar nuestras propias pruebas.
Actualmente soporta los motores XQuery open-source: Qexo[8], Qizx/open[9] y
Saxon[10] y los motores XQuery propietarios: Cerisent[11], Ipedo[12], IPSI-XQ[13] y
X-Hive[14].
BumbleBee es software propietario aunque est disponible para descarga una
versin de demostracin completamente funcional durante 30 das.
38
5. Conclusiones
XQuery es en la actualidad, y a pesar de estar an en fase de borrador, una
tecnologa emergente con grandes expectativas en el mundo de la programacin y del
tratamiento y manipulacin de informacin como lo demuestra el nmero de empresas
que estn apostando por desarrollar implementaciones de motores de consulta basados
en XQuery.
Sus principales aplicaciones se pueden resumir en tres grandes grupos.
En primer lugar, recuperar informacin a partir de conjuntos de datos XML.
Hemos expuesto en este trabajo, a travs de los ejemplos, como, gracias a un lenguaje
sencillo, potente y flexible, es posible recorrer los nodos de un conjunto de datos XML,
filtrando aquellos que nos interesen y transformndolos para mostrar la informacin
deseada con la estructura adecuada.
En segundo lugar, transformar unas estructuras de datos XML en otras
estructuras que organicen la informacin de forma diferente. Por ejemplo, es sencillo y
fcil obtener a partir de la jerarqua de datos almacenada en el archivo "[Link]", otra
jerarqua de datos donde se almacene una lista con todos los autores y los libros que ha
escrito cada autor, tal y como se muestra en la figura 8.
<libro ao="1994">
<titulo>TCP/IP Illustrated</titulo>
<autor>
<apellido>Stevens</apellido>
<nombre>W.</nombre>
</autor>
<editorial>Addison-Wesley</editorial>
<precio> 65.95</precio>
</libro>
<libro ao="1992">
<titulo>Advan Programming for Unix
environment</titulo>
<autor>
<apellido>Stevens</apellido>
<nombre>W.</nombre>
</autor>
<editorial>Addison-Wesley</editorial>
<precio>65.95</precio>
</libro>
<autor>
<apellido>Stevens</apellido>
<nombre>W.</nombre>
<libros>
<titulo>TCP/IP Illustrated</titulo>
<titulo>Advan Programming for
Unix environment</titulo>
</libros>
</autor>
Figura 8. Transformacin de una jerarqua en otra mediante XQuery.
Y en tercer lugar, ofrecer una alternativa a XSLT para realizar transformaciones
de datos en XML a otro tipo de representaciones, como HTML o PDF. Ya hemos visto
en uno de los ejemplos del punto 3.9 lo sencillo que resulta escribir una consulta
XQuery para que genere cdigo HMTL.
Actualmente tambin existe un nmero variado de implementaciones opensource, lo que nos ofrece libertad de eleccin, y estn lo suficientemente maduras como
para poder ser incorporadas con garantas a cualquier proyecto de programacin, con la
condicin de que dicho proyecto mantenga la licencia GPL y siga siendo open-source.
39
6. Referencias y enlaces.
[1] Marchal, Benot. XML by Example. QUE. 2.001 West 103rd Street, Indianapolis, Indiana
46290.
[2] McLaughlin, Brett. Java and XML Data Binding. 2.002. O'Reilly.
[3] Robert Gardner, John; Rendon, Zarella L. XSLT and XPATH: A Guide to XML
Transformations. 2001. Prentice Hall PTR
[4] Katz, Howard; Chamberlin, Don, et-al. XQuery from the Experts: A Guide to the W3C XML
Query Language. 2.003. Addison Wesley
[5] Brundage, Michael. XQuery: The XML Query Language. 2.004. Addison Wesley
[6] XQEngine. [Link]
[7] BumbleBee. [Link]
[8] Qexo. [Link]
[9] Qizx/open. [Link]
[10] Saxon. [Link]
[11]Cerisent. [Link]
[12] Ipedo. [Link]
[13] IPSI-XQ. [Link]
[14] X-Hive. [Link]
[15] JAXB, API Java de Sun para XML Binding. [Link]
[16] Xquark. [Link]
[17] SAX project website. [Link]
[18] DOM home page. [Link]
[19] Apache's XML parser. [Link]
[20] W3C Xquery. [Link]
40
Apndice I. Parses SAX y DOM
En el contexto de este artculo, un parser es una herramienta que procesa una
coleccin de datos organizados en un rbol de etiquetas que sigue la sintaxis XML.
Estos parsers son construidos como libreras o componentes para ser utilizarlos en
programas que manejen colecciones de datos en XML. A continuacin se describen
brevemente las caractersticas principales de un parser SAX y un parser DOM.
SAX.
SAX[1][17] es un parser dirigido por eventos. Esto significa que cada vez que
aparece un elemento XML, como la apertura o cierre de una nueva etiqueta, el parser
genera un evento. La programacin con un parser SAX consiste en redefinir las
funciones de los eventos que nos interese controlar y, para cada evento, comprobar el
valor de la etiqueta y actuar en consecuencia.
Las ventajas principales de los parsers SAX son que no necesita una gran
cantidad de memoria, ya que solo carga la seccin de datos XML con la que est
trabajando, y que es rpido y sencillo escribir parsers SAX simples. Sus principales
inconvenientes son que depende completamente de la estructura del documento, si
cambia la estructura es necesario modificar el cdigo, no es reutilizable de un
documento a oro a menos que compartan las mismas etiquetas y estructura de datos y,
como se procesa a medida que se lee, no se tiene informacin de lo que viene a
continuacin y solo se pueden escribir acciones simples.
DOM.
DOM[1][18], a diferencia del anterior, carga todo el conjunto de datos XML en
memoria en la forma de un rbol n-ario. Cualquier operacin sobre el conjunto de datos
se realiza sobre el rbol que se almacena en memoria.
Como ventajas, es ms rpido que SAX ya que trabaja con los datos en memoria
y no en el archivo. Adems, al tener toda la estructura de datos disponible, es posible
obtener informacin de lo que viene a continuacin, retroceder, o hacer varias
bsquedas.
Como inconvenientes, es ms complejo trabajar con un parser DOM ya que es
necesario escribir un recorrido sobre un rbol n-ario, necesita ms cantidad de memoria
que SAX y es ms lento, aunque si es necesario recorrer ms de un vez el documento o
una parte de l, DOM gana en velocidad.
41
Apndice II. XML Binding
Bsicamente la idea que se esconde tras el trmino binding (vincular o
vinculacin)[2] es tomar un documento que contiene un conjunto de datos expresados
en XML y convertirlo en una instancia de un objeto, que puede estar formado a su vez
por varios objetos. El proceso de binding est basado en cuatro conceptos que
estudiaremos a continuacin. Estos conceptos son:
Generacin de cdigo fuente
Unmarshalling
Marshalling
Binding schemas (esquemas de vinculacin)
Las herramientas de binding, como primer paso, permiten crear automticamente
un conjunto de clases a partir de los DTDs o XML-Schemas del conjunto de datos.
Estas clases sern instanciadas y sus objetos almacenarn los datos del documento XML
por la herramienta vinculadora.
Una vez que se han generado las clases ya se puede convertir el documento
XML en un conjunto de objetos. Esta operacin se conoce con el nombre de
unmarshalling. La operacin opuesta se conoce con el nombre de marshalling y consiste
en almacenar en un documento XML, la informacin contenida en los atributos de un
objeto o conjunto de objetos.
Aunque no es necesario, las herramientas de binding permiten definir binding
schemas (esquemas de vinculacin), los cuales permiten indicar con mayor precisin las
conversiones de tipo o transformaciones de nombres.
Las herramientas de binding tienen la ventaja de que son sencillas y rpidas de
utilizar, generan automticamente la estructura de clases necesaria para cargar en
memoria la estructura de datos XML, y nos permite abstraernos de conceptos de bajo
nivel, como la lectura y procesamiento del archivo XML. Tambin tienen el
inconveniente de que es necesario disponer en DTD o el XML-Schema de la estructura
de datos para poder generar el cdigo fuente. Adems, el proceso de binding solo realiza
la carga en memoria de la estructura de datos XML, al igual que DOM pero, a
diferencia de este, organizado como un conjunto de objetos en vez de un rbol n-ario,
por lo que es necesario escribir procedimientos de bsqueda de la informacin
dependientes de dicha estructura de objetos.
JAXB[15] es el nombre del API oficial de SUN para binding de archivos XML.
Ya existe una implementacin de referencia de este API suministrado por la propia Sun.
Algunas de las caractersticas principales de esta API se detallan a continuacin.
Soporta binding a partir de DTDs y XML Schema.
Permite personalizacin del binding.
Estandariza las interfaces para las clases generadas.
Soporta validacin de documentos.
Soporta validacin de rboles XML.
A continuacin, en la tabla 3, se muestran los enlaces a varias herramientas de
binding para Java.
42
Castor
[Link]
Xgen
[Link]
Breeze
[Link]
Zeus
[Link]
XMLBeans
[Link]
Tabla 3. Herramientas de binding para plataforma Java.
43
Apndice III. Xpath.
XPath es un lenguaje de expresin utilizado para referenciar nodos de
informacin en un conjunto de datos XML. XQuery utiliza este lenguaje para las
clusulas for y let de una consulta.
Actualmente tanto XQuery 1.0 como XPath 2.0 estn en desarrollo por el mismo
grupo de trabajo de la W3C, dado que XQuery hace un uso intensivo de XPath.
Las expresiones XPath tienen un comportamiento similar a las expresiones
regulares aplicadas al contexto de un conjunto de datos en XML y, ms concretamente,
al un conjunto de nodos XML en vez de un conjunto de caracteres.
XPath es muy fcil de entender mediante ejemplos. A continuacin mostramos
algunas expresiones bsicas y lo que se obtiene a partir de ellas:
/html/body/h1
Selecciona todos los nodos <h1> que son hijos de un nodo <body> que, a su vez,
es hijo de un nodo <html> que es el nodo raz del rbol XML. El resultado ser todos
los nodos <h1> que cumplan la anterior condicin.
//h1
Selecciona todos los nodos <h1> que aparezcan en cualquier posicin del rbol
XML. La doble barra indica cualquier profundidad.
count(//libro)
Devuelve el nmero de nodos <libro> que aparecen en el documento en
cualquier posicin.
//libro[autor = "Hunter"]
Devuelve todos los nodos <libro> que aparezcan en el documento en cualquier
posicin y que tengan un nodo hijo <autor> con el valor "Hunter". Los corchetes
indican un filtro para seleccionar los resultados que cumplan una determinada
condicin.
//libro[@ao > 1999]
44
Devuelve todos los nodos <libro> que tengan un atributo "ao" con un valor
superior a 1999. La arroba indica que "ao" no es un hijo (una etiqueta) sino un atributo
de la etiqueta libro.
//libro[@paginas]
Devuelve todos los nodos <libro> que tengan un atributo paginas,
independientemente del valor de ese atributo.
//libro/@paginas
Devuelve todos los atributos pagina de los nodos <libro>.
(i | b)
Devuelve todos los nodos <i> o todos los nodos <b> que encuentre en el nodo
contexto. Por defecto el nodo contexto es el nodo raz del documento.
XPath soporta el uso de predicados, los cuales son condiciones booleanas que
permiten seleccionar un subconjunto de los nodos referenciados. La expresin se evala
por cada nodo encontrado y segn sea cierta o falsa, el nodo se selecciona o se descarta.
A continuacin se muestra un ejemplo:
(//servlet | //servlet-mapping) [servlet-name = $servlet]
Devuelve todos los nodos <servlet> o <servlet-maping> que tengan un hijo
llamado <servelt-name> cuyo valor coincida con el valor de la variable $servlet.
Si el predicado contiene un literal numrico, se trata como si fuera un ndice, tal
y como muestra el siguiente ejemplo:
doc("[Link]")/bib/libro/autor[1]
La expresin anterior devuelve solo el primero nodo autor que encuentre para
cada nodo libro.
(doc("[Link]")/bib/libro/autor)[1]
La expresin anterior es igual a la que acabamos de ver, excepto por los
parntesis. Estos parntesis fuerzan a que se evale primero el recorrido por los nodos
45
autor de cada libro, y despus se aplique el predicado, por lo que el resultado de esta
expresin ser el primer autor que aparezca en el archivo [Link].
//key[. = "Tiempo total"]
Devuelve todos los nodos <key> que tengan un valor de "Tiempo total.". El
carcter "." representa el nodo contexto, lo cual tiene una funcin similar al operador
"this" en lenguajes como C++ o Java.
(//key)[1]/texto
Devuelve los nodos <texto> del primer nodo <key> del documento.
46
Apndice IV. Conjunto de documentos que describen XQuery y
XPath.
A continuacin se detalla el conjunto de documentos que describen y definen
XQuery en su totalidad, junto con la URL donde se encuentra cada documento.
XML Query Requirements.
Este el documento principal del grupo de trabajo y el que contiene el conjunto de
requerimientos de XQuery
[Link]
XML Query Use Cases.
Este documento contiene un conjunto de escenarios reales y y varias consultas
XQuery para cada uno de esos escenarios.
[Link]
XQuery 1.0: An XML Query Language.
Este es el documento principal del proyecto, el cual presenta el lenguaje y da una
perspectiva de todos sus aspectos.
[Link]
XQuery 1.0 and XPath 2.0 Data Model.
Este documento describe una extensin de conjunto de modelo de datos de
XML.
[Link]
XQuery 1.0 and XPath 2.0 Formal Semantics.
Este documento contiene la definicin formal algebraica del lenguaje.
[Link]
XML Syntax for XQuery 1.0 (XQueryX).
Este documento describe una sintaxis alternativa para poder escribir las
consultas en XML.
[Link]
XQuery 1.0 and XPath 2.0 Functions and Operators Version 1.0.
Este documento detalla las funciones y operadores bsicos soportados por
XQuery y XPath.
[Link]
XML Path Language (XPath) 2.0.
Este documento contiene la documentacin sobre XPath.
[Link]
XSLT 2.0 and XQuery 1.0 Serialization.
Este documento expone una primera aproximacin a las consideraciones
involucradas en la serializacin del modelo de datos usado en XQuery y XPath.
47
[Link]
XML Query and XPath Full-Text Requirements.
Este documento contiene la descripcin de los requisitos que una
implementacin completa debe ser capaz de cumplir.
[Link]
XML Query and XPath Full-Text Use Cases.
Este documento detalla un conjunto de escenarios tomados del mundo real que
una especificacin completa debe ser capaz de gestionar.
[Link]
48