2009-10-20 11 views
7

sto creando un feed Atom, quando ho cercato di seguito per aggiungere xmlns:i come attributo -namespace aggiuntivo Impossibile con phps SimpleXML

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

Ho ottenuto questo come uscita -

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

"xmlns:" parte è stato interrotto. devo sfuggire al carattere :? O è un altro modo per aggiungere questo spazio dei nomi?

risposta

20

Se si desidera aggiungere un attributo dallo spazio dei nomi/prefisso i a $ nodo, non preoccuparsi di dichiarare preventivamente lo spazio dei nomi. Basta usare il terzo parametro di addAttribute() per fornire lo spazio dei nomi uri per il prefisso che si sta utilizzando nel primo parametro.

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

stampe

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

Se l'attributo in sé non è necessario, è possibile rimuovere con unset(), lasciando la dichiarazione dello spazio dei nomi.

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

Questo mi sembra un tale spreco. Sta dichiarando lo spazio dei nomi su ogni riga invece sulla sola radice. –

+1

Penso che stia aggiungendo un attributo fittizio alla radice, solo per convincere SimpleXMLElement ad aggiungere la dichiarazione dello spazio dei nomi. Brutto (ma colpa di PHP, non di VolkerK) ma funziona se non ti dispiace l'attributo extra. –

+1

La soluzione migliore è in realtà quella fornita da Olivier 'Ölbaum' Scherler –

17

Se non si desidera avere per aggiungere un attributo fittizio per il vostro elemento principale, è possibile dichiarare il namespace manualmente su di esso con l'aggiunta di un attributo xmlns per la vostra i prefisso:

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

Per fare ciò, e come suggerito in una risposta esistente (Unable to add Attribute with Namespace Prefix using PHP Simplexml), è necessario aggiungere il prefisso al nuovo attributo con xmlns: (poiché lo spazio dei nomi non è dichiarato nel documento xmlns:). E poiché xmlns: è parte del nome di tale attributo, è therfore bisogno di due ricorrenze di 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(); 

Dà (formattati manualmente per migliorare la leggibilità):

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

Quindi questo xmlns: prefisso di sembra di barare esso. Si noti che se si ricarica l'elemento dopo impostazione tale attributo, è possibile utilizzare l'URI dello spazio dei nomi, così quando si aggiungono i bambini, e questo senza specificare il prefisso:

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

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

echo $root->asXml(); 

Gives (di nuovo, formattato manualmente):

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

Questo secondo esempio sembra essere più vicino alla destinazione d'uso (o almeno atteso).

Si noti che l'unico modo per farlo correttamente sarebbe utilizzare le classi DOMDocument più complete (ma purtroppo anche più complesse e più dettagliate). Questo è delineato in How to declare an XML namespace prefix with DOM/PHP?.

+0

Grazie per il montaggio, hakre. –

+7

Non hai bisogno di prefisso con '" xmlns: "', puoi prefissi con qualsiasi vecchia spazzatura (compresi gli spazi bianchi!) Finché includi _qualcosa_ prima dei primi due ':', ad esempio '$ bambino-> addAttribute ('HACK: i: bar', 'baz'); '. In altre parole, questo non è un modo supportato ma oscuro per ottenere un prefisso xmlns, stiamo solo "ingannando" il parser losco. Quindi non possiamo fare affidamento su questo per lavorare nel futuro. Dovremmo utilizzare il DOM per questo, fino a quando il supporto del prefisso _proper_ ns viene aggiunto a SimpleXMLElement. PS stesso hack funziona anche per prefissare i nomi degli elementi. – Sepster

+1

Il parser è dubbia? In PHP? Sono scioccato. Scioccato! –

3

Ho trovato questo cercando la stessa cosa, e nessuna delle risposte ha funzionato davvero per me. Quindi, ho provato un percorso diverso. Se SimpleXML non gestisce correttamente lo spazio dei nomi, utilizzare invece DOM.

Quindi, qualcosa di simile a questo dovrebbe funzionare:

$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"); 

che si tradurrà in questo:

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