搜索和替换占位符,该占位符已分割为多个<w:t>元素

7

我正在尝试使用Open XML SDK 2.5从.docx模板创建报告。在模板中,我定义了一些占位符,这些占位符将被实际值替换。这些占位符可以在不同的模式下定义,例如

<#Name#>
or
<!#Name#!>
or
#Name#
or
{{Name}}

占位符的模式可以有多种,只要在文本中可以清晰地识别出占位符即可。
我目前面临的问题是,一个占位符常常被分成多个-元素(DocumentFormat.OpenXml.Wordprocessing.Text),这些元素都在一个-元素(DocumentFormat.OpenXml.Wordprocessing.Paragraph)内。以下是一个示例:
<w:p w:rsidR="003137E0" w:rsidRDefault="008C62F1" w:rsidP="00D43D55">
  <w:r>
    <w:t xml:space="preserve">#FirstName# </w:t>
  </w:r>
  <w:r w:rsidR="00C93A70">
    <w:t>#LastName</w:t>
  </w:r>
  <w:r w:rsidR="005F49B7">
    <w:t>#</w:t>
  </w:r>
</w:p>

在这里,占位符#FirstName#很容易识别,因为它在一个<w:t>元素中,但是占位符#LastName#被分成多个<w:t>元素,因此我无法像对文档上的文本一样使用简单的正则表达式。

Regex placeholderRegex = new Regex(@"#[\w]*#");

document.MainDocumentPart.Document.Body.Descendants<Text>().Where(t=> placeholderRegex.IsMatch(t.Text))

我无法控制模板的定义,也不会对用户创建模板的方式施加限制。对于我来说,当一个占位符被拆分成多个<w:t>元素时也不清楚。

下面是另一个使用{{[\w]*}}作为占位符模式的示例。

文本(Docx)

{{Ort}}
And this {{placeholder}} is within the text 

Xml (OpenXML)

<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14">
  <w:body>
    <w:p w:rsidR="007B60F2" w:rsidRDefault="00BB7370" w:rsidP="00D43D55">
      <w:pPr>
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
      </w:pPr>
      <w:r w:rsidRPr="00114EA7">
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
        <w:t>{{</w:t>
      </w:r>
      <w:r w:rsidR="00C93A70" w:rsidRPr="00114EA7">
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
        <w:t>Ort</w:t>
      </w:r>
      <w:r w:rsidR="00114EA7" w:rsidRPr="00114EA7">
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
        <w:t>}}</w:t>
      </w:r>
    </w:p>
    <w:p w:rsidR="00EC3BED" w:rsidRPr="00114EA7" w:rsidRDefault="00C310E0" w:rsidP="00D43D55">
      <w:pPr>
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
      </w:pPr>
      <w:r w:rsidRPr="00114EA7">
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
        <w:t xml:space="preserve">This is a text with a </w:t>
      </w:r>
      <w:r w:rsidR="00A07A5D">
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
        <w:t>{{</w:t>
      </w:r>
      <w:r w:rsidRPr="00114EA7">
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
        <w:t>placeholder</w:t>
      </w:r>
      <w:r w:rsidR="00A07A5D">
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
        <w:t>}</w:t>
      </w:r>
      <w:r w:rsidR="00114EA7" w:rsidRPr="00114EA7">
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
        <w:t>}</w:t>
      </w:r>
      <w:bookmarkStart w:id="0" w:name="_GoBack" />
      <w:bookmarkEnd w:id="0" />
      <w:r w:rsidR="00A07A5D">
        <w:rPr>
          <w:lang w:val="en-US" />
        </w:rPr>
        <w:t>.</w:t>
      </w:r>
    </w:p>
    <w:sectPr w:rsidR="00EC3BED" w:rsidRPr="00114EA7" w:rsidSect="00237721">
      <w:pgSz w:w="11906" w:h="16838" />
      <w:pgMar w:top="1417" w:right="1417" w:bottom="1134" w:left="1417" w:header="708" w:footer="708" w:gutter="0" />
      <w:cols w:space="708" />
      <w:docGrid w:linePitch="360" />
    </w:sectPr>
  </w:body>
</w:document>

那么我的问题现在是,如何使用Open XML SDK搜索和替换占位符,并用值进行替换?SDK中是否有一些功能可以帮助我解决这个问题?还有其他人解决了这个问题并提供了帮助吗?

3个回答

3
我会用类似以下的方法来做这件事(尚未测试,但我认为这会对您有所帮助):

列表 placeHolders = 新列表();

//load xml string
var doc = XDocument.Parse(xml);
//or to load from file use XDocument.Load("path_to_xml_file.xml");

//get all <w:p> element
var wpElements = doc.Root.Elements("w:p");

foreach (var wp in wpElements)
{
    var wrElements = wp.Descendants("w:r");
    foreach (var wr in wrElements)
    {
        var wt = (string)wr.Element("w:t");
        if (wt.IsMatch(@"\w")) { //add the string to placeHolders if word is found 
            placeHolders.Add(wt);
        }
        else
        {
            //if not found a word, add it to the last placeHolder, 
            placeHolder[placeHolder.Count - 1] = placeHolder[placeHolder.Count - 1] + wt;
        }
    }
}

3

2
是的,Microsoft Word应用程序甚至会将单个单词拆分为多个运行/文本元素(出于某种原因)。而且,Open XML SDK功能中没有提供查找/替换功能。但是,您可以为最简单的段落/运行/文本结构创建自己的功能。您需要:
  1. 为所有单词创建一个映射,其中包含每个单词由哪些对应的Run / Text元素组成的信息。
  2. 然后,您将搜索特定单词(例如<#Name#>)的索引,并替换第一个Run / Text元素的内容并删除所有其他元素,除了最后一个元素,它可能是下一个单词的一部分。在这种情况下,您将不得不修复它,以便它只包括该单词的一部分。

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