【问题标题】:Get DocumentPart from OpenXmlElement when working with Word document in OpenXML在 OpenXML 中处理 Word 文档时从 OpenXmlElement 获取 DocumentPart
【发布时间】:2017-08-20 19:34:42
【问题描述】:

我正在使用 OpenXML API 修改 docx 模板并遇到问题。

我需要将图像插入到某个位置 - 该位置由 Content Controll 元素定义,该元素可以位于文档的主要部分、页脚的页眉中。

我得到这样的内容控制:

static IEnumerable<TElement> GetDecendants<TElement>(OpenXmlPart part) where TElement : OpenXmlElement
{
    var result = part.RootElement
        .Descendants()
        .OfType<TElement>();

    return result;
}

稍后我需要通过这个将图像插入到文档的正确部分

internal static OpenXmlElement InsertImage(OpenXmlPart documentPart, Stream stream, string fileName, int imageWidth, int imageHeight)
{
    // actual implementation that is tested and works
}

现在我的问题是,当我发现需要用图像替换的 ContentControl 元素时,我没有对 documentPart 的引用 - 我只有 SdtRunSdtBlock 的引用。

有没有办法从SdtRun 导航到documentPart?我检查了.Parent,但找不到从OpenXmlElementOpenXmlPart 的方法——它们位于不同的层次结构中。

【问题讨论】:

    标签: c# ms-word openxml openxml-sdk


    【解决方案1】:

    我推荐以下方法。它使用Ancestor 来避免recursion 并利用C# 6 中的短路Null-conditional Operators

        internal static OpenXmlPart GetMainDocumentPart(OpenXmlElement xmlElement)
        {
            return
            xmlElement?.Ancestors<Document>()?.FirstOrDefault()?.MainDocumentPart as OpenXmlPart ??
            xmlElement?.Ancestors<Footer>()?.FirstOrDefault()?.FooterPart as OpenXmlPart ??
            xmlElement?.Ancestors<Header>()?.FirstOrDefault()?.HeaderPart as OpenXmlPart;
        }
    

    【讨论】:

    • 哇!这是一大堆问号!我回去工作的时候去看看。谢谢!
    • 这通常有效。但是当xmlElementHeaderDocumentFooter 时失败 - 它没有相同类型的祖先。但是,总体思路和将我指向Ancestors&lt;&gt;()(我以前不知道的方法)很好
    • 实际上HeaderFooterDocument 都是OpenXmlPart 而不是OpenXmlElement,所以用它们调用这个方法甚至不会编译,更不用说运行了。我认为这种方法应该适合你。
    • 但是我下面的代码编译和HeaderFooterDocument都是OpenXmlElement不是部分。在 GitHub 上的任何地方都找不到源代码,但我已经看到它被反编译了。
    • 你是对的。您的代码确实可以编译。我上一条评论不正确 - 他们确实是 OpenXmlElements -
    【解决方案2】:

    浏览了 OpenXML 的源代码后,我找到了一种可以满足我需要的方法。只有它被标记为internal,我无法在我的代码中使用它。

    所以我想出了这个:

    using DocumentFormat.OpenXml;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Wordprocessing;
    using System;
    
    
    internal static class XmlElementHelpers
    {
        internal static OpenXmlPart GetDocumentPart(this OpenXmlElement xmlElement)
        {
            if (xmlElement == null)
            {
                return null;
            }
            if (xmlElement is Document document)
            {
                return document.MainDocumentPart;
            }
    
            if (xmlElement is Header header)
            {
                return header.HeaderPart;
            }
    
            if (xmlElement is Footer footer)
            {
                return footer.FooterPart;
            }
    
            return GetDocumentPart(xmlElement.Parent);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      • 2015-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多