Introducción a XPath

Cómo funciona el lenguaje de consultas XPath. Explorando la búsqueda de información dentro de XML
El lenguaje de marcado XML ha estado presente en las computadoras de los usuarios desde el primer estándar. Tablas en Excel, exportaciones de tiendas en línea, feeds RSS de noticias, todo esto se basa en XML. Aunque la representación visual puede variar en dispositivos y programas, siempre se utiliza un formato común en su base.

Dentro de un archivo XML puede haber una gran cantidad de información, por lo que surge la pregunta de cómo moverse y extraer datos dentro del documento. ¿Cómo hacerlo de manera eficiente? ¿Qué herramientas se deben utilizar para encontrar un producto específico entre decenas de miles en una tienda en línea? Para la navegación y búsqueda dentro de XML se utiliza el lenguaje de consultas XPath.

En este artículo, vamos a explorar:
  • para quién puede ser útil el XPath
  • las construcciones básicas del lenguaje para buscar información en XML
  • las diferencias entre XPath y los selectores CSS al buscar en HTML
Sintaxis de XPath
Para empezar, crearemos un ejemplo básico de XML con el que trabajaremos durante todo el tutorial. Por ejemplo, una lista de cursos de maquetación en Códica en XML se verá así:

<?xml version="1.0" encoding="UTF-8"?>
<courses>
  <title>Cursos de HTML y CSS (maquetación)</title>
  <description>En los cursos de maquetación aprenderás los fundamentos de HTML y CSS, cómo crear páginas web adaptables, trabajar con preprocesadores. Dominarás tecnologías y herramientas modernas, incluyendo Flex, Sass, Bootstrap.</description>
  <course>
    <name>Fundamentos de maquetación moderna</name>
    <tags>HTML5, CSS, DevTools, diseño</tags>
    <duration value="9">9 horas</duration>
    <url lang="es">https://app.codica.la/courses/layout-designer-basics</url>
  </course>
  <course>
    <name>Fundamentos de maquetación de contenido</name>
    <tags>CSS3, HTML5, Selectores, Accesibilidad, CSS Columns, CSS Units, Diseño</tags>
    <duration value="18">18 horas</duration>
    <url lang="es">https://app.codica.la/courses/css-content-course</url>
  </course>
</courses>
Este es un ejemplo educativo, pero para practicar los conceptos de XPath se puede utilizar cualquier otro XML. Los principios de XPath se mantienen independientemente de la estructura del archivo, ya que XML permite utilizar elementos con etiquetas arbitrarias.

Para probar los resultados, se pueden utilizar servicios en línea como:
Rutas absolutas

La consulta más simple consiste en acceder al elemento raíz. Para hacer esto, simplemente se debe ejecutar la consulta /courses. Esto devolverá el XML en un formato muy similar al ejemplo anterior. Presta atención a la línea <?xml version="1.0" encoding="UTF-8"?>. Es diferente porque el elemento no está dentro de <courses>:

<courses>
  <title>Cursos de HTML y CSS (diseño)</title>
  <description>En los cursos de maquetación aprenderás los fundamentos de HTML y CSS, cómo crear páginas web adaptables, trabajar con preprocesadores. Dominarás tecnologías y herramientas modernas, incluyendo Flex, Sass, Bootstrap.</description>
  <course>
    <name>Fundamentos de maquetación moderna</name>
    <tags>HTML5, CSS, DevTools, diseño</tags>
    <duration value="9">9 horas</duration>
    <url lang="es">https://app.codica.la/courses/layout-designer-basics</url>
  <course>
    <name>Fundamentos de maquetación de contenido</name>
    <tags>CSS3, HTML5, Selectores, Accesibilidad, CSS Columns, CSS Units, Diseño</tags>
    <duration value="18">18 horas</duration>
    <url lang="es">https://app.codica.la/courses/css-content-course</url>
  </course>
</courses>
Como resultado, XPath devuelve los nodos del documento XML.

Continuemos la cadena y accedamos a la descripción del elemento <description>. Para hacer esto, agreguemos la ruta description a la consulta: /courses/description. El resultado será:

<description>En los cursos de maquetación aprenderás los fundamentos de HTML y CSS, cómo crear páginas web adaptables, trabajar con preprocesadores. Dominarás tecnologías y herramientas modernas, incluyendo Flex, Sass, Bootstrap.</description>
La ruta que se construye desde el elemento raíz se llama ruta absoluta. Utilicemos el esquema de la consulta anterior y accedamos a cualquier elemento dentro del XML.

Intentemos acceder al nombre de un curso. En este caso, se devolverá el campo <name> de todos los cursos. La consulta /courses/course/name devolverá:

<name>Fundamentos de maquetación moderna</name>
<name>Fundamentos de maquetación de contenido</name>

Aquí hay una lista de algunas consultas básicas y sus resultados:
Rutas relativas

Las consultas anteriores se construyeron utilizando rutas absolutas, es decir, se especificó la ruta completa hasta la información. Sin embargo, hay situaciones en las que la ruta completa no es adecuada: por ejemplo, cuando se desea acceder a un campo único o no se conoce la ruta completa. En este caso, se puede utilizar una ruta relativa, que buscará en todo el XML y devolverá los nodos que coincidan con la consulta.

Para escribir una ruta relativa, se debe utilizar la construcción //. Después de esto, se puede escribir cualquier campo y se obtendrá el resultado. Por ejemplo, //name devolverá los campos <name> de todo el XML:

<name>Fundamentos de maquetación moderna</name>
<name>Fundamentos de maquetación de contenido</name>

El problema de este enfoque es la unicidad de los campos. En los documentos, los mismos nombres de campos pueden representar diferentes datos dependiendo de su ubicación. Por lo tanto, se deben utilizar rutas relativas solo cuando se está seguro de los datos que se devolverán. Por ejemplo, en nuestro ejemplo, el nombre del curso puede estar contenido en <title>:

<courses>
  <title>Cursos de HTML y CSS (maquetación )</title>
  <!-- ... -->
    
  <course>
    <title>Fundamentos de maquetación moderna</title>
    <!-- ... -->
  </course>
    
  <course>
    <title>Fundamentos de maquetación de contenido</title>
    <!-- ... -->
  </course>
        
</courses>

La consulta //title devolverá no solo los nombres de los cursos, sino también el nodo que se encuentra dentro de <courses>:

<title>Cursos de HTML y CSS (maquetación )</title>
<title>Fundamentos de maquetación moderna</title>
<title>Fundamentos de maquetación de contenido</title>


Para ahorrar tiempo, los desarrolladores omiten el elemento raíz y utilizan rutas relativas. Por ejemplo, en lugar de /courses/course/name, escriben //course/name. Para practicar, intenta convertir los ejemplos anteriores a rutas relativas utilizando este mecanismo.
Aquí hay algunos ejemplos de consultas con los mismos resultados que en la tabla anterior:
Predicados

En los ejemplos anteriores, las consultas seleccionaban todos los nombres de los cursos encontrados. En algunas situaciones, esto puede ser redundante. ¿Qué hacer si solo se desea obtener datos del primer curso en <courses>? Aquí es donde entran en juego los predicados, que son construcciones que permiten filtrar elementos según condiciones específicas.

Seleccionemos las palabras clave del primer curso de diseño. Para hacer esto, simplemente se debe utilizar la consulta //course[1]/tags:

<tags>HTML5, CSS, DevTools, diseño</tags>
Observa [1]. Este es un predicado con la condición "Tomar el elemento con el índice 1". Intenta hacer una consulta para el segundo o tercer elemento. ¡Solo se necesita cambiar un número!
En XPath, los índices de los elementos comienzan en 1, no en 0 como en los estándares de programación habituales. Si ya tienes experiencia en programación, esto puede ser un poco confuso.
Los predicados ayudan a hacer selecciones precisas. Por ejemplo, obtener enlaces a páginas en español de los cursos. Para hacer esto, se deben seleccionar los elementos <url> que tengan el atributo lang igual a ru. Esto se logra especificando el atributo y su valor. Para diferenciar un atributo de un elemento en XPath, se debe utilizar el símbolo @.

La consulta será //course/url[@lang="ru"]

<url lang="es">https://app.codica.la/courses/layout-designer-basics</url>
<url lang="es">https://app.codica.la/courses/css-content-course</url>

A veces es útil seleccionar elementos que tengan algún atributo. Para hacer esto, se puede utilizar la construcción //*[@*]:

<duration value="9">9 horas</duration>
<url lang="ru">https://app.codica.la/courses/layout-designer-basics</url>
<duration value="18">18 horas</duration>
<url lang="ru">https://app.codica.la/courses/css-content-course</url>

En el ejemplo anterior se puede ver que el signo * significa "todos/cualquier".

Cuando se seleccionan elementos por atributos, se puede realizar un filtrado adicional en función de esos valores. Por ejemplo, seleccionar elementos <duration> con un valor de atributo value mayor a 9. Dentro de los predicados se utilizan operadores de comparación, que son familiares en los lenguajes de programación:
  • > — mayor que
  • < — menor que
  • >= — mayor o igual que
  • <= — menor o igual que
  • = — igual a
  • != — no igual a
La consulta será //course/duration[@value > 9]:

<duration value="18">18 horas</duration>
<duration value="10">10 horas</duration>
Hemos aprendido cómo seleccionar un solo campo, lo cual es interesante pero raro. Con mayor frecuencia, los desarrolladores procesan datos en todo el archivo o en varios campos. Intentemos utilizar un predicado y acceder a otros campos al mismo tiempo. Observa dos cosas:
  • El predicado no tiene que ir al final de la consulta
  • Dentro del predicado puede haber nuevas rutas que se deben verificar
Ya sabemos cómo filtrar datos por el campo <duration> utilizando el predicado duration[@value > 9]. Ahora intentemos hacer que esta construcción sea un predicado para <course>. Esto nos dará datos sobre los cursos con una duración mayor a 9 horas: //course[duration[@value > 9]]:

<course>
  <title>Fundamentos de maquetación de contenido</title>
  <tags>CSS3, HTML5, Selectores, Accesibilidad, CSS Columns, CSS Units, Diseño</tags>
  <duration value="18">18 horas</duration>
  <url lang="es">https://app.codica.la/courses/css-content-course</url>
</course>
<course>

También se puede continuar esta consulta y obtener solo los nombres de los cursos. En este caso, el predicado estará en el medio de la consulta, no al final: //course[duration[@value > 9]]/name

<name>Fundamentos del diseño de contenido</name>
<name>Bootstrap 5: Fundamentos del diseño</name>
Funciones

En los ejemplos anteriores, las consultas afectaban a las etiquetas y atributos. No se tocaban los datos en sí, a pesar de que son una gran cantidad de información de la que se pueden hacer selecciones. Para resolver este problema, se utilizan las funciones incorporadas en XPath. Estas funciones son parte de los predicados, como @. Intentemos encontrar un curso con el nombre "Fundamentos del diseño de contenido".

Para buscar texto dentro de un elemento, se utiliza la función text(). Su tarea es obtener el valor de texto del elemento y compararlo con la condición según sea necesario. Aquí está cómo se verá la consulta para buscar un curso con el nombre deseado: //course[name[text()="Fundamentos del diseño de contenido"]]

<course>
  <name>Fundamentos del diseño de contenido</name>
  <tags>CSS3, HTML5, Selectores, Accesibilidad, CSS Columns, CSS Units, Diseño</tags>
  <duration value="18">18 horas</duration>
  <url lang="ru">https://codica.la/cursos/css-content</url>
  <url lang="en">https://codica.la/cursos/css-content</url>
</course>
Pero, ¿qué pasa si solo se conoce una parte del nombre? Para esto existe la función contains(), que toma dos argumentos:
  • 1
    La cadena en la que se realizará la búsqueda
  • 2
    La subcadena que se buscará
Por ejemplo, busquemos un curso que tenga la palabra "Bootstrap" en las palabras clave. La función tomará el valor de texto del elemento tags y buscará la palabra "Bootstrap" allí: //course[tags[contains(text(), "Bootstrap")]]

<course>
  <name>Bootstrap 5: Fundamentos del diseño</name>
  <tags>Bootstrap 5, Adaptabilidad, HTML, CSS3</tags>
  <duration value="10">10 horas</duration>
  <url lang="ru">https://codica.la/cursos/bootstrap_basic</url>
  <url lang="en">https://codica.la/cursos/bootstrap_basic</url>
</course>
En el estándar XPath existen algunas otras funciones, pero el objetivo de este artículo es mostrar los principios de cómo funcionan los diferentes mecanismos, no proporcionar una documentación exhaustiva sobre el lenguaje.
Diferencias con los selectores CSS
Si has trabajado con JavaScript, sabrás que se pueden buscar elementos utilizando selectores CSS con los métodos querySelector() o querySelectorAll(). Entonces, ¿por qué los desarrolladores a veces buscan elementos dentro de HTML utilizando XPath en lugar de CSS?

La diferencia radica en el concepto de búsqueda de elementos. Utilizando CSS, solo se puede ir hacia abajo sin la posibilidad de acceder a elementos padres. A diferencia de CSS, XPath permite acceder tanto a elementos secundarios como a elementos padres en cualquier momento.
Si deseas aprender más sobre la búsqueda en HTML utilizando XPath, te recomendamos consultar el artículo Introduction to using XPath in JavaScript (en español).
Con CSS no se pueden encontrar todos los elementos div que contengan enlaces, solo se pueden encontrar los propios enlaces, pero no sus padres. XPath permite hacer esto con la simple combinación div[a]. Con el tiempo, esta situación está cambiando: CSS ha introducido el selector :has(), pero aún no es compatible con todas las versiones más recientes de los navegadores. Con el tiempo, esto cambiará, pero por ahora, esta es la realidad.

Otro ejemplo es la búsqueda de elementos por texto dentro de ellos. CSS nunca podrá hacer esto, ya que no es su objetivo. XPath, como hemos aprendido, puede hacer esto utilizando la función text().
Quién necesita XPath
En resumen, XPath es útil para todos los que trabajan con XML.

Para comprenderlo mejor, veamos algunos ejemplos:

Especialistas en SEO. Los especialistas en optimización de motores de búsqueda a menudo procesan grandes cantidades de datos y extraen información de las páginas web.

Por ejemplo, las etiquetas meta son críticas para ellos: contienen información adicional, como íconos de sitios web, títulos de páginas, descripciones, etc. Los especialistas en SEO pueden extraer automáticamente esta información utilizando consultas en XPath.
Probadores de software. Al trabajar con pruebas de front-end, los probadores a menudo verifican la salida de información en una página: seleccionan elementos individuales de la página según sea necesario. Esto se puede hacer a través de XPath y las herramientas de desarrollo integradas en los navegadores basados en Chromium.

Desarrolladores. A menudo, los desarrolladores utilizan rastreadores: scripts que buscan información específica en páginas web de uno o varios sitios. Por ejemplo, si queremos comparar el precio de un producto en diferentes tiendas, se puede escribir un script que recorra todos los sitios necesarios, compare los precios y devuelva los datos. En este caso, se puede utilizar XPath para buscar información en la página.

Estos son solo algunos de los escenarios en los que el lenguaje XPath es útil, pero en realidad hay docenas de ellos.
Conclusión
En este artículo, hemos explorado dónde se encuentra XML y quién puede beneficiarse de él. Hemos aprendido a construir consultas básicas y hemos explorado las construcciones comúnmente utilizadas en XPath:
  • Rutas absolutas y relativas
  • Predicados
  • Búsqueda por atributos
  • Operadores de comparación
  • Funciones
También ahora sabemos que la búsqueda en HTML utilizando XPath puede ser más eficiente que la búsqueda utilizando selectores CSS.

Hemos intentado proporcionar conocimientos que ayudarán a resolver la mayoría de las tareas. Sin embargo, esto no cubre todas las capacidades de XPath, ya que es un lenguaje más profundo de lo que se presenta en este artículo. Al igual que con otras tecnologías, la práctica es importante. Cuanto más practiques, más precisas y útiles serán tus consultas.
Leer otros artículos de Guías
Lea otros artículos relevantes del mundo de la tecnología y el espíritu empresarial.