2

我刚刚花了很多时间试图从 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 中的错误吗?有人知道我还能做什么吗?

感谢您的任何回答

4

2 回答 2

2

你不能用DOMDocument. 这些并不是真正的“属性”(它们在 DOM 中作为属性不可见,也不属于 XML 信息集)。它们是命名空间声明,在 xml 序列化之外不存在。最重要的是,它们不会以任何方式在 DOM 中表示。

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

旧版本的 PHP 中似乎存在一个错误,您可以使用 删除这些节点removeAttributeNS,但这已得到修复。有关此方法,请参阅PHP 文档的注释。

我的意见:你不应该试图摆脱这些节点。这不值得你花时间,离开他们也没有什么坏处。

但是,如果您真的想摆脱它们,则必须使用另一种方法。一种方法是手动将整个 DOM 树深度复制到新的 DOM 文档中。如果您在复制时使用createElementNSand (而不是使用or ),则不会在您的副本中创建隐藏的命名空间节点。我不会为您编写代码来执行此操作,因为它会很乏味。setAttributeNSimportNodecloneNode

这个 stackoverflow 答案提出了一个 xslt 解决方案。我不确定它是否会起作用,因为 XSLT 1.0 也没有公开这些命名空间声明“节点”。

更新

如果除了删除多余的 XML 节点之外,您还可以对 XML 执行其他操作,您可以尝试XML canonicalization。规范 XML 的目的是确保相同的 XML 信息集始终生成相同的 XML 输出字符串。(这对于比较 XML 文件或创建校验和哈希等事情很有用。)但它也可以做一些事情,比如从不使用自闭合标签。

试试看:

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

文档:

于 2012-10-16T19:48:55.727 回答
-3

您应该使用 removeAttributeNS 方法:

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

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

于 2012-10-16T18:30:31.963 回答