我正在使用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
- 我只引用SdtRun
或SdtBlock
。
有没有办法从documentPart
导航到SdtRun
?我已经检查过.Parent
但找不到从OpenXmlElement
到OpenXmlPart
的方法 - 这些方法位于不同的层次结构中。
答案 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);
}
}