2016-11-10 42 views
1

我使用PHP的built-in DOM实现来修改ODS电子表格中的XML文档,特别是content.xml文件。本文档大量使用名称空间(在根元素中声明了35个不同的名称空间)。如何保持DOMNode :: cloneNode()不插入冗余名称空间?

我想用浅cloneNode()table-cell元素复制到一个新行,但结果并不完全等同于原:

<?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被压缩在磁盘上)。

有没有解决方案?


使用非名称空间感知的方法,并简单地复制属性(包括前缀和标签名称)的简易方法,似乎作品,起初:

$clone = $doc->createElement($ele->tagName); 
foreach ($ele->attributes as $att) { 
    $clone->setAttribute($att->nodeName, $att->value); 
} 

生成的XML外观完全按照预期。但是,当克隆元素再次操作:

$clone->setAttributeNS($officeNS, "office:value-type", "string"); 

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

<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=""> 

,这使得该文件无效。一般来说,我发现混合名称空间和非名称空间的方法调用是不切实际的。

回答

1

这里有一个libxml的常数,它允许以优化负载的命名空间:

$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(); 

输出:

<?xml version="1.0"?> 
<f:foo xmlns:f="urn:foo"> 
    <f:foo> 
    <f:foo> 
    </f:foo> 
    </f:foo> 
</f:foo> 

此作品居多,但我得到了一些无效的结果,如果使用相同的前缀用于同一文档中的不同名称空间。

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

相关问题