C#使用OpenXML复制DOCX文件

时间:2013-04-17 20:16:11

标签: c# .net clone openxml

我正在尝试复制docx文件内容并使用C#中的OpenXML将它们保存在同一文件中

以下是代码:

using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(wordFileNamePath, true))
{
    foreach(OpenXmlElement element in wordDoc.MainDocumentPart.Document.ChildElements)
    {
        OpenXmlElement cloneElement = (OpenXmlElement)element.Clone();
        wordDoc.MainDocumentPart.Document.Append(cloneElement);
    }
    wordDoc.MainDocumentPart.Document.Save();
}

代码工作正常,做我需要的。我的问题是生成的docx文件部分损坏。当我打开文件时,我收到以下两条消息: enter image description here

单击“确定”,然后单击“是”将正常打开文件。但是,文件一直被破坏,直到我'保存为'它(使用相同或不同的名称)。这就是新保存文件的修复方式。

通过使用适用于Microsoft Office的Open XML SDK 2.5生产力工具,我可以验证文件并查看反映的代码。验证文件将产生以下5个错误:

enter image description here

所以我认为我在代码中使用的“Clone”函数会复制元素,因此当它附加到文档时,会发生一些ID重复。

任何想法在复制后获得正确的DOCX文件?任何替代代码都表示赞赏。

2 个答案:

答案 0 :(得分:0)

您的方法存在的问题是它创建了无效的Open XML标记。这就是为什么。

假设您有一个非常简单的Word文档,该文档由以下标记表示:

undefined

在您的<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"> <w:body> <w:p> <w:r> <w:t>First paragraph</w:t> </w:r> </w:p> <w:p> <w:r> <w:t>Second paragraph</w:t> </w:r> </w:p> <w:body> <w:document> 循环中,foreach将是一个仅包含wordDoc.MainDocumentPart.Document.ChildElements元素的单元素列表。因此,您将创建w:body元素的深层克隆并将其附加到w:body。最终的Open XML标记如下:

w:document

上面是一个<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"> <w:body> <w:p> <w:r> <w:t>First paragraph</w:t> </w:r> </w:p> <w:p> <w:r> <w:t>Second paragraph</w:t> </w:r> </w:p> <w:body> <w:body> <w:p> <w:r> <w:t>First paragraph</w:t> </w:r> </w:p> <w:p> <w:r> <w:t>Second paragraph</w:t> </w:r> </w:p> <w:body> <w:document> ,带有两个w:document子元素,这是无效的Open XML标记,因为w:body必须恰好有一个w:document子元素。因此,Word会显示该错误消息。

要解决此问题,无论您何时使用w:body,都需要使用Document.Body。下面的精简示例显示了操作方法。

Document

您将看到我没有显式保存using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(wordFileNamePath, true)) { Body body = wordDoc.MainDocumentPart.Document.Body; IEnumerable<OpenXmlElement> clonedElements = body .Elements() .Select(e => e.CloneNode(true)) .ToList(); body.Append(clonedElements); } ,因为Document语句和默认情况下自动保存这些文档的事实,这并不必要。其次,我在追加之前使用using来实现集合。这是为了避免在枚举同时更改的元素时出现任何问题。

答案 1 :(得分:-1)

为什么不会被破坏?您正在打开文档,获取所有子元素,并将它们写入同一文档。我不确定应该做什么。