2016-11-10 77 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庫包含此作業的優化程序。它也允許您更改/定義前綴。

相關問題