首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止DOMNode::cloneNode()插入冗余名称空间?

如何防止DOMNode::cloneNode()插入冗余名称空间?
EN

Stack Overflow用户
提问于 2016-11-10 22:51:52
回答 1查看 199关注 0票数 1

我使用PHP实现来修改内置DOM文档,特别是ODS电子表格中的content.xml文件。本文档大量使用名称空间(根元素中声明了35个不同的名称空间)。

我试图使用浅层table-cell将一个cloneNode()元素复制到一个新行,但是结果与原来的不完全相同:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<office:document-content
    xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
    xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
    xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
    [... snip 32 ...]>

<!-- original -->
<table:table-cell table:style-name="ce5"
                  office:value-type="string"
                  calcext:value-type="string">

<!-- cloned -->
<table:table-cell xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
                  xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
                  xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
                  table:style-name="ce5"
                  office:value-type="string"
                  calcext:value-type="string">

虽然这在语义上是相似的,但它可能会在较大的电子表格中造成很大的膨胀(即使XML是压缩在磁盘上的)。

有解决办法吗?

首先,使用非命名空间感知方法并简单地复制属性(包括前缀和标记名)的天真方法似乎是可行的:

代码语言:javascript
复制
$clone = $doc->createElement($ele->tagName);
foreach ($ele->attributes as $att) {
    $clone->setAttribute($att->nodeName, $att->value);
}

生成的XML看起来与预期的完全相同。但是,当克隆元素再次被操作时:

代码语言:javascript
复制
$clone->setAttributeNS($officeNS, "office:value-type", "string");

结果有两个相同的属性名:

代码语言:javascript
复制
<table:table-cell xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
                  table:style-name="ce5"
                  office:value-type="string"
                  calcext:value-type="string"
                  office:value-type="string"
                  office:string-value="">

这使得文档无效。通常,我发现混合命名空间和非命名空间的方法调用是不可行的。

EN

回答 1

Stack Overflow用户

发布于 2016-11-11 15:14:40

下面是一个libxml常量,允许在加载时优化名称空间:

代码语言:javascript
复制
$xml = <<<'XML'
<f:foo xmlns:f="urn:foo">
  <f:foo>
    <f:foo xmlns:f="urn:foo">
    </f:foo>
  </f:foo>
</f:foo>
XML;

$document = new DOMDocument();
$document->loadXml($xml, LIBXML_NSCLEAN);
echo $document->saveXml();

输出:

代码语言:javascript
复制
<?xml version="1.0"?>
<f:foo xmlns:f="urn:foo">
  <f:foo>
    <f:foo>
    </f:foo>
  </f:foo>
</f:foo>

这主要是可行的,但如果同一文档中的不同名称空间使用相同的前缀,则会得到一些无效的结果。

FluentDOM库包含此作业的优化器。它还允许您更改/定义前缀。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40538406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档