在OpenXML中使用Word文档时从OpenXmlElement获取DocumentPart

时间:2017-08-17 12:15:16

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

我正在使用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

有没有办法从documentPart导航到SdtRun?我已经检查过.Parent但找不到从OpenXmlElementOpenXmlPart的方法 - 这些方法位于不同的层次结构中。

2 个答案:

答案 0 :(得分:2)

我推荐以下方法。它使用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;
    }

答案 1 :(得分:1)

通过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);
    }
}