Introducción a XPath
XPath es un lenguaje declarativo, que sirve para “navegar” dentro de un documento XML, seleccionando elementos, atributos, etc. XPath es una W3C Recommendation y es utilizado por otros estándares de W3C, como XSLT. En este artículo utilizar la API que nos ofrece Java para trabajar con XPath.
Que es y para que sirve XPath
XPath es, como ya dijimos, un lenguaje recomendado por W3C que sirve para navegar dentro de un documento XML. Conocerlo es indispensable para poder entender y utilizar otros estándares, como XSLT. Además, es soportado por algunas herramientas de parsing XML. Y muchas otras herramientas XML se basan en el (como XQL).
Para los que todavía no sepan de que va XML, pueden leer primero esta Introduccióna a XML.
Como ya sabemos, la estructura de un documento XML se compone de nodos, estos nodos pueden ser elementos o atributos. Los elementos pueden ser hijos/padres de otros atributos, etc.
Bueno, XPath se basa básicamente en expresiones (expresiones XPath) similares a las expresiones regulares, pero diseñadas para la estructura jerárquica de XML. Con ellas podemos buscar y seleccionar nodos de un documento XML.
Entendiendo las expresiones XPath
La estructura jerárquica de XML se parece bastante a la de un árbol de directorios, por ejemplo, si queremos seleccionar de un documento HTML, el título, utilizaríamos una expresión como esta:
[sourcecode language="xml"]
/html/head/title
[/sourcecode]
Si quisiéramos seleccionar TODOS los párrafos, utilizaríamos una expresión así:
[sourcecode language="xml"]
//p
[/sourcecode]
Con esta última expresión seleccionamos todos los elementos p, sin importar dentro de que otros elementos se encuentren. En cambio cuando utilizamos la expresión /html/head/title, estamos seleccionando un sólo elemento title, hijo de un elemento head, que a su vez es hijo de un elemento html. Es decir, que con “/” seleccionamos el nodo hijo del nodo en que estamos, y con “//” seleccionamos cualquier nodo descendiente del nodo en que estamos, o sea que podría ser el hijo del hijo del hijo…
Podemos combinar “/” y “//” en una misma expresión:
[sourcecode language="xml"]
/html/body//p
[/sourcecode]
Con esa expresión, seleccionamos todos los elementos p, que estén dentro del elemento body, dentro del elemento html del documento.
Y como para terminar de sobre explicar más el concepto, una pregunta: ¿cuál es la diferencia entre la expresión anterior y la siguiente?
[sourcecode language="xml"]
/html/body/p
[/sourcecode]
Bueno, que con esta expresión, seleccionaríamos sólo los elementos p que estén directamente dentro del elemento body. En cambio con la primera expresión, seleccionaríamos todos los elementos p que estén dentro de body, sin importar si están dentro de /html/body/div/p o dentro de /html/body/p, ¿se entiende?
Para seleccionar atributos, utilizamos el prefijo @.
Esta expresión seleccionaría todos los atributos class del documento:
[sourcecode language="xml"]
//@class
[/sourcecode]
Y esta expresión seleccionaría el atributo class del elemento especificado:
[sourcecode language="xml"]
/html/body/p/@class
[/sourcecode]
Fíjense que cuando usan por ejemplo la expresión:
[sourcecode language="xml"]
/html/body/p
[/sourcecode]
Se seleccionan todos los elementos p. Para decidir cual de todos queremos, utilizamos corchetes así:
[sourcecode language="xml"]
/html/body/p[3]
[/sourcecode]
Eso seleccionaría el tercer elemento p hijo de body, dentro del elemento html.
Los corchetes también pueden usarse para especificar más la búsqueda, por ejemplo:
[sourcecode language="xml"]
//p[@color="RED"]
[/sourcecode]
Con esa expresión seleccionamos todos elementos p del documento, que tengan un atributo color con valor “RED”.
XPath, nos ofrece algunas funciones útiles. Por ejemplo para contar la cantidad de nodos seleccionados:
[sourcecode language="xml"]
count(/html/body//p/@class)
[/sourcecode]
Eso nos devolvería la cantidad de atributos class de elementos p dentro del elemento body, hijo del elemento html.
Ejemplo en Java
Primero que nada creamos un documento XML para usar de ejemplo:
[sourcecode language="xml"]
[/sourcecode]
J2SE 5.0 nos provee de una API para trabajar con expresiones XPath. Esta se encuentra en el paquete javax.xml.xpath. Así que lo importamos:
[sourcecode language="java"]
import javax.xml.xpath.*;
[/sourcecode]
Abrimos el documento XML desde Java:
[sourcecode language="java"]
DocumentBuilderFactory factoryDocument = DocumentBuilderFactory.newInstance();
Document doc = factoryDocument.newDocumentBuilder().parse(“/home/homer/releases.xml”);
[/sourcecode]
Para crear una expresión XPath, hacemos lo siguiente:
- Creamos un objeto XPath, desde XPathFactory:
[sourcecode language="java"]
XPathFactory factoryXPath = XPathFactory.newInstance();
XPath xpath = factoryXPath.newXPath();
[/sourcecode] - Compilamos una expresión mediante el método compile() del objeto XPath, pasándole un String con la expresión como parámetro. Y en caso de compilarse bien, devuelve un objeto XPathExpression:
[sourcecode language="java"]
// compilamos expresión
XPathExpression expr = xpath.compile(“//release[@version>2][1]“);
[/sourcecode]
Si ocurre algún error durante la compilación de la expresión, va a lanzarse una TransformerException. - Ahora para evaluar la expresión en un documento XML, llamamos al método evaluate() de XPathExpression, pasándole como primer parámetro el objeto Document que representa el documento XML donde vamos a evaluar la expresión, y como segundo parámetro le indicamos como queremos que nos devuelva e resultado, en este caso lo queremos como un String:
[sourcecode language="java"]
// evaluamos expresión
String result = expr.evaluate(doc, XPathConstants.STRING);
// mostramos el resultado
System.out.println(result);
[/sourcecode]
NOTA: en el código anterior no manejé las excepciones (try/catch) por una cuestión de legibilidad.
Dejo un programa muy sencillo, pero que nos sirve para hacer algunas pruebas con XPath:
[sourcecode language="java"]
import javax.xml.xpath.*;
import javax.xml.parsers.*;
import javax.xml.validation.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import java.io.*;
public class XPathTester {
public static void main(String[] args) throws IOException {
DocumentBuilderFactory factoryDocument = DocumentBuilderFactory.newInstance();
Document doc = null;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
do {
System.out.println(“Ingrese path del fichero:\n”);
try {
doc = factoryDocument.newDocumentBuilder().parse(br.readLine());
} catch (Exception e) {
System.out.println(“Err\n”);
doc = null;
}
} while (doc == null);
XPathFactory factoryXPath = XPathFactory.newInstance();
XPath xpath = factoryXPath.newXPath();
XPathExpression expr = null;
do {
System.out.println(“Ingrese expresión:\n”);
try {
expr = xpath.compile(br.readLine());
System.out.println(expr.evaluate(doc, XPathConstants.STRING) + “\n”);
} catch (Exception e) {
System.out.println(“Err\n”);
}
} while (true);
}
}
[/sourcecode]
Es bastante sencillo el programa, primero pide ingresar el path del documento XML donde vamos a evaluar las expresiones, después nos pide ingresar la expresión, y en caso de que sea correcta imprime el resultado.
Pueden probar las siguientes expresiones con el documento anterior:
- [sourcecode language="xml"]
//@version
[/sourcecode] - [sourcecode language="xml"]
count(//release)
[/sourcecode] - [sourcecode language="xml"]
/releases/release[name='Etch']
[/sourcecode] - [sourcecode language="xml"]
/releases/release[@version>2][3]
[/sourcecode]
Bueno, esa fue mi intento de introducción a XPath, pueden consultar por mejor info. en W3 Schools.
15 comentarios15 comentarios
Dejá una respuesta








Te felicito por la calidad del artículo.
Gracias por el artículo, anduve buscando mucho tiempo un ejemplo con XPath y por fin un articulo claro y conciso q me ayudo muchisimo.
Muy buen blog, te felicito
si sigues asi, te convertiras en una profesional excelente
Me encanto la info del blog. Realmente muy precisa. Una excelente info para empezar a entender XPath
Te felicito
Que buen articulo y en general buen blog
Ya eres profesional! Desde hoy soy seguidor de tu blog[: Gracias!
Puedes ayudarme con esto?, me aperece ese error
XPathFactory#newInstance() failed to create an XPathFactory for the default object model: http://java.sun.com/jaxp/xpath/dom with the XPathFactoryConfigurationException: javax.xml.xpath.XPathFactoryConfigurationException: No XPathFctory implementation found for the object model: http://java.sun.com/jaxp/xpath/dom
at javax.xml.xpath.XPathFactory.newInstance(Unknown Source)
que dolor de ojos.
Y más idiota que tenga que batallar la gente para salir.
[...] [...]
Exquisitamente excelente. Felicitaciones.
Muy bien hecho, sigue así y serás muy buena… la verdad es que sorprende la relación calidad del artículo con tu edad… Sé perseverante y el mundo te lo agradecerá.
¡Enhorabuena!
Buen articulo compadre. Entendi de una pata!
BUEN COMIENZO
Bueno… no!, Buenissimo!!!
Sigue así…