动态创建的Word文档中缺少Open XML部件

问题描述 投票:0回答:1

我正在使用Open XML SDK在C#中创建WordprocessingDocument,然后将它们转换为pdf。最初,我是使用Interop将文档保存为PDF格式的,但是现在这不是一个选择。我发现LibreOffice可以转换从cmd调用soffice.exe的文档,使用普通文档我得到了很好的结果。但是,当我用动态文档测试LibreOffice转换器时,该转换器崩溃了。

我复制了其中一个文档,并使用LibreOffice Writer打开了该文档,其结构错误,然后我使用Microsoft Word打开了相同的文档,其结构也很好。最后,我用Microsoft Word将其保存,并按如下所示将两个文档作为ZIP文件打开:

这是好人:

Good document structure

这是不好的一个:

Bad document structure

[我注意到,当我将文档保存在Microsoft Word中时,出现了这些Open XML部分(在此问题的较早版本中称为“文件”)。当我打开以前用Microsoft Word在LibreOffice中保存的文档时,该文档又可以了。

因此,有没有一种方法可以在不打开Microsoft Word的情况下生成这些Open XML部件(在Word文档中)?

我使用以下代码(检查它是否正在创建所有文件):

        using (MemoryStream mem = new MemoryStream())
        {
            // Create Document
            using (WordprocessingDocument wordDocument =
                WordprocessingDocument.Create(mem, WordprocessingDocumentType.Document, true))
            {
                // Add a main document part. 
                MainDocumentPart mainPart = wordDocument.AddMainDocumentPart();

                // Create the document structure and add some text.
                mainPart.Document = new Document();
                Body docBody = new Body();

                // Add your docx content here
                CreateParagraph(docBody);
                CreateStyledParagraph(docBody);
                CreateTable(docBody);
                CreateList(docBody);

                Paragraph pImg = new Paragraph();
                ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
                string imgPath = "https://cdn.pixabay.com/photo/2019/11/15/05/23/dog-4627679_960_720.png";
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(imgPath);
                req.UseDefaultCredentials = true;
                req.PreAuthenticate = true;
                req.Credentials = CredentialCache.DefaultCredentials;
                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                imagePart.FeedData(resp.GetResponseStream());

                // 1500000 and 1092000 are img width and height
                Run rImg = new Run(DrawingManager(mainPart.GetIdOfPart(imagePart), "PictureName", 1500000, 1092000, string.Empty));
                pImg.Append(rImg);
                docBody.Append(pImg);

                Paragraph pLink = new Paragraph();
                // For the mainpart see above
                pLink.Append(HyperLinkManager("http://YourLink", "My awesome link", mainPart));
                docBody.Append(pLink);

                mainPart.Document.Append(docBody);
                mainPart.Document.Save();
                wordDocument.Close();
            }

            result = Convert.ToBase64String(mem.ToArray());
        }

上面的代码创建具有以下结构的名为Result.docx的Word文档:

Result.docx structure

但是没有其他任何Open XML部分(例如app.xmlstyles.xml

c# openxml libreoffice
1个回答
0
投票

您需要在以下两者之间有所作为:

  • Open XML标准及其在WordprocessingDocument和[]上的最低要求>
  • 由Microsoft Word或其他应用程序创建的“最小”文档。
  • 根据标准,最小的WordprocessingDocument只需要具有以下内容的主文档部分(MainDocumentPartdocument.xml):

<w:document xmlns:w="...">
  <w:body>
    <w:p />
  </w:body>
</w:document>

仅当您具有样式或编号时才需要StyleDefinitionsPartstyles.xml)或NumberingDefintionsPartnumbering.xml)等其他部分,在这种情况下,您必须在代码中显式创建它们。

接下来,查看您的示例代码,看来您正在创建:

  1. 引用样式的段落(请参见CreateStyledParagraph(docBody)),必须在StyleDefinitionsPartstyles.xml)中定义;和
  2. 编号列表(例如CreateList(docBody)),必须在NumberingDefinitionsPartnumbering.xml)中定义。
  3. 但是,您的代码既不会创建StyleDefinitionsPart也不会创建NumberingDefintionsPart,这意味着您的文档可能不是有效的Open XML文档。

现在,Word非常宽容,并且无声地修复了各种问题,而忽略了您的Open XML标记的某些部分(例如,您可能分配给段落的样式)。

相反,根据LibreOffice的容错程度,无效的Open XML标记可能会导致崩溃。例如,如果LibreOffice在您的StyleDefinitionsPart中找到类似于<w:pStyle w:val="MyStyleName" />的元素时只是假设w:document存在,然后在询问null时不检查是否获得了StyleDefinitionsPart引用,则可以崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.