1. XPath. Introducción 2. El modelo de datos de XPath

Anuncio
1. XPath. Introducción
1.1 Qué es y para qué sirve
Todo el procesamiento realizado con un fichero XML está basado en la posibilidad de direccionar o acceder a cada una de las partes que lo componen, de modo que podamos tratar cada uno de los elementos de forma diferenciada. El tratamiento del fichero XML comienza por la localización del mismo a lo largo del conjunto de documentos existentes en el mundo. Para llevar a cabo esta localización de forma unívoca, se utilizan los URI (Unifom Resource Identifiers), de los cuales los URL (Unifom Resource Locators) son sin duda los más conocidos. Una vez localizado el documento XML, la forma de seleccionar información dentro de él es mediante el uso de XPath, que es la abreviación de lo que se conoce como XML Path Language. Con XPath podremos seleccionar y hacer referencia a texto, elementos, atributos y cualquier otra información contenida dentro de un fichero XML. XPath en sí es un lenguaje sofisticado y complejo, pero distinto de los lenguajes procedurales que solemos usar (C, C++, Basic, Java...). Además, como casi todo en el mundo de XML, aún está en estado de desarrollo, por lo que no es fácil encontrar herramientas que incorporen todas sus funcionalidades. XPath es a su vez la base sobre la que se han especificado nuevas herramientas que aprovechar para el tratamiento de documentos XML. Herramientas tales como XPointer, XLink y XQL (el lenguaje que maneja los documentos XML como si de una base de datos se tratase), que también están en estado de desarrollo, pero que sin duda cambiarán el modo en que actualmente concebimos la navegación por la Web. Así, XPath sirve para decir cómo debe procesar una hoja de estilo el contenido de una página XML, pero también para poder poner enlaces o cargar en un navegador zonas determinadas de una página XML, en vez de toda la página.
2. El modelo de datos de XPath
2.1. Construcción del Árbol de Nodos
Un documento XML es procesado por un analizador (o parser) construyendo un árbol de nodos. Este árbol comienza con un elemento raíz, que se diversifica a lo largo de los elementos que cuelgan de él y acaba en nodos hoja, que contienen sólo texto, comentarios, intrucciones de proceso o incluso que están vacíos y sólo tienen atributos La forma en que XPath selecciona partes del documento XML se basa precisamente en la representación arbórea que se genera del documento. De hecho, los "operadores" de que consta este lenguaje nos recordarán la terminología que se utiliza a la hora de hablar de árboles en informática: raíz, hijo, ancestro, descendiente, etc... Un caso especial de nodo son los nodos atributo. Un nodo puede tener tantos atributos como desee, y para cada uno se creará un nodo atributo. No obstante, dichos nodos atributo NO se consideran como hijos suyos, sino más bien como etiquetas añadidas al nodo elemento. A continuación se muestra un ejemplo de cómo se convierte en árbol un documento XML. Este mismo ejemplo será usado a lo largo de todo el tutorial. En primer lugar se muestra el documento XML y a continuación el árbol que genera. Página XML: <libro>
<titulo>Dos por tres calles</titulo>
<autor>Josefa Santos</autor>
<capitulo num="1">
La primera calle
<parrafo>
Era una sombria noche del mes de agosto...
</parrafo>
<parrafo destacar="si">
Ella, inocente cual
<enlace href="http://www.enlace.es">mariposa</enlace>
que surca el cielo en busca de libaciones...
</parrafo>
</capitulo>
<capitulo num="2" public="si">
La segunda calle
<parrafo>Era una obscura noche del mes de septiembre...</parrafo>
<parrafo>
Ella, inocente cual
<enlace href="http://www.abejilla.es">abejilla</enlace>
que surca el viento en busca del nectar de las flores...
</parrafo>
</capitulo>
<apendice num="a" public="si">
La tercera calle
<parrafo>
Era una densa noche del mes de diciembre...
</parrafo>
<parrafo>
Ella, candida cual
<enlace href="http://www.pajarillo.es">abejilla</enlace>
que surca el espacio en busca de bichejos para comer...
</parrafo>
</apendice>
</libro>
Árbol generado: /
|
+---libro
|
+---titulo
|
|
|
+---(texto)Dos por tres calles
|
+---autor
|
|
|
+---(texto)Josefa Santos
|
+---capitulo [num=1]
|
|
|
+---(texto)La primera calle
|
|
|
+---parrafo
|
|
|
|
|
+---(texto)Era una sombría noche ...
|
+---parrafo
|
|
|
+---(texto)Ella, cual inocente mariposa...
|
+---capitulo [num=2]
|
+---(texto)La segunda calle
|
+---parrafo
|
|
|
+---(texto)Era una obscura noche ...
+---parrafo
|
+---(texto)Ella, cual inocente abeja...
2.2. Tipos de Nodos
Existen distintos tipos de nodos en un árbol generado a partir de un documento XML, a saber: raíz, elemento, atributo, texto, comentario e instrucción de procesamiento (respectivamente; root, elements, attribute, text, comment y processing instruction). Nodo Raíz
Se identifica por /. No se debe confundir el nodo raíz con el elemento raíz del documento. Así, si el documento XML de nuestro ejemplo tiene por elemento raíz a libro, éste será el primer nodo que cuelgue del nodo raíz del árbol, el cual es: /. Insisto: / hace referencia al nodo raíz del árbol, pero no al elemento raíz del documento XML, por más que un documento XML sólo pueda tener un elemento raíz. De hecho, podemos afirmar que el nodo raíz del árbol contiene al elemento raíz del documento. Nodo Elemento
Cualquier elemento de un documento XML se convierte en un nodo elemento dentro del árbol. Cada elemento tiene su nodo padre. El nodo padre de cualquier elemento es, a su vez, un elemento, excepto el elemento raíz, cuyo padre es el nodo raíz. Los nodos elemento tienen a su vez hijos, que son: nodos elemento, nodos texto, nodos comentario y nodos de intrucciones de proceso. Los nodos elemento también tienen propiedades tales como su nombre, sus atributos e información sobre los "espacios de nombre" que tiene activos. Cualquier elemento de un documento XML se convierte en un nodo elemento dentro del árbol. Cada elemento tiene su nodo padre. El nodo padre de cualquier elemento es, a su vez, un elemento, excepto el elemento raíz, cuyo padre es el nodo raíz. Los nodos elemento tienen a su vez hijos, que son: nodos elemento, nodos texto, nodos comentario y nodos de intrucciones de proceso. Los nodos elemento también tienen propiedades tales como su nombre, sus atributos e información sobre los "espacios de nombre" que tiene activos. Una propiedad interesante de los nodos elemento es que pueden tener identificadores únicos (para ello deben ir acompañados de un DTD que especifique dicho atributo y asegura que toma valores únicos), esto permite referenciar a dichos elementos de una forma mucho más directa. Nodos Texto
Por texto vamos a hacer refrenecia a todos los caracteres del documento que no está marcados con alguna etiqueta. Un nodo texto no tiene hijos, es decir, los distintos caracteres que lo forman no se consideran hijos suyos. Nodo Atributo
Como ya hemos indicado, los nodo atributo no son tanto hijos del nodo elemento que los contiene como etiquetas añadidas a dicho nodo elemento. Cada nodo atributo consta de un nombre, un valor (que es siempre una cadena) y un posible "espacio de nombres". Aquellos atributos que tienen por valor el valor por defecto asignado en el DTD se tratarán como si el valor se le hubiese asignado al escribir el documento XML. Al contrario, no se crea nodo para atributos no especificados en el documento XML, y con la propiedad #IMPLIED definida en su DTD. Tampoco se crean nodos atributo para las deficiones de los espacios de nombre. Todo esto es normal si tenemos en cuenta que no es necesario tener un DTD para procesar un documento XML.
Nodos comentario y de instrucciones de proceso
Aparte de los nodos indicados, en el árbol también se generan nodos para cada nodo con comentarios y con instrucciones de proceso. Al contenido de estos nodos se puede acceder con la propiedad string-value.
3. Los Location Paths
3.1. Conceptos básicos
Expresiones
Una "instrucción" en lenguaje XPath se denomina una expresión. Y pongo entre comillas lo de "instrucción" porque XPath es un lenguaje declarativo, por lo que las intrucciones no son exactamente como estamos acostumbrados a ver. Dichas expresiones pueden incluir cierta variedad de operaciones sobre distintos tipos de operanods. En nuestro caso nos vamos a ceñir a dos tipos de operandos: llamadas a funciones y location paths (algo así como caminos de localización). Un location path es la más importante de los tipos de expresiones que se pueden especificar en notación XPath. La sintaxis de un location path es simliar a la usada a la hora de describir los directorios que forman una unidad de disco en Unix o Linux (y similar a la de los sistemas basados en MS­DOS y Windows, si exceptuamos la unidad de disco ­C:,
A:­ y que las barras usadas son / en vez de las típicas \ de estos últimos sistemas operativos). Sin embargo, sólo la sintaxis es lo similar al sistema de archivos. El significado de las expresiones es totalmente diferente. Por ejemplo, el siguiente path en Unix: /usr/home/pepeillo/docs
hace referencia a un único directorio: docs el cual cuelga de el conjunto de directorios /usr/home/pepeillo. Sin embargo, la siguiente expresión en XPath: /libro/capitulo/parrafo
hace referencia a TODOS los elementos parrafo que cuelguen directamente de CUALQUIER elemento capitulo
que cuelgue de CUALQUIER elemento libro que, finalmente, cuelguen del nodo raíz, /. Bueno, el último "TODOS" sobra dado que solo puede haber un elemento raíz: libro. Hay que tener en cuenta que una expresión en XPath no devuelve los elementos que cumplen con el patrón que representa dicha expresión, sino que devuelve una referencia a dichos elementos; es decir, una expresión XPath nos devuelve una lista de apuntadores a los elementos que encajan en el patrón. Dicha lista puede estar vacía o contener uno o más nodos. Nodo contexto
Un location path siempre tiene un punto de partida llamado nodo contexto. Para entendernos es como el directorio actual si nos referimos a un sistema de ficheros. Así, si estando en Unix, damos una orden ls obtendremos los ficheros que existen en el directorio actual, mientras que si decimos ls /usr/bin obtendremos el listado de los ficheros existentes en el directorio /usr/bin con independencia del directorio en que estemos colocados al dar la orden. En los location path ocurre lo mismo. A menos que se indique un camino explícito, se entenderá que el location path parte del nodo que en cada momento se esté procesando. El concepto de "nodo contexto" es imprescindible para comprender cómo se lleva a cabo la elección de los nodos que ajustan con el patrón indicado en el location path. para explicar esto, veamos cómo actuaría un motor de evaluación de expresiones XPath al leer la siguiente expresión aplicada al documento XML que manejamos desde el principio del turtorial: /libro/capitulo/parrafo (Aviso: lo que viene a continuación requiere de pausada lectura, descansito para ir al frigorífico a por algo de beber y pequeño masaje en los ojos... como mínimo) En primer lugar comienza por leer /, lo cual le dice que debe seleccionar el nodo raíz, independientemente del nodo contexto que en ese momento exista. En el momento en que el evaluador de XPath localiza el nodo raíz, éste pasa a ser el nodo contexto de dicha expresión. Siguiendo con nuestro ejemplo, el analizador leería ahora libro, lo cual le dice que seleccione TODOS los elementos que cuelgan del nodo contexto (que atendiendo al párrafo anterior es el nodo raíz) que se llamen libro. Bueno... en este caso solo hay uno... porque (otra vez) solo puede haber un elemento raíz. Sigamos avanzando con nuestro ejemplo. A continuación el analizador leería capitulo, lo cual le dice que seleccione TODOS los elementos que cuelgan del nodo contexto (que atendiendo al párrafo anterior es el nodo libro). En un disco sería imposible que hubiera dos directorios con el mismo nombre colgando de un mismo directorio padre. Sin embargo, en nuestro documento XML podemos ver como hay dos elementos capitulo colgando del elemento raíz libro. Por tanto, en estos momentos hay dos elementos que encajan con el patrón /libro/capitulo. El analizador continua leyendo la expresión XPath que le hemos dado y llega a parrafo. Con ello le estamos diciendo que seleccione TODOS los elementos parrafo que cuelgan del nodo contexto...¡¡pero NO hay un nodo contexto, sino DOS!! Bueno, no pasa nada, cada uno de los nodos de ese conjunto de nodos va a tener su momento de gloria, de forma que el evaluador de expresiones lo va a recorrer uno por uno haciendo que, mientras evalúa un determinado nodo, ése sea el nodo contexto de ese momento. En otras palabras, para localizar todos los elementos parrafo tal y como deseamos, se procesa el primer elemento capitulo y de él se extraen todos los parrafo que contenga. A continuación se pasa al próximo elemento capitulo del cual se vuelven a extraer todos los de tipo parrafo que tenga... y así sucesivamente. El resultado final es un nuevo conjunto de nodos (o para ser más precisos, conjunto de punteros a nodo) que encajan con el patrón buscado. Predicados
Por lo poco que llevamos visto, podemos pensar que XPath es un gran mecanismo para seleccionar muchos nodos a la vez, lo cual es muy útil. ¿Pero qué pasa si solo queremos seleccionar un nodo que cumple ciertas características? ¿o más de un nodo que cumple con un patrón pero no todos los que lo cumplen, sino solo aquellos con un atributo que les hemos añadido para saber que los puede ver todo el mundo? Bueno, pues para todo esto se utilizan los predicados. Los predicados se incluyen dentro de un location path utilizando los corchetes, como por ejemplo: /libro/capitulo[@num="1"]/parrafo Mediante el anterior location path estamos indicando que se escojan todos los elementos parrafo de todos los elementos capitulo que tengan un atributo llamado num al cual se le haya asignado el valor "1" (recordemos que en XML todos los atributos tienen valores de tipo cadena). Atendiendo a nuestro ejemplo, solo hay un capitulo que cumpla dichas condiciones, por lo que solo los elementos parrafo que él contiene serán seleccionados. Posteriormente, veremos qué tipo de cosas se pueden poner en un predicado.
3.2. ¿Cómo hago los ejemplos?
Buena pregunta. Generar un fichero XML es muy sencillo, basta un editor de texto corriente y moliente; pero, ¿cómo podemos comprobar que una expresión XPath es correcta?, es decir, que tras ejecutarse podamos comprobar que dicha expresión selecciona justo los nodos que deseamos. En realidad, hacer esto también es muy sencillo. Podemos utilizar programas a tal efecto, muy útiles cuando deseamos evaluar expresiones muy complejas, o bien usar una hoja XSL.
De hecho, más adelante estudiaremos un programa Java desarrollado para este tutorial, y lo utilizaremos para probar los ejemplos. No obstante, para realizar los ejemplos y ejercicios es suficiente con disponer de un navegador Web que sea capaz de mostrar documentos XML a los que, a su vez, se aplica un fichero XSL, esto es, un fichero que realiza transformaciones en el XML generando un nuevo contenido. Para hacerlo fácil, haz lo siguiente:
Paso 1: Guarda el siguiente fichero con el nombre libro.xml. <?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="evalua_xpath.xsl"?>
<libro>
<titulo>Dos por tres calles</titulo>
<autor>Josefa Santos</autor>
<capitulo num="1">
La primera calle
<parrafo>
Era una sombría noche del mes de agosto...
</parrafo>
<parrafo destacar="si">
Ella, inocente cual
<enlace href="http://www.enlace.es">mariposa</enlace>
que surca el cielo en busca de libaciones...
</parrafo>
</capitulo>
<capitulo num="2" public="si">
La segunda calle
<parrafo>Era una obscura noche del mes de septiembre...</parrafo>
<parrafo>
Ella, inocente cual
<enlace href="http://www.abejilla.es">abejilla</enlace>
que surca el viento en busca del néctar de las flores...
</parrafo>
</capitulo>
<apendice num="a" public="si">
La tercera calle
<parrafo>
Era una densa noche del mes de diciembre...
</parrafo>
<parrafo>
Ella, cándida cual
<enlace href="http://www.pajarillo.es">abejilla</enlace>
que surca el espacio en busca de bichejos para comer...
</parrafo>
</apendice>
</libro>
Como puedes ver, este fichero XML incluye una línea que indica qué fichero XSL (el fichero que permite evaluar expresiones XPath) va a utilizarse para seleccionar nodos y generar la información con la que realimente se desea trabajar. Dicho fichero, evalua_xpath.xsl es justo el que ponemos a continuación. Paso 2: Guarda el siguiente fichero con el nombre evalua_xpath.xsl (ojo a la extensión: xsl). <?xml version="1.0"?>
<!-==========================================================================
| File..........: evalua_xpath.xsl
| Author........: Victor Manuel Rivas Santos, [email protected]
| Description...: XSL for tutorials
==========================================================================
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="libro">
<HTML>
<HEAD>
<TITLE>Ejemplos en XPath</TITLE>
</HEAD>
<BODY>
<H1>Resultados:</H1>
<PRE>
<xsl:apply-templates select="/libro/capitulo/text()"/>
</PRE>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
Paso 3: Comprobar que tus expresiones XPath son correctas.
A continuación, lo único que tienes que hacer es sustituir lo que hemos escrito en rojo en el fichero evalua_xpath.xsl (es decir, /libro/capitulo) por la expresión que quieras evaluar y volver a guardar el fichero. Ojo: no se debe quitar /text(), pero es porque nos va a servir para poder comprobar visualmente que sólo se han seleccionado los nodos que nos interesaban; insistimos, la expresión XPath no necesita acabar con /text(), pero la ponemos para que nosotros veamos mejor el resultado en el navegador. Para ver si funciona, carga en un navegador de páginas web moderno el fichero libro.xml que has guardado y podrás ver cómo se visualizan sólo los nodos que hayas elegido.
Usando Java
Como alternativa, hemos desarrollado un programa Java que recibe el documento XML a procesar, y pide que se teclee la expresión. Mediante las clases XPath y XPathExpression podemos buscar la expresión en el documento XML.
import java.io.*; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.*; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; public class DemoXPath { public DemoXPath() { } public static void main(String[] args) { if (args.length != 1) { System.out.println("\nUSO: java DemoXPath documento.xml \n"); System.exit(0); } DemoXPath demoxpath = new DemoXPath(); try { System.out.print("\nIntroduce la expresion de busqueda: "); BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); String busqueda = stdin.readLine(); XPath xpath = XpathFactory.newInstance().newXPath(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document XMLDoc = factory.newDocumentBuilder().parse(new InputSource(new FileInputStream( args[0] ))); Element element = XMLDoc.getDocumentElement(); XPathExpression exp; exp = xpath.compile( busqueda );
System.out.println("=>\n" + (String) exp.evaluate(element,XPathConstants.STRING) + "\n"); }catch (Exception ex) { System.out.println("Error: " + ex.toString()); } } // del main
} // de la definición de clase
3.3. ¿Hachas?¿Ejes?
La verdad es que no sabía muy bien como traducir el término axes que significa algo así como cercenar o podar, aunque también hacha. Lo voy a traducir por hacha que seguro que después de un par de párrafos se convierte en algo normal. Digamos que un hacha incluída en un location path realiza una selección de nodos dentro del árbol (o mejor dicho, dentro del subárbol que cuelga del nodo o conjunto de nodos contexto) de acuerdo con algún patrón. Es decir, que cada vez que hemos usado la barra / (salvo para denominar el nodo raíz) estábamos usando un hacha. Veamos las distintas hachas que podemos usar para recorrer el arbolito. Child
Es el hacha utilizada por defecto. Se corresponde con la barra, / (aunque tiene una forma más larga que es: /child::). Ejemplo: Seleccionar todos los titulo de un libro: /libro/titulo Ejercicio: Seleccionar el autor del libro. Ejercicio: Seleccionar todos los párrafos del libro. Attribute
Se corresponde con el signo de la arroba, @ (o en su forma larga que es: attribute::). Mediante este operador podemos seleccionar aquellos nodos atributos que deseemos, indicando el nombre del atributo en cuestión. Ejemplo: Seleccionar el atributo num que posean los elementos capitulo /libro/capitulo/@num (Para ver este ejemplo tendrás que quitar /text() del fichero evalua_xpath.xsl)
Nótese, que para seleccionar los nodos elemento que muestran dichos atributos, lo que se ha de usar es un predicado (como se ha indicado ya anteriormente) indicando el nombre que ha de poseer el atributo y, si se desea, el valor que debe presentar.
Ejemplo: Seleccionar todos los elementos hijo de los capitulo que posean el atributo public (sin importar el valor asignado al mismo): /libro/capitulo[@public]/* Ejemplo: Seleccionar todos los elementos hijo de parrafo cuyo atributo destacar sea igual a "si". /libro/titulo/parrafo[@destacar="si"] Ejercicio: Seleccionar todos atributos num de los apéndices. Ejercicio: Seleccionar todos los atributos href de todos los párrafos del fichero. Ejercicio: Seleccionar todos los párrafos de los capítulos (no de los apéndices) que posean un atributo href Descendant
Se especifica poniendo una doble barra: // (en su forma larga: descendant::). Sirve para seleccionar TODOS los nodos que descendiendan del conjunto de nodos contexto. Es decir, no solo los hijos de los nodos contexto, sino también los hijos de los hijos, y los hijos de estos, etc. Ejemplo: Seleccionar todos los parrafo de un libro: /libro//parrafo Ejemplo: Seleccionar todos los descendientes de parrafo que tienen un atributo href. //parrafo//*[@href] Ejemplo: Mostrar el valor del atributo href del caso anterior:. //parrafo//*[@href]/@href Self
Se especifica mediante el punto (.). Es muy útil pues sirve para seleccionar el nodo contexto. Por ejemplo, supongamos que deseamos seleccionar todos los parrafo descendientes del nodo contexto. No podemos escribir //parrafo, dado que seleccionaría todos los descendientes del nodo raíz. Por ello, la forma correcta es: .//parrafo No es fácil proponer un ejemplo ni ejercicio teniendo en cuenta que aún no conocemos el lenguaje XSLT. En dicho momento se verá con más claridad la gran utilidad de este hacha. Parent
Al igual que en los sistemas de ficheros, se utilizan los dos puntos para identificarlo: .. El comportamiento de este hacha es un poco extraño al principio dado que realiza un paso hacia atrás en el árbol de nodos. Ejemplo: Seleccionar todos los nodos que tienen algún hijo de tipo parrafo: //parrafo/.. Ejemplo: Seleccionar todos los nodos capitulo que tienen algún hijo de tipo parrafo: //parrafo/../../capitulo
O bien: //capitulo/parrafo/.. Ejercicio: Seleccionar todos los nodos que tienen un hijo de tipo enlace. Ancestor
De todas las hachas que podemos usar, esta es la única que no tiene ninguna forma de abreviación, sino que hay que ponerla como ancestor:: Ancestor es a parent lo que descendant es a child. Es decir, devuelve todos los elementos de los cuales el nodo contexto es descendiente. Ejemplo: Seleccionar todos los elementos que tienen entre sus descendientes algún parrafo //parrafo/ancestor::* 3.4. Nodos test
Los nodos test son algo así como funciones que nos van a ayudar a restringir un poquito lo que nos devuelve una expresión XPath. Ya hemos visto algunos de estos nodos test en los ejemplos anteriores. Pero ahora vamos a verlos con más detenimiento. En primer lugar hemos de distinguir entre las hachas de contenido (content axis) de las que no lo son. Las hachas de contenio son básicamente todas las vistas excepto attibute y namespace (es como attribute pero para obtener el "espacio de nombres" asociado al elemento). Nodos test aplicables a TODAS las hachas
El nodo test * devuelve todos los nodos de tipo principal (es decir, elemento, atributo o espacio de nombres), pero no nodos de texto, comentarios y de instrucciones de proceso. Ejemplo: Seleccionar todos los nodos principales descendientes de los parrafo: //parrafo/*
Ejercicio: Seleccionar todos los nodos principales descendientes de los apéndices: node()
El nodo test node() devuelve todos los nodos de todos los tipos. Seleccionar todos los nodos descendientes de los parrafo: //parrafo/node()
Nodos Test aplicables SOLO a la hachas de contenido
text()
Selecciona cualquier nodo de tipo texto y es precisamente lo que hemos estado poniendo en el fichero evalua_xpath.xl para visualizar el contenido de los nodos seleccionados por cada una de las expresiones de los ejemplos y ejercicios. Ejemplo: Seleccionar el texto de todos los nodos parrafo: //parrafo/text() Ejemplo: Seleccionar TODO el texto que cuelga de todos los nodos parrafo (ojo: ¿ves la diferencia con el anterior?) //parrafo//text() comment()
Permite seleccionar cualquier nodo de tipo comentario. processing-instruction()
Cualquier nodo de tipo de instrucción de proceso, independientemente de su destino. processing-instruction( destino )
Cualquier nodo de tipo de instrucción de proceso relativo al destino especificado. processing-instruction( cursor )
Cualquier nodo de tipo de instrucción de proceso con el destino cursor.
3.5. Predicados
Ya hemos tenido que introducir los predicados en párrafos anteriores. Básicamente, un predicado permite restringir el conjunto de nodos seleccionados por un hacha a aquellos que cumplen cierta condición. Dicha condición es una expresión XPath y se expecifica entre corchetes. Ejemplo: Seleccionar todos los capitulo que tengan un parrafo que tenga algún elemento con atributo href: //capitulo[parrafo/*[@href]] Serán muchas las ocasiones en que deseemos que los nodos a seleccionar no cumplan una sino varias condiciones. En estos casos, los predicados se pueden suceder uno a otro haciendo el efecto de la operación AND. Como en el siguiente ejemplo. Ejemplo: Seleccionar todos los capitulo que tengan un parrafo que tenga algún elemento con atributo href
y que ellos mismos (los capitulo) tengan el atributo public a valor si: //capitulo [parrafo/*[@href]] [@public='si']
Aunque también se puede hacer uso del operador and encerrando entre paréntesis los distintos predicados logicos. Ejemplo similar al anterior //capitulo[ (parrafo/*[@href]) and (@public='si')]
También se puede hacer uso de la operación or. Esiste otro tipo de operacion or que utiliza la barra vertical: | separando no dos predicados, sino dos expresiones XPath. Ejemplo: Seleccionar todos los capitulo que tengan un parrafo que tenga algún elemento con atributo href
o todos los apendice: //capitulo[parrafo/*[@href]]|//apendice
Por último, también podemos especificar con not la negación de alguna de las negaciones del predicado. Seleccionar todos los capitulo que no tengan el atributo public //capitulo[not(@public)]
Predicados con funciones de cardinalidad
Existen, por último, ciertas funciones que nos van a servir para restringir el conjunto de nodos devueltos en una expresión XPath basándose en la posición del elemento devuelto. Tales funciones son: position(), last() e id(). position()
Seleccionar el segundo capitulo: //capitulo[position()=2] Esta función se puede simular poniendo simplemente el número entre corchetes. Mismo ejemplo anterior: seleccionar el segundo capitulo: //capitulo[2] last()
Seleccionar el último capitulo: //capitulo[last()] Seleccionar todos los capitulo menos el último: //capitulo[not(position()=last())] Estas funciones se pueden usar con expresiones matemáticas, como en el siguiente ejemplo. Seleccionar el penúltimo capitulo: //capitulo[last()-1] id()
Seleccionar los parrafo hijos del elemento con id="capitulo_1": id( "capitulo_1" )/parrafo Hay que tener en cuenta un detalle: sólo se podrá usar en aquellos ficheros XML que sean validados por un DTD en el que se especifique que el atributo id es único.
4. Apéndice
4.1. Ejercicios
Hemos creado una dirección web en la que puedes hacer ejercicios de XPath: ejercicios_xpath.html
El fichero XML sobre el que tratan los ejercicios es: ejercicios_xpath_xml.html
Deberías tenerlo a la vista para hacer los ejercicios.
Descargar