2009-10-20 83 views
7

我创建一个Atom feed,当我试图下方添加xmlns:i作为一个属性 -无法添加命名空间与PHP的SimpleXML的

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

我得到这个作为一个输出 -

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

"xmlns:"部分被切断。我需要逃脱:-character?或者他们是否有其他方式来添加这个名称空间?

回答

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']); 
+4

这似乎是一种浪费。它是在每一行上声明命名空间,而不是仅在根上。 –

+1

我认为他正在向根添加一个虚拟属性,只是为了说服SimpleXMLElement添加名称空间声明。丑陋(但PHP的错,而不是VolkerK的),但它的作品,如果你不介意额外的属性。 –

+1

最好的解决方案实际上是由Olivier“Ölbaum” Scherler – 2013-05-15 08:29:34

17

如果你不希望有一个虚拟的属性添加到您的根元素,你可以手动上通过添加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:是该属性的名称的一部分,你therfore需要的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?中概述。

+0

谢谢你的编辑,哈哈。 –

+7

你不需要用'前缀“的xmlns:”',你可以用任何旧的垃圾前缀,只要您提供您的第一个冒号之前'_something_(包括空格!):',比如'$儿童安全>的addAttribute ('HACK:我:酒吧','baz');'。换句话说,这并不是一些得到xmlns前缀的模糊方式,我们只是“欺骗”狡猾的解析器。所以我们不能依靠这个去面对未来。我们应该为此使用DOM,直到_proper_ ns前缀支持被添加到SimpleXMLElement。 PS同样的黑客也可以为元素名称加上前缀。 – Sepster

+1

解析器是狡猾的?在PHP中?我很震惊。震惊! –

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>