W3docs

xpath()

SimpleXML is a PHP extension that provides a simple and easy-to-use API for working with XML documents. The SimpleXMLElement::xpath() function is one of the

Introduction

SimpleXMLElement::xpath() runs an XPath query against an XML document loaded with PHP's SimpleXML extension and returns the matching nodes. Without it, you can only walk an XML tree property-by-property ($xml->book->title); with it, you can jump straight to any node — no matter how deep — using a single path expression such as //book/title.

This page explains what xpath() returns, the XPath syntax you'll use most, how to read attributes and handle namespaces, and the gotchas that trip people up.

Syntax

public SimpleXMLElement::xpath(string $expression): array|false
  • $expression — the XPath expression to evaluate, relative to the node you call it on.
  • Returns — an array of SimpleXMLElement objects for every matching node, an empty array when nothing matches, or false on a malformed expression.

Because the result is always an array, you normally iterate it with foreach even when you expect a single match.

A first example

The examples below use simplexml_load_string() so they run as-is, with no external file:

<?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";
}

Output:

The Pragmatic Programmer
PHP Cookbook

//title means "any title element at any depth." The loop prints each result; casting a SimpleXMLElement to a string (done implicitly by echo) yields its text content.

Common XPath expressions

ExpressionSelects
/library/bookbook elements that are direct children of the root library
//bookevery book element, at any depth
//book/titlethe title child of every book
//book[1]the first book (XPath is 1-indexed, not 0)
//book[@genre='fiction']books whose genre attribute equals fiction
//book[author='Sklar']books with a child <author> of Sklar
//@genreevery genre attribute node

Filtering with a predicate

A predicate in square brackets keeps only the nodes that match a condition:

<?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

Output:

Dune
1 match

Reading an attribute inside the predicate uses @, while reading it from a result node uses array syntax — (string) $book['genre']. See attributes for the full picture.

Working with XML namespaces

If the document declares namespaces, a bare path like //book will return nothing — the parser needs the namespace prefix. Register a prefix with registerXPathNamespace() first, then use it in the expression:

<?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
}

Output:

Clean Code

The prefix you register (l) is local to your query — it does not have to match the prefix used in the document (lib); only the namespace URI must match.

Gotchas

  • Always check the result. xpath() returns false on an invalid expression and an empty array on no match. foreach (($xml->xpath($e) ?: []) as $n) guards against both.
  • Results are objects, not strings. Cast with (string) when you need the text: (string) $node.
  • XPath indexes from 1. //book[1] is the first book; there is no [0].
  • Context matters. Calling xpath('title') on a book node searches relative to that node, while a leading / or // searches from the document root regardless of where you call it.

Conclusion

SimpleXMLElement::xpath() turns deep, repetitive tree-walking into a single declarative query. Combined with predicates and namespace registration, it lets you pinpoint exactly the nodes you need. Pair it with simplexml_load_string() or the broader SimpleXML API to read and transform XML in just a few lines.

Practice

Practice
What is XPath in PHP used for?
What is XPath in PHP used for?
Was this page helpful?