Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 打开XML-在文档模板中查找并替换多个占位符_C#_Ms Word_Openxml_Openxml Sdk - Fatal编程技术网

C# 打开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

我知道有很多关于这个话题的帖子,但是似乎没有一篇是针对这个问题的。 我正在尝试制作一个小型通用文档生成器POC。 我正在使用开放式XML

代码如下所示:

   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”后生成的文档,前提是操作正确。请注意,格式是保留的,我们没有丢失符号

    
    你好
    伯尼
    
    给我们看看