我花了很多时间尝试从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中的错误吗?有人知道我还能做什么吗?
感谢您的回答
答案 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文档。如果您在复制时使用createElementNS
和setAttributeNS
(而不是使用importNode
或cloneNode
),则不会在副本中创建隐藏的命名空间节点。我不打算为你编写代码,因为它会很乏味。
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