getDocNamespaces()
SimpleXML es una extensión de PHP que ofrece una API sencilla para trabajar con documentos XML. Aprende a usar SimpleXMLElement::getDocNamespaces().
Introducción
SimpleXML es una extensión de PHP que proporciona una API sencilla y orientada a objetos para leer documentos XML. Los espacios de nombres XML permiten que dos vocabularios compartan un mismo documento sin que sus nombres de elementos entren en conflicto — cada espacio de nombres se identifica mediante una URI y generalmente se referencia con un breve prefijo (por ejemplo, bk en <bk:title>).
SimpleXMLElement::getDocNamespaces() es el método que indica qué espacios de nombres declara un documento. Por lo general se usa antes de llamar a children() o xpath() sobre datos con espacios de nombres, ya que se necesitan las URIs para poder direccionar esos nodos. Este capítulo cubre la sintaxis, la diferencia que produce el indicador $recursive, el problema con el espacio de nombres predeterminado y cómo difiere del método getNamespaces(), que tiene un nombre muy similar.
Sintaxis
public SimpleXMLElement::getDocNamespaces(bool $recursive = false, bool $from_root = true): array$recursive— cuando esfalse(el valor predeterminado), solo se devuelven los espacios de nombres declarados en el elemento raíz. Cuando estrue, se analiza todo el árbol del documento y también se incluyen los espacios de nombres declarados en cualquier descendiente.$from_root— cuando estrue(el valor predeterminado), el análisis comienza desde la raíz del documento aunque se llame al método sobre un subelemento. Establézcalo enfalsepara analizar solo desde el nodo actual hacia abajo.
El valor de retorno es un array asociativo que asigna cada prefijo de espacio de nombres (la cadena antes de los dos puntos) a su URI.
Ejemplo básico
Este documento declara un espacio de nombres, bk, en su elemento raíz:
Salida:
Prefix: bk, URI: https://example.com/booksEl método devuelve un array asociativo, por lo que un foreach con $prefix => $uri recorre cada declaración en un solo bucle.
Qué cambia realmente $recursive
El indicador solo importa cuando un espacio de nombres se declara por debajo de la raíz. Aquí lib está en la raíz, pero dc se declara en un elemento <details> anidado:
<?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));Salida:
Root only:
Array
(
[lib] => https://example.com/library
)
Whole document:
Array
(
[lib] => https://example.com/library
[dc] => https://purl.org/dc/elements/1.1/
)Pasa true siempre que no puedas garantizar que todos los espacios de nombres estén declarados en la raíz — los feeds y los documentos agregados suelen declarar extras más abajo en el árbol.
El problema con el espacio de nombres predeterminado
Un espacio de nombres declarado con xmlns="..." (sin prefijo) es el espacio de nombres predeterminado del documento. getDocNamespaces() lo devuelve bajo una clave de cadena vacía, no bajo la 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));Salida:
Array
(
[] => http://www.w3.org/2005/Atom
[media] => http://search.yahoo.com/mrss/
)Necesitarás esa URI de cadena vacía para leer los nodos con espacio de nombres predeterminado, p. ej. $xml->children('http://www.w3.org/2005/Atom') o registrándola con registerXPathNamespace() antes de una consulta xpath().
getDocNamespaces() vs getNamespaces()
Estos dos métodos son fáciles de confundir:
| Método | Alcance |
|---|---|
getDocNamespaces() | Espacios de nombres declarados en el documento (los atributos xmlns), independientemente de si algo los usa. |
getNamespaces() | Espacios de nombres realmente usados por el elemento y (opcionalmente) sus hijos — los espacios de nombres declarados pero no utilizados quedan excluidos. |
En resumen: getDocNamespaces() responde "¿qué define este documento?" mientras que getNamespaces() responde "¿qué usa esta parte del documento?".
Cuándo usarlo
- Antes de consultar nodos con espacios de nombres — introduce las URIs devueltas en
children($uri)oregisterXPathNamespace(). - Al consumir XML de terceros (RSS/Atom, SOAP, RSS Media, SVG) donde no controlas los prefijos.
- Para inspeccionar o validar las declaraciones de espacio de nombres de un documento desconocido.
Conclusión
SimpleXMLElement::getDocNamespaces() devuelve un array asociativo con los prefijos de espacio de nombres y las URIs declaradas en un documento XML. Usa el valor predeterminado (false) cuando todos los espacios de nombres están en la raíz, y pasa true para analizar todo el árbol. Recuerda que el espacio de nombres predeterminado (sin prefijo) se devuelve bajo una clave de cadena vacía, y recurre a getNamespaces() cuando te importa cuáles espacios de nombres se usan realmente y no solo cuáles están declarados.