Skip to content

11 XPath

Introducción

XPath es un lenguaje que permite seleccionar nodos de un documento XML y calcular valores a partir de su contenido. Existen varias versiones de XPath aprobadas por el W3C.

Además XPath, consideran los documentos XML como un árbol de nodos.

Sintaxis de las expresiones XPath

Una expresión XPath es una cadena de texto que representa un recorrido en el árbol del documento. Las expresiones más simples se parecen a las rutas de los archivos en el explorador de Windows o en la shell de GNU/Linux.

Evaluar una expresión XPath es buscar si hay nodos en el documento que se ajustan al recorrido definido en la expresión. El resultado de la evaluación son todos los nodos que se ajustan a la expresión. Para poder evaluar una expresión XPath, el documento debe estar bien formado.

Las expresiones XPath se pueden escribir de dos formas distintas:

  • sintaxis abreviada: más compacta y fácil de leer.
  • sintaxis completa: más larga pero con más opciones disponibles.

Las expresiones XPath se pueden dividir en pasos de búsqueda. Cada paso de búsqueda se puede a su vez dividir en tres partes:

  • eje: selecciona nodos elemento o atributo basándose en sus nombres.
  • predicado: restringe la selección del eje a que los nodos cumplan ciertas condiciones.
  • selección de nodos: de los nodos seleccionados por el eje y predicado, selecciona los elementos, el texto que contienen o ambos.

Eje

Vamos a partir del siguiente ejemplo:

<?xml version="1.0" encoding="UTF-8"?>
<biblioteca>
  <libro>
    <titulo>La vida está en otra parte</titulo>
    <autor>Milan Kundera</autor>
    <fechaPublicacion año="1973"/>
  </libro>
  <libro>
    <titulo>Pantaleón y las visitadoras</titulo>
    <autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
    <fechaPublicacion año="1973"/>
  </libro>
  <libro>
    <titulo>Conversación en la catedral</titulo>
    <autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
    <fechaPublicacion año="1969"/>
  </libro>
</biblioteca>

El eje nos permite seleccionar un subconjunto de nodos del documento y corresponde a recorridos en el árbol del documento. Los nodos elemento se indican mediante el nombre del elemento. Los nodos atributo se indican mediante @ y el nombre del atributo.

  • /: si está al principio de la expresión, indica el nodo raíz, si no, indica su hijo, puede ir seguida del nombre de un elemento, o de otro /. Veamos un ejemplo:
/biblioteca/libro/autor
<autor>Milan Kundera</autor>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  • @: indica un atributo:
/biblioteca/libro/autor/@fechaNacimiento
 fechaNacimiento="28/03/1936"
 fechaNacimiento="28/03/1936"
  • //: si se usa una doble barra, en ese caso, hace referencia a un nodo descendiente, ya sea hijo directamente del elemento, o hijo de sus hijos.
/biblioteca//autor
<autor>Milan Kundera</autor>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  • /...: indica el elemento padre. Si queremos devolver aquellas etiquetas que tienen fecha de nacimiento:
/biblioteca/libro/autor/@fechaNacimiento/..
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  • |: permite seguir varios recorridos. Por ejemplo, se quiere obtener los elementos que sean titulo o autor:
//autor|//titulo
<titulo>La vida está en otra parte</titulo>
<autor>Milan Kundera</autor>
<titulo>Pantaleón y las visitadoras</titulo>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
<titulo>Conversación en la catedral</titulo>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>

Predicado

El predicado se escribe entre corchetes, a continuación del eje. Si el eje ha seleccionado unos nodos, el predicado permite restringir esa selección a los que cumplan determinadas condiciones.

  • [@atributo]: selecciona los elementos que tienen el atributo.
//autor[@fechaNacimiento]
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  • [número]: si hay varios resultados selecciona uno de ellos por número de orden
//libro[1]
<libro>
  <titulo>La vida está en otra parte</titulo>
  <autor>Milan Kundera</autor>
  <fechaPublicacion año="1973"/>
</libro>
  • [last()]: devuelve el último elemento.
//libro[last()]
<libro>
  <titulo>Conversación en la catedral</titulo>
  <autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  <fechaPublicacion año="1969"/>
</libro>
  • [condición]: selecciona los nodos que cumple la condición. Los predicados permiten definir condiciones sobre los valores de los atributos. En las condiciones se pueden utilizar los operadores lógicos,aritméticos y de comparación. Las comparaciones se pueden hacer entre valores de nodos y atributos o con cadenas de texto o numéricas. Las cadenas de texto deben escribirse entre comillas simples o dobles. En el caso de las cadenas numéricas, las comillas son optativas. Por ejemplo: queremos las fecha de publicación que sean superiores al año 1970:
//fechaPublicacion[@año>1970]
<fechaPublicacion año="1973"/>
<fechaPublicacion año="1973"/>

Se puede hacer referencia al propio elemento, con el punto .:

//autor[.="Mario Vargas Llosa"]
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>

Además un predicado puede contener condiciones compuestas, haciendo uso de and u or.

//libro[autor="Mario Vargas Llosa" and fechaPublicacion/@año="1973"]
<libro>
  <titulo>La vida está en otra parte</titulo>
  <autor>Milan Kundera</autor>
  <fechaPublicacion año="1973"/>
</libro>
<libro>
  <titulo>Pantaleón y las visitadoras</titulo>
  <autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  <fechaPublicacion año="1973"/>
</libro>
<libro>
  <titulo>Conversación en la catedral</titulo>
  <autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  <fechaPublicacion año="1969"/>
</libro>

También se pueden realizar condiciones sobre el resultado de otras condiciones:

//libro[autor="Mario Vargas Llosa"][fechaPublicacion/@año="1973"]
<libro>
  <titulo>Pantaleón y las visitadoras</titulo>
  <autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  <fechaPublicacion año="1973"/>
</libro>

Selección de nodos

La selección de nodos se escribe a continuación del eje y el predicado. Si el eje y el predicado han seleccionado unos nodos, la selección de nodos indica con qué parte de esos nodos nos quedamos.

  • /node(): selecciona todos los hijos (elementos o texto) del nodo. //node(): selecciona todos los descendientes (elementos o texto) del nodo.
//libro/node()
<titulo>La vida está en otra parte</titulo>
<autor>Milan Kundera</autor>
<fechaPublicacion año="1973"/>
<titulo>Pantaleón y las visitadoras</titulo>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
<fechaPublicacion año="1973"/>
<titulo>Conversación en la catedral</titulo>
<autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
<fechaPublicacion año="1969"/>
  • /text(): selecciona únicamente el texto contenido en el nodo. //text(): selecciona únicamente el texto contenido en el nodo y todos sus descendientes.
//libro//text()
La vida está en otra parte
Milan Kundera
Pantaleón y las visitadoras
Mario Vargas Llosa
Conversación en la catedral
Mario Vargas Llosa
  • /*: selecciona todos los hijos (sólo elementos) del nodo. //*: selecciona todos los descendientes (sólo elementos) del nodo.
//autor/*
No devuelve nada porque el autor no tiene nodos hijos, solo texto.
  • /@*: selecciona todos los atributos del nodo. //@*: selecciona todos los atributos de los descendientes del nodo.
//@*
año="1973"
fechaNacimiento="28/03/1936"
año="1973"
fechaNacimiento="28/03/1936"
año="1969"

Pasos de búsquedas consecutivos

Una expresión XPath puede contener varios pasos de búsqueda consecutivos. Cada uno incluirá su eje (y en su caso, su predicado) y el último paso de búsqueda incluirá en su caso una selección de nodos. Cada paso de búsqueda trabaja a partir de los nodos seleccionados por el paso de búsqueda anterior.

En el ejemplo siguiente se obtienen los títulos de los libros publicados después de 1970, mediante dos pasos de búsqueda:

  • en el primer paso (//fechaPublicacion[@año>1970]) se seleccionan los elementos <fechaPublicacion> cuyo atributo año es superior a 1970.
  • en el segundo paso (/../titulo), se seleccionan primero los elementos padrev(/..) de los <fechaPublicacion> seleccionados en el primer paso de búsqueda (es decir, elementos <libro>) y a continuación sus subelementos <titulo>.
//fechaPublicacion[@año>1970]/../titulo
<titulo>La vida está en otra parte</titulo>
<titulo>Pantaleón y las visitadoras</titulo>

Un determinado resultado se puede obtener mediante un sólo paso de búsqueda o mediante varios pasos.

Por ejemplo, vamos a obtener los libros escritos por Mario Vargas Llosa, de dos formas distintas.

La primera forma, mediante un sólo paso de búsqueda. Se seleccionan los elementos <libro> cuyo subelemento <autor> tiene como contenido la cadena "Mario Vargas Llosa".

//libro[autor="Mario Vargas Llosa"]
<libro>
  <titulo>Pantaleón y las visitadoras</titulo>
  <autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  <fechaPublicacion año="1973"/>
</libro>
<libro>
  <titulo>Conversación en la catedral</titulo>
  <autor fechaNacimiento="28/03/1936">Mario Vargas Llosa</autor>
  <fechaPublicacion año="1969"/>
</libro>

La segunda forma mediante dos pasos de búsqueda. En el primer paso se seleccionan los elementos <autor> cuyo contenido es la cadena "Mario Vargas Llosa". En el segundo paso de búsqueda se seleccionan los elementos padre (es decir, los elementos <libro>). Se obtiene el mismo resultado.

Expresiones anidadas

Las expresiones XPath pueden anidarse, lo que permite definir expresiones más complicadas. Un ejemplo de expresión anidada sería obtener los títulos de los libros publicados el mismo año que la novela "La vida está en otra parte". Esta información no está directamente almacenada en el documento, pero se puede obtener la respuesta en dos pasos:

  • primero, obtener primero el año en que se publicó la novela "La vida está en otra parte":
//libro[titulo="La vida está en otra parte"]/fechaPublicacion/@año
año=1973
  • segundo, obtener después los títulos de los libros publicados en 1973:
//libro[fechaPublicacion/@año=1973]/titulo
<titulo>La vida está en otra parte</titulo>
<titulo>Pantaleón y las visitadoras</titulo>

Estas dos expresiones se pueden unir en una única expresión, sustituyendo en la segunda expresión el valor 1973 por la primera expresión:

//libro[fechaPublicacion/@año=//libro[titulo="La vida está en otra parte"]/fechaPublicacion/@año]/titulo
<titulo>La vida está en otra parte</titulo>
<titulo>Pantaleón y las visitadoras</titulo>

XPath en Java

Para poder evaluar una expresión XPath, podemos usar la API XPath de la librería Java. A través de la clase factoría XPathFactory se puede crear una instancia de la clase XPath.

Posteriormente, a través del método compile(String expression) se puede compilar la expresión XPath y con el método evaluate(document, mode) se ejecuta dicha expresión. Veamos un ejemplo:

DocumentBuilderFactory builderFactory = newSecureDocumentBuilderFactory();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(fileIS);
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/Tutorials/Tutorial";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);

El modo del método evaluate() puede ser:

  • NODESET. Mapea el resultado obtenido en un NodeList.
  • NODE. Mapea el resultado obtenido en un Node.
  • STRING. Mapea el resultado obtenido en una cadena String.
  • NUMBER. Mapea el resultado obtenido en un número Double.
  • BOOLEAN. Mapea el resultado obtenido en un boolean Boolean.

Todas estas constantes se encuentra de forma estática en la clase XPathConstants.