getDocNamespaces()
SimpleXML è un'estensione PHP che fornisce un'API semplice per lavorare con documenti XML. La funzione SimpleXMLElement::getDocNamespaces() è uno
Introduzione
SimpleXML è un'estensione PHP che fornisce un'API semplice e orientata agli oggetti per leggere documenti XML. I namespace XML permettono a due vocabolari di condividere lo stesso documento senza che i nomi degli elementi collidano — ogni namespace è identificato da un URI e di solito viene referenziato tramite un breve prefisso (ad esempio, bk in <bk:title>).
SimpleXMLElement::getDocNamespaces() è il metodo che indica quali namespace un documento dichiara. Di solito lo si utilizza prima di chiamare children() o xpath() su dati con namespace, perché servono gli URI per accedere a quei nodi. Questo capitolo tratta la sintassi, la differenza che il flag $recursive comporta, il problema del namespace predefinito e come differisce dal metodo dal nome simile getNamespaces().
Sintassi
public SimpleXMLElement::getDocNamespaces(bool $recursive = false, bool $from_root = true): array$recursive— quando èfalse(il valore predefinito), vengono restituiti solo i namespace dichiarati sull'elemento radice. Quando ètrue, viene analizzato l'intero albero del documento e vengono inclusi anche i namespace dichiarati su qualsiasi discendente.$from_root— quando ètrue(il valore predefinito), la scansione parte dalla radice del documento anche se si chiama il metodo su un sotto-elemento. Impostarlo afalseper scansionare solo dal nodo corrente in poi.
Il valore restituito è un array associativo che mappa ogni prefisso di namespace (la stringa prima dei due punti) al suo URI.
Esempio di base
Questo documento dichiara un namespace, bk, sul suo elemento radice:
Output:
Prefix: bk, URI: https://example.com/booksIl metodo restituisce un array associativo, quindi un foreach con $prefix => $uri percorre ogni dichiarazione in un solo ciclo.
Cosa cambia con $recursive
Il flag è rilevante solo quando un namespace viene dichiarato sotto la radice. Qui lib si trova sulla radice ma dc è dichiarato su un elemento <details> annidato:
<?php
$xml = new SimpleXMLElement(
'<library xmlns:lib="https://example.com/library">'
. ' <lib:book>'
. ' <details xmlns:dc="https://purl.org/dc/elements/1.1/">'
. ' <dc:title>PHP Basics</dc:title>'
. ' </details>'
. ' </lib:book>'
. '</library>'
);
echo "Root only:\n";
print_r($xml->getDocNamespaces(false));
echo "Whole document:\n";
print_r($xml->getDocNamespaces(true));Output:
Root only:
Array
(
[lib] => https://example.com/library
)
Whole document:
Array
(
[lib] => https://example.com/library
[dc] => https://purl.org/dc/elements/1.1/
)Passa true ogni volta che non puoi garantire che ogni namespace sia dichiarato sulla radice — feed e documenti aggregati spesso dichiarano namespace extra più in profondità nell'albero.
Il problema del namespace predefinito
Un namespace dichiarato con xmlns="..." (senza prefisso) è il namespace predefinito del documento. getDocNamespaces() lo restituisce con una chiave stringa vuota, non con l'URI:
<?php
$xml = new SimpleXMLElement(
'<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">'
. '<entry><title>Hello</title></entry>'
. '</feed>'
);
print_r($xml->getDocNamespaces(true));Output:
Array
(
[] => http://www.w3.org/2005/Atom
[media] => http://search.yahoo.com/mrss/
)Sarà necessario quell'URI con stringa vuota per leggere i nodi con namespace predefinito, ad es. $xml->children('http://www.w3.org/2005/Atom') oppure registrandolo con registerXPathNamespace() prima di una query xpath().
getDocNamespaces() vs getNamespaces()
Questi due metodi si confondono facilmente:
| Metodo | Ambito |
|---|---|
getDocNamespaces() | Namespace dichiarati nel documento (gli attributi xmlns), indipendentemente dal fatto che vengano utilizzati o meno. |
getNamespaces() | Namespace effettivamente usati dall'elemento e (opzionalmente) dai suoi figli — i namespace dichiarati ma non usati vengono esclusi. |
In breve: getDocNamespaces() risponde alla domanda "cosa definisce questo documento?" mentre getNamespaces() risponde a "cosa usa questa parte del documento?".
Quando usarlo
- Prima di interrogare nodi con namespace — alimenta gli URI restituiti in
children($uri)oregisterXPathNamespace(). - Quando si consumano XML di terze parti (RSS/Atom, SOAP, RSS Media, SVG) di cui non si controllano i prefissi.
- Per ispezionare o validare le dichiarazioni di namespace di un documento sconosciuto.
Conclusione
SimpleXMLElement::getDocNamespaces() restituisce un array associativo dei prefissi e URI di namespace dichiarati in un documento XML. Usa il valore predefinito (false) quando ogni namespace si trova sulla radice, e passa true per scansionare l'intero albero. Ricorda che il namespace predefinito (senza prefisso) viene restituito con una chiave stringa vuota, e usa getNamespaces() quando ti interessa quali namespace vengono effettivamente usati anziché semplicemente dichiarati.