2009-10-20 12 views
7

Estoy creando un feed Atom, cuando traté de abajo para agregar xmlns:i como un atributo -Incapaz espacio de nombres complemento con los PHP SimpleXML

$node->addAttribute("xmlns:i","http://www.w3.org/2001/XMLSchema-instance"); 

Tengo esto como una salida -

i="http://www.w3.org/2001/XMLSchema-instance" 

"xmlns:" parte fue cortado. ¿Necesito escapar del : -character? ¿O hay alguna otra manera de agregar este espacio de nombres?

Respuesta

20

Si desea agregar un atributo del espacio de nombre/prefijo i a $ node, no se moleste en declarar el espacio de nombres de antemano. Simplemente use el tercer parámetro de addAttribute() para proporcionar el espacio de nombres uri para el prefijo que está utilizando en el primer parámetro.

$node = new SimpleXMLElement('<root></root>'); 
$node->addAttribute("i:somename", "somevalue", 'http://www.w3.org/2001/XMLSchema-instance'); 
echo $node->asXml(); 

impresiones

<?xml version="1.0"?> 
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance" i:somename="somevalue"/> 

Si no se necesita el atributo en sí, a continuación, puede eliminar con unset(), dejando a la declaración de espacio de nombres.

unset($node->attributes('i', TRUE)['somename']); 
+4

Este parece ser un desperdicio. Está declarando el espacio de nombres en cada línea en lugar de solo la raíz. –

+1

Creo que está agregando un atributo ficticio a la raíz, solo para convencer a SimpleXMLElement de que agregue la declaración del espacio de nombres. Feo (pero culpa de PHP, no de VolkerK) pero funciona si no te importa el atributo extra. –

+1

La mejor solución es realmente la proporcionada por Olivier 'Ölbaum' Scherler –

17

Si no quieren tener que añadir un atributo ficticio a su elemento raíz, se puede declarar el espacio de nombres de forma manual en él mediante la adición de un atributo xmlns para su i prefijo:

<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 

Para hacerlo, y como se insinuó en una respuesta existente (Unable to add Attribute with Namespace Prefix using PHP Simplexml), debe anteponer el nuevo atributo al xmlns: (ya que el espacio de nombres xmlns: no está declarado en su documento). Y puesto que xmlns: es parte del nombre de ese atributo, therfore necesita dos apariciones de xmlns:

$uri = 'http://www.w3.org/2001/XMLSchema-instance'; 

$root = new SimpleXMLElement('<root/>'); 
$root->addAttribute('xmlns:xmlns:i', $uri); 
         ###### 

$child = $root->addChild('foo'); 
$child->addAttribute('xmlns:i:bar', 'baz'); 
         ###### 

echo $root->asXml(); 

Gives (formato manualmente para facilitar la lectura):

<?xml version="1.0"?> 
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <foo i:bar="baz"/> 
</root> 

Así que este xmlns: prefijar parece tramposo ella. Tenga en cuenta que si vuelve a cargar el elemento después establecimiento de ese atributo, es posible utilizar el URI de espacio de nombres, así cuando se añaden los niños, y esto sin especificar el prefijo:

$root = new SimpleXMLElement($root->asXML()); 

$child = $root->addChild('foo'); 
$child->addAttribute('i:bar', 'bazy', $uri); 
             #### 

echo $root->asXml(); 

Da (de nuevo, el formato manualmente):

<?xml version="1.0"?> 
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <foo i:bar="baz"/> 
    <foo i:bar="bazy"/> 
</root> 

Este segundo ejemplo parece estar más cerca del uso previsto (o al menos esperado).

Tenga en cuenta que la única manera de hacer esto correctamente sería utilizar las clases más completas (pero desafortunadamente también más complejas y más detalladas) DOMDocument. Esto se describe en How to declare an XML namespace prefix with DOM/PHP?.

+0

Gracias por la edición, hakre. –

+7

No necesita insertar el prefijo '" xmlns: "', puede prefijar con cualquier basura vieja (incluido el espacio en blanco!) Siempre que incluya _algo_ antes de los primeros dos puntos ':', por ejemplo '$ child-> addAttribute ('HACK: i: bar', 'baz'); '. En otras palabras, esta no es una forma soportada pero oscura de obtener un prefijo xmlns en su lugar, solo estamos "engañando" al analizador dudoso. Entonces no podemos confiar en que esto funcione en el futuro. Deberíamos usar el DOM para esto, hasta que se agregue el soporte del prefijo _proper_ ns a SimpleXMLElement. El mismo truco de PS también sirve para prefijar los nombres de los elementos. – Sepster

+1

¿El analizador es dudoso? En PHP? Estoy impactado. ¡Conmocionado! –

3

Encontré esto buscando lo mismo, y ninguna de las respuestas realmente funcionó para mí. Entonces, probé una ruta diferente. Si SimpleXML no gestiona correctamente el espacio de nombres, use DOM en su lugar.

Por lo tanto, algo como esto debería funcionar:

$s = new simplexmlelement('<root/>'); 
$d = dom_import_simplexml($s); 
$d->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:i", "http://www.w3.org/2001/XMLSchema-instance"); 
$s->addChild("bar", "bazy", "http://www.w3.org/2001/XMLSchema-instance"); 
$f = $s->addChild("foo", "quux"); 
$f->addAttribute("i:corge", "grault", "http://www.w3.org/2001/XMLSchema-instance"); 

que darán lugar a esto:

<?xml version="1.0"?> 
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <i:bar>bazy</i:bar> 
    <foo i:corge="grault">quux</foo> 
</root> 
Cuestiones relacionadas