W3docs

xpath()

Aprende a usar SimpleXMLElement::xpath() en PHP para ejecutar consultas XPath sobre documentos XML y obtener nodos coincidentes.

Introducción

SimpleXMLElement::xpath() ejecuta una consulta XPath sobre un documento XML cargado con la extensión SimpleXML de PHP y devuelve los nodos coincidentes. Sin ella, solo puedes recorrer un árbol XML propiedad a propiedad ($xml->book->title); con ella, puedes saltar directamente a cualquier nodo —sin importar su profundidad— usando una única expresión de ruta como //book/title.

Esta página explica qué devuelve xpath(), la sintaxis XPath que más usarás, cómo leer atributos y manejar espacios de nombres, y los errores comunes que suelen confundir a los desarrolladores.

Sintaxis

public SimpleXMLElement::xpath(string $expression): array|false
  • $expression — la expresión XPath a evaluar, relativa al nodo sobre el que se llama.
  • Devuelve — un array de objetos SimpleXMLElement por cada nodo coincidente, un array vacío cuando no hay coincidencias, o false si la expresión es incorrecta.

Dado que el resultado siempre es un array, normalmente se itera con foreach incluso cuando se espera una sola coincidencia.

Un primer ejemplo

Los ejemplos a continuación usan simplexml_load_string() para poder ejecutarse tal cual, sin ningún archivo externo:

<?php

$data = <<<XML
<library>
    <book genre="fiction">
        <title>The Pragmatic Programmer</title>
        <author>Hunt</author>
    </book>
    <book genre="reference">
        <title>PHP Cookbook</title>
        <author>Sklar</author>
    </book>
</library>
XML;

$xml = simplexml_load_string($data);

// Select every <title> anywhere under the root.
foreach ($xml->xpath('//title') as $title) {
    echo $title . "\n";
}

Salida:

The Pragmatic Programmer
PHP Cookbook

//title significa "cualquier elemento title a cualquier profundidad." El bucle imprime cada resultado; convertir un SimpleXMLElement a string (realizado implícitamente por echo) devuelve su contenido de texto.

Expresiones XPath comunes

ExpresiónSelecciona
/library/bookelementos book que son hijos directos del elemento raíz library
//booktodo elemento book, a cualquier profundidad
//book/titleel hijo title de cada book
//book[1]el primer book (XPath indexa desde 1, no desde 0)
//book[@genre='fiction']libros cuyo atributo genre es igual a fiction
//book[author='Sklar']libros con un elemento hijo <author> igual a Sklar
//@genretodo nodo de atributo genre

Filtrado con un predicado

Un predicado entre corchetes conserva solo los nodos que cumplen una condición:

<?php

$data = <<<XML
<library>
    <book genre="fiction"><title>Dune</title></book>
    <book genre="reference"><title>PHP Cookbook</title></book>
</library>
XML;

$xml = simplexml_load_string($data);

$fiction = $xml->xpath("//book[@genre='fiction']");
echo $fiction[0]->title . "\n";  // Dune
echo count($fiction) . " match\n"; // 1 match

Salida:

Dune
1 match

Leer un atributo dentro del predicado usa @, mientras que leerlo desde un nodo resultado usa sintaxis de array — (string) $book['genre']. Consulta attributes para ver el panorama completo.

Trabajo con espacios de nombres XML

Si el documento declara espacios de nombres, una ruta simple como //book no devolverá nada — el analizador necesita el prefijo del espacio de nombres. Registra un prefijo con registerXPathNamespace() primero y luego úsalo en la expresión:

<?php

$data = <<<XML
<lib:library xmlns:lib="http://example.com/lib">
    <lib:book><lib:title>Clean Code</lib:title></lib:book>
</lib:library>
XML;

$xml = simplexml_load_string($data);
$xml->registerXPathNamespace('l', 'http://example.com/lib');

foreach ($xml->xpath('//l:book/l:title') as $title) {
    echo $title . "\n";  // Clean Code
}

Salida:

Clean Code

El prefijo que registras (l) es local a tu consulta — no tiene que coincidir con el prefijo usado en el documento (lib); solo debe coincidir el URI del espacio de nombres.

Errores comunes

  • Verifica siempre el resultado. xpath() devuelve false ante una expresión inválida y un array vacío si no hay coincidencias. foreach (($xml->xpath($e) ?: []) as $n) protege contra ambos casos.
  • Los resultados son objetos, no strings. Convierte con (string) cuando necesites el texto: (string) $node.
  • XPath indexa desde 1. //book[1] es el primer libro; no existe el [0].
  • El contexto importa. Llamar a xpath('title') en un nodo book busca relativo a ese nodo, mientras que un / o // inicial busca desde la raíz del documento independientemente de dónde se llame.

Conclusión

SimpleXMLElement::xpath() convierte el recorrido profundo y repetitivo de árboles en una única consulta declarativa. Combinado con predicados y registro de espacios de nombres, permite ubicar exactamente los nodos que necesitas. Úsalo junto con simplexml_load_string() o la API más amplia de SimpleXML para leer y transformar XML en pocas líneas.

Práctica

Práctica
¿Para qué se usa XPath en PHP?
¿Para qué se usa XPath en PHP?
Was this page helpful?