W3docs

xpath()

SimpleXMLElement::xpath() esegue query XPath su documenti XML in PHP e restituisce i nodi corrispondenti con SimpleXML.

Introduzione

SimpleXMLElement::xpath() esegue una query XPath su un documento XML caricato con l'estensione SimpleXML di PHP e restituisce i nodi corrispondenti. Senza di essa, puoi solo scorrere un albero XML proprietà per proprietà ($xml->book->title); con essa, puoi raggiungere direttamente qualsiasi nodo — indipendentemente dalla profondità — usando una singola espressione di percorso come //book/title.

Questa pagina spiega cosa restituisce xpath(), la sintassi XPath più utilizzata, come leggere gli attributi e gestire i namespace, e le insidie più comuni.

Sintassi

public SimpleXMLElement::xpath(string $expression): array|false
  • $expression — l'espressione XPath da valutare, relativa al nodo su cui viene chiamata.
  • Restituisce — un array di oggetti SimpleXMLElement per ogni nodo corrispondente, un array vuoto quando non ci sono corrispondenze, o false in caso di espressione malformata.

Poiché il risultato è sempre un array, di norma lo si itera con foreach anche quando ci si aspetta una singola corrispondenza.

Primo esempio

Gli esempi seguenti usano simplexml_load_string() per essere eseguiti così come sono, senza file esterni:

<?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 significa "qualsiasi elemento title a qualsiasi profondità." Il ciclo stampa ogni risultato; convertire un SimpleXMLElement in stringa (operazione implicita con echo) restituisce il suo contenuto testuale.

Espressioni XPath comuni

EspressioneSeleziona
/library/bookelementi book figli diretti della radice library
//bookogni elemento book, a qualsiasi profondità
//book/titleil figlio title di ogni book
//book[1]il primo book (XPath è indicizzato da 1, non da 0)
//book[@genre='fiction']libri il cui attributo genre è uguale a fiction
//book[author='Sklar']libri con un figlio <author> uguale a Sklar
//@genreogni nodo attributo genre

Filtrare con un predicato

Un predicato tra parentesi quadre mantiene solo i nodi che soddisfano una condizione:

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

Leggere un attributo all'interno del predicato usa @, mentre leggerlo da un nodo risultato usa la sintassi array — (string) $book['genre']. Consulta attributes per il quadro completo.

Lavorare con i namespace XML

Se il documento dichiara namespace, un percorso semplice come //book non restituirà nulla — il parser ha bisogno del prefisso del namespace. Registra un prefisso con registerXPathNamespace() prima, poi usalo nell'espressione:

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

Il prefisso che registri (l) è locale alla tua query — non deve necessariamente corrispondere al prefisso usato nel documento (lib); solo l'URI del namespace deve coincidere.

Insidie

  • Controlla sempre il risultato. xpath() restituisce false in caso di espressione non valida e un array vuoto se non ci sono corrispondenze. foreach (($xml->xpath($e) ?: []) as $n) protegge da entrambi i casi.
  • I risultati sono oggetti, non stringhe. Esegui il cast con (string) quando hai bisogno del testo: (string) $node.
  • XPath indicizza da 1. //book[1] è il primo libro; non esiste [0].
  • Il contesto è importante. Chiamare xpath('title') su un nodo book effettua la ricerca relativa a quel nodo, mentre un / o // iniziale effettua la ricerca dalla radice del documento indipendentemente da dove lo chiami.

Conclusione

SimpleXMLElement::xpath() trasforma la navigazione profonda e ripetitiva di un albero in una singola query dichiarativa. Combinata con i predicati e la registrazione dei namespace, consente di individuare esattamente i nodi necessari. Abbinala a simplexml_load_string() o all'API SimpleXML più ampia per leggere e trasformare XML in poche righe.

Esercitazione

Pratica
A cosa serve XPath in PHP?
A cosa serve XPath in PHP?
Was this page helpful?