如何使用OpenXML SDK替换段落文本

11
我正在使用 .Net OpenXml SDK 2.0 解析一些 Openxml Word 文档。作为处理的一部分,我需要用其他句子替换某些句子。在迭代段落时,我知道何时找到需要替换的内容,但我不知道如何进行替换。
例如,假设我需要将句子“a contract exclusively for construction work that is not building work.”替换为以下 SharePoint 可重复使用内容的 HTML 片段: a contract exclusively for construction work that is not building work. 注:我已经通过 XSLT 实现了 docx 到 HTML 的转换,因此这个阶段不是问题。
段落节点的 InnerText 属性给我正确的文本,但是 InnerText 属性本身无法设置。因此,Regex.Match(currentParagraph.InnerText, currentString).Success 返回 true,并告诉我当前段落包含我想要的文本。
正如我所说,InnerText 本身无法设置,因此我尝试使用下面给出的 outerxml 创建一个新段落。
string modifiedOuterxml = Regex.Replace(currentParagraph.OuterXml, currentString, reusableContentString);
OpenXmlElement parent = currentParagraph.Parent;
Paragraph modifiedParagraph = new Paragraph(modifiedOuterxml);
parent.ReplaceChild<Paragraph>(modifiedParagraph, currentParagraph);

虽然我对格式并不太关心,而且似乎也没有什么问题,但outerXML似乎有一些额外的元素,这些元素会破坏正则表达式。

..."16" /><w:lang w:val="en-AU" /></w:rPr><w:t>a</w:t></w:r><w:proofErr w:type="gramEnd" /> <w:r w:rsidRPr="00C73B58"><w:rPr><w:sz w:val="16" /><w:szCs w:val="16" /><w:lang w:val="en-AU" /></w:rPr><w:t xml:space="preserve"> 专门为非建筑工作的施工工作签订合同。</w:t></w:r></w:p>

总之,我该如何用其他文本替换OpenXml段落中的文本呢?即使牺牲一些格式。

3个回答

17

我自己解决了。关键是要删除所有的运行并在当前段落中创建新的运行。

string modifiedString = Regex.Replace(currentParagraph.InnerText, currentString, reusableContentString);
currentParagraph.RemoveAllChildren<Run>();
currentParagraph.AppendChild<Run>(new Run(new Text(modifiedString)));

4

所有段落内部都有一个文本元素,因此您只需要找到文本元素并更新其文本即可,例如:

var text = part.RootElement.Descendants<Text>().FirstOrDefault(e=>e.Text == "a contract exclusively for construction work that is not building work.");
if(text != null)
{
    text.Text = "New text here";
}
mainPart.Document.Save();

1
这��一种很好的方法,可以在不丢失样式的情况下修改文本。我刚刚测试了从表格到其行,再到行中的单元格,然后到单元格中的段落,最后使用 if (var text = paragraph.Descendants<Text>().FirstOrDefault(e => e.Text == "Company Name"); 获取文本。任何想要简单替换文本的人都应该能够使用这种方法。 - Goal Man
如果要替换的文本在单个Run中,则此方法可以正常工作。但是,我需要替换用方括号标记的标签。Word似乎随机地将括号包含在Run元素中 - 因此有时我会有一个包含文本“[myTag]”的单个Run,有时我会有3个Runs:“ [”,“ myTag”和“]”。 有什么想法如何解决这个问题吗? - user2727133

1

使用 RemoveAllChildren() 然后 AppendChild() 会失去所有样式元素,除非您再花费大量代码将它们放回。Nick Hoang 和 Goal Man 的方法更好,不会失去任何样式。

如果您在模板 docx 中使用一个被广泛接受的符号作为占位符,例如 '#' 或 '|',那么替换文本将是最佳选择。

var tag = pghBillAmount.Descendants<WordOpenXML.Text>().FirstOrDefault(p => p.Text == "#");
if (tag != null)
{
    tag.Text = order.BillAmount.ToString("C2");
}

您的加粗或高亮样式等仍将保留。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接