Just Sherekan – Blog de Programación



Compartiendo conocimiento… intentando no reinventar la rueda…

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"]



Potato
2000


Sarge
2005


Etch
2007


[/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 comentarios

15 comentarios

  1. Pepe ARGENTINA Septiembre 29th, 2008 9:06 pm

    Te felicito por la calidad del artículo.

  2. Victor COLOMBIA Noviembre 7th, 2008 8:37 am

    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.

  3. Alonso PERU Noviembre 8th, 2008 4:39 pm

    Muy buen blog, te felicito
    si sigues asi, te convertiras en una profesional excelente

  4. Tamara ARGENTINA Noviembre 25th, 2008 10:15 pm

    Me encanto la info del blog. Realmente muy precisa. Una excelente info para empezar a entender XPath
    Te felicito

  5. Oscar MEXICO Diciembre 9th, 2008 3:45 pm

    Que buen articulo y en general buen blog

  6. Miguel Sauza MEXICO Enero 29th, 2009 9:24 pm

    Ya eres profesional! Desde hoy soy seguidor de tu blog[: Gracias!

  7. julio NICARAGUA Mayo 5th, 2009 7:00 pm

    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)

  8. bah MEXICO Junio 23rd, 2009 8:15 pm

    que dolor de ojos.

  9. bah MEXICO Junio 23rd, 2009 8:16 pm

    Y más idiota que tenga que batallar la gente para salir.

  10. [...] [...]

  11. Javier BOLIVIA Agosto 22nd, 2009 1:30 am

    Exquisitamente excelente. Felicitaciones.

  12. Jaime SPAIN Agosto 31st, 2009 8:30 am

    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!

  13. Francisco CHILE Septiembre 21st, 2009 5:20 pm

    Buen articulo compadre. Entendi de una pata!

  14. online-maris UKRAINE Octubre 15th, 2009 3:17 am

    BUEN COMIENZO

  15. David SPAIN Noviembre 29th, 2009 3:23 am

    Bueno… no!, Buenissimo!!!
    Sigue así…

Dejá una respuesta

Mexico