C# 打开XML-在文档模板中查找并替换多个占位符
我知道有很多关于这个话题的帖子,但是似乎没有一篇是针对这个问题的。 我正在尝试制作一个小型通用文档生成器POC。 我正在使用开放式XML 代码如下所示:C# 打开XML-在文档模板中查找并替换多个占位符,c#,ms-word,openxml,openxml-sdk,C#,Ms Word,Openxml,Openxml Sdk,我知道有很多关于这个话题的帖子,但是似乎没有一篇是针对这个问题的。 我正在尝试制作一个小型通用文档生成器POC。 我正在使用开放式XML 代码如下所示: private static void ReplacePlaceholders<T>(string templateDocumentPath, T templateObject) where T : class { using (var templateDocument = Wordp
private static void ReplacePlaceholders<T>(string templateDocumentPath, T templateObject)
where T : class
{
using (var templateDocument = WordprocessingDocument.Open(templateDocumentPath, true))
{
string templateDocumentText = null;
using (var streamReader = new StreamReader(templateDocument.MainDocumentPart.GetStream()))
{
templateDocumentText = streamReader.ReadToEnd();
}
var props = templateObject.GetType().GetProperties();
foreach (var prop in props)
{
var regexText = new Regex($"{prop.Name}");
templateDocumentText =
regexText.Replace(templateDocumentText, prop.GetValue(templateObject).ToString());
}
using var streamWriter = new StreamWriter(templateDocument.MainDocumentPart.GetStream(FileMode.Create));
streamWriter.Write(templateDocumentText);
}
}
private静态void replacep占位符(字符串templateDocumentPath,T templateObject)
T:在哪里上课
{
使用(var templateDocument=WordprocessingDocument.Open(templateDocumentPath,true))
{
字符串templateDocumentText=null;
使用(var streamReader=newstreamreader(templateDocument.MainDocumentPart.GetStream())
{
templateDocumentText=streamReader.ReadToEnd();
}
var props=templateObject.GetType().GetProperties();
foreach(道具中的var道具)
{
var regexText=newregex($“{prop.Name}”);
模板文档文本=
Replace(templateDocumentText,prop.GetValue(templateObject.ToString());
}
使用var streamWriter=newstreamwriter(templateDocument.MainDocumentPart.GetStream(FileMode.Create));
streamWriter.Write(templateDocumentText);
}
}
代码按预期工作。
问题如下:
StreamReader.ReadToEnd()在标记之间拆分我的占位符,因此我的替换方法只替换不会被拆分的单词
在本例中,我的代码将搜索单词“Firstname”,但会找到“irstname”,因此不会替换它
有没有办法逐字扫描整个.docx并替换它们
(编辑)部分解决方案/解决方案我发现: -我注意到您必须立即在.docx中写入占位符(无需重新编辑)。例如,如果我写“firstname”,然后返回并将其修改为“firstname”,它会将单词拆分为“F”“irstname”。如果不进行编辑,它将不会被丢弃。TLDR 简而言之,问题的解决方案是使用的
OpenXmlRegex
实用程序类,如下面的单元测试所示
为什么?
使用开放式XML,您可以用多种方式表示相同的文本。如果MicrosoftWord参与创建开放式XML标记,那么为生成该文本所做的编辑将发挥重要作用。这是因为Word跟踪在哪个编辑会话中进行的编辑。因此,例如,以下极端场景中显示的w:p
(段落
)元素表示完全相同的文本。这两个例子之间的任何事情都是可能的,所以任何真正的解决方案都必须能够解决这个问题
极端情况1:单个w:r
和w:t
元素
以下标记非常简单:
名字
极端场景2:单个字符w:r
和w:t
元素
虽然您通常找不到以下标记,但它代表了理论上的极端,每个字符都有自己的w:r
和w:t
元素
F
我
R
s
T
N
A.
M
E
你可能会问,如果这个极端的例子在实践中没有出现,我为什么要使用它?答案是,它在解决方案中起着至关重要的作用,以防您想要推出自己的解决方案
如何推出自己的?
要正确操作,您必须:
w:p
)的运行(w:r
)转换为单字符运行(即,w:r
元素,每个元素有一个单字符w:t
或一个w:sym
),保留运行属性(w:rPr
)李>
w:rPr
),请将这些产生的运行转换回表示文本及其格式所需的最少数量的“合并”运行w:sdt
)。啊,顺便说一下,不要忘记修订标记,比如w:ins
和w:del
为什么不自己滚呢?
好消息是你不必自己动手。Eric White的OpenXmlRegex
实用程序类实现了上述算法(以及更多)。我已经成功地将其应用于大规模的RFP和承包方案中,并为此做出了贡献
如何使用OPEN-XML-POWERTOOLS?
在本节中,我将演示如何使用OpenXMLPowerTools将占位符文本“Firstname”(如问题中所示)替换为各种名字(在示例输出文档中使用“Bernie”)
输入文件样本
让我们首先看看下面的示例文档,它是由稍后显示的单元测试创建的。请注意,我们已经格式化了运行和符号。正如问题中所述,占位符“Firstname”分为两个运行,即“F”和“irstname”
你好
F
域名
所需输出文档
以下是将“Firstname”替换为“Bernie”后生成的文档,前提是操作正确。请注意,格式是保留的,我们没有丢失符号
你好
伯尼
给我们看看