无法使用PHP的SimpleXML向属性添加命名空间

时间:2009-10-20 05:38:35

标签: php simplexml xml-namespaces

我正在创建一个Atom Feed,当我在下面尝试添加xmlns:i作为属性时 -

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

我把它作为输出 -

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

"xmlns:"部分被切断了。我是否需要逃避:字符?或者他们是否可以通过其他方式添加此命名空间?

3 个答案:

答案 0 :(得分:20)

如果要将名称空间/前缀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']);

答案 1 :(得分:18)

如果您不想在根元素中添加虚拟属性,可以通过为xmlns前缀添加i属性来手动声明命名空间:

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

为了做到这一点,并且在现有答案(Unable to add Attribute with Namespace Prefix using 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类。这在How to declare an XML namespace prefix with DOM/PHP?中列出。

答案 2 :(得分:3)

我发现这找到了同样的事情,但没有一个答案对我有用。所以,我尝试了不同的路线。如果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>