Невозможно добавить пространство имен к атрибуту с PHP SimpleXML

Я создаю канал Atom, когда я попытался добавить xmlns:i в качестве атрибута ниже -

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

Я получил это как вывод -

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

"xmlns:" часть была отрезана. мне нужно экранировать :-символ? Или есть другой способ добавить это пространство имен?


person Sourabh    schedule 20.10.2009    source источник


Ответы (3)


Если вы хотите добавить атрибут из пространства имен/префикса i в $node, не утруждайте себя объявлением пространства имен заранее. Просто используйте третий параметр addAttribute(), чтобы предоставить uri пространства имен для префикса, который вы используете в первом параметре.

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

отпечатки

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

Если сам атрибут не нужен, вы можете удалить его с помощью unset(), оставив объявление пространства имен.

unset($node->attributes('i', TRUE)['somename']);
person VolkerK    schedule 20.10.2009
comment
Это кажется такой тратой. Он объявляет пространство имен в каждой строке, а не только в корне. - person Nathan H; 11.06.2010
comment
Я думаю, что он добавляет в корень фиктивный атрибут, просто чтобы убедить SimpleXMLElement добавить объявление пространства имен. Некрасиво (но это вина PHP, а не VolkerK), но это работает, если вы не возражаете против дополнительного атрибута. - person Olivier 'Ölbaum' Scherler; 22.02.2012
comment
Лучшее решение на самом деле предложено Оливье «Ольбаум» Шерлер. - person ; 15.05.2013
comment
@NathanH Один и тот же префикс может означать разные вещи в разных частях документа, поэтому ссылка на URI пространства имен для каждого элемента является единственным надежным способом указать пространство имен элемента. Затем на этапе сериализации остается удалить лишние объявления xmlns, что он и делает: 3v4l.org/TSdO5 - person IMSoP; 22.04.2017

Если вы не хотите добавлять фиктивный атрибут к корневому элементу, вы можете вручную объявить для него пространство имен, добавив атрибут xmlns для вашего префикса i:

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

Для этого, как указано в существующем ответе (Невозможно добавить атрибут с префиксом пространства имен с помощью PHP Simplexml), вы должны добавить к новому атрибуту префикс xmlns: (поскольку префикс пространства имен xmlns: не объявлен в вашем документе). И поскольку xmlns: является частью имени этого атрибута, вам нужно два вхождения 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();

Выдает (отформатировано вручную для удобочитаемости):

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

Так что этот префикс xmlns: кажется обманом. Обратите внимание, что если вы перезагрузите элемент после установки этого атрибута, можно также использовать uri пространства имен при добавлении дочерних элементов, и это без указания префикса:

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

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

echo $root->asXml();

Выдает (опять же отформатировано вручную):

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

Этот второй пример кажется более близким к предполагаемому (или, по крайней мере, ожидаемому) использованию.

Обратите внимание, что единственный способ сделать это правильно — использовать более полный (но, к сожалению, более сложный и многословный) DOMDocument. Это описано в разделе Как объявить префикс пространства имен XML с помощью DOM/PHP?.

person Olivier 'Ölbaum' Scherler    schedule 22.02.2012
comment
Вам не нужно использовать префикс "xmlns:", вы можете использовать префикс любой старой ерунды (включая пробелы!), если вы включаете что-то перед первым двоеточием :, например $child->addAttribute( 'HACK:i:bar', 'baz');. Другими словами, это не какой-то поддерживаемый, но малоизвестный способ установки префикса xmlns, мы просто обманываем хитрый синтаксический анализатор. Так что мы не можем полагаться на это, чтобы работать в будущем. Мы должны использовать для этого DOM, пока в SimpleXMLElement не будет добавлена ​​правильная поддержка префикса ns. PS тот же хак работает и для префикса имен элементов. - person Sepster; 27.05.2013
comment
Парсер хитрый? В PHP? Я в шоке. Потрясенный! - person Olivier 'Ölbaum' Scherler; 17.01.2014
comment
Вы с сарказмом? Я не могу точно сказать? ;-) - person Sepster; 21.01.2014
comment
Обратите внимание, что это добавляет пространство имен как атрибут, а не объявление: оно появляется в $root->attributes(), но не $root->attributes('xmlns', TRUE), $root->getNamespaces() или $root->getDocNamespaces(). Точно так же «i:bar» не находится в пространстве имен «i»: сравните $child->attributes() и $child->attributes('i', TRUE). - person outis; 15.09.2016

Я нашел это в поисках того же самого, и ни один из ответов мне не помог. Итак, я попробовал другой путь. Если SimpleXML неправильно управляет пространством имен, используйте DOM.

Итак, что-то вроде этого должно работать:

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

Это приведет к следующему:

<?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>
person Dan Jones    schedule 11.04.2014