如何删除带有命名空间的属性,例如xmlns:使用DOMElement的xsi

时间:2012-10-16 18:12:40

标签: php dom

我花了很多时间尝试从DOMNode中删除带有命名空间的属性,而根本不工作。

xml是从数据库生成的,如下所示:

<dictionary>

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

  <table>answers</table>
  <entity>Answer</entity>
</row>

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

  <table>file_trans</table>
  <entity>FileTrans</entity>
</row>

...
</dictionary>

我试图删除的属性名称显然是“xmlns:xsi”。 postgres db自动添加它,我无法将其删除,所以我试图用php完成这项工作。

我将xml加载为DOMDocument,然后我在所有行元素中执行foreach循环:

$xml = new DOMDocument();
$xml->loadXML($tablesInXml['xmlelement'], LIBXML_NOBLANKS);

foreach($xml->documentElement->childNodes as $row) {
  $row->removeAttribute('xsi');  // not working
  $row->removeAttribute('xmlns:xsi'); // not working
...

我甚至尝试侦察DOMNode属性属性,它根本不包含任何属性,并显示长度为0.

这是php 5.3中的错误吗?有人知道我还能做什么吗?

感谢您的回答

2 个答案:

答案 0 :(得分:2)

你不能用DOMDocument以微不足道的方式做到这一点。那些不是真正的“属性”(它们在DOM中不作为属性可见,并且不是XML Infoset的一部分)。它们是命名空间声明,并且在xml序列化之外不存在。最重要的是,它们没有以任何方式在DOM中表示。

libxml2(DOMDocument的底层xml库)在内部跟踪这些“命名空间节点”,但不向它们公开公共接口。因此,如果您克隆或导入节点,即使您看不到它,xml命名空间声明也会跟随。

在旧版本的PHP中似乎存在一个错误,您可以使用removeAttributeNS删除这些节点,但这已得到修复。请参阅the comment on the PHP documentation for this method

我的观点:你不应该试图摆脱这些节点。这不值得花时间,离开它们不会有任何伤害。

但是,如果你真的想要摆脱它们,你必须使用另一种方法。您可以这样做的一种方法是手动将整个DOM树深度复制到新的DOM文档。如果您在复制时使用createElementNSsetAttributeNS(而不是使用importNodecloneNode),则不会在副本中创建隐藏的命名空间节点。我不打算为你编写代码,因为它会很乏味。

This stackoverflow answer建议使用xslt解决方案。我不确定它是否会起作用,因为XSLT 1.0也没有暴露这些命名空间声明“节点”。

更新

如果您对XML 除了之外的其他事情做好了,只需删除冗余的XML节点,您就可以尝试XML canonicalization。 Canonical XML的目的是确保相同的XML信息集始终生成相同的XML输出字符串。 (这对于比较XML文件或创建校验和哈希等内容非常有用。)但它也可以执行从不使用自关闭标记的操作。

试一试,看看:

$d = new DOMDocument();
$d->loadXML($xml, LIBXML_NOBLANKS);
echo $d->C14N(true, false);

文档:

答案 1 :(得分:-3)

您应该使用removeAttributeNS方法:

$row->removeAttributeNS('xmlns:xsi');

更多信息可在手册中找到:http://www.php.net/manual/en/domelement.removeattributens.php