W3docs

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 a false per 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:

php— editable, runs on the server

Output:

Prefix: bk, URI: https://example.com/books

Il 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:

MetodoAmbito
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) o registerXPathNamespace().
  • 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.

Pratica

Pratica
Cosa restituisce SimpleXMLElement::getDocNamespaces(true) che getDocNamespaces() (il valore predefinito) non restituisce?
Cosa restituisce SimpleXMLElement::getDocNamespaces(true) che getDocNamespaces() (il valore predefinito) non restituisce?
Was this page helpful?