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

Sou*_*abh 9 php simplexml xml-namespaces

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

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

我把它作为输出 -

i="http://www.w3.org/2001/XMLSchema-instance"
Run Code Online (Sandbox Code Playgroud)

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

Vol*_*erK 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();
Run Code Online (Sandbox Code Playgroud)

版画

<?xml version="1.0"?>
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance" i:somename="somevalue"/>
Run Code Online (Sandbox Code Playgroud)

如果不需要属性本身,则可以删除它unset(),保留命名空间声明.

unset($node->attributes('i', TRUE)['somename']);
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是一种浪费.它在每一行声明命名空间而不仅仅是根. (4认同)

Oli*_*ler 18

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

<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
Run Code Online (Sandbox Code Playgroud)

为了做到这一点,并且在现有答案中暗示(无法使用PHP Simplexml添加带有命名空间前缀的属性),您必须为新属性添加前缀xmlns:(因为xmlns:未在您的文档中声明命名空间prefic).并且由于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();
Run Code Online (Sandbox Code Playgroud)

给出(手动格式化以便于阅读):

<?xml version="1.0"?>
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <foo i:bar="baz"/>
</root>
Run Code Online (Sandbox Code Playgroud)

所以这个xmlns:前缀似乎欺骗了它.请注意,如果设置该属性重新加载元素,则在添加子元素时也可以使用命名空间uri,而不指定前缀:

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

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

echo $root->asXml();
Run Code Online (Sandbox Code Playgroud)

给(再次,手动格式化):

<?xml version="1.0"?>
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <foo i:bar="baz"/>
    <foo i:bar="bazy"/>
</root>
Run Code Online (Sandbox Code Playgroud)

第二个例子似乎更接近预期(或至少预期)的用途.

请注意,正确执行此操作的唯一方法是使用更完整(但不幸的是也更复杂和更详细)的DOMDocument类.如何使用DOM/PHP声明XML名称空间前缀中概述了这一点.

  • 你不需要以"xmlns:"`作为前缀,只要在第一个冒号`:`之前包含_something_,就可以在任何旧的垃圾前缀(包括空格!),例如`$ child-> addAttribute( '哈克:我:酒吧','巴兹');`.换句话说,这不是一些支持但不明确的方式来获取xmlns前缀,我们只是"欺骗"狡猾的解析器.所以我们不能依靠这个来开展未来.我们应该使用DOM,直到将_proper_ns前缀支持添加到SimpleXMLElement.PS同样的hack也可以为元素名称添加前缀. (7认同)