Open XML Power Tools识别段落索引

本文关键字:段落 索引 识别 Tools XML Power Open | 更新日期: 2023-09-27 18:00:09

我在合并具有特定位置标头的复杂文档时遇到问题。

这里有一个例子:

var letterhead = @"C:'Users'dheale'Desktop'Word Docs'TESTING'StandardLetterhead.DOCX";
var blackrule = @"C:'Users'dheale'Desktop'Word Docs'TESTING'NJBlackrule.DOCX";
var asb = @"C:'Users'dheale'Desktop'Word Docs'TESTING'asb.DOCX";
var outDoc = @"C:'Users'dheale'Desktop'Word Docs'TESTING'out.DOCX";
var sources = new List<Source>
{
    new Source(new WmlDocument(asb), 0, 80, false),
    new Source(new WmlDocument(letterhead), true),
    new Source(new WmlDocument(asb), 80,120, false),
    new Source(new WmlDocument(blackrule), true),
    new Source(new WmlDocument(asb), 200, false),
    new Source(new WmlDocument(letterhead), true)
};
var doc = DocumentBuilder.BuildDocument(sources);

我的问题是试图弄清楚段落索引是什么。原始文档有标签来标识模板应该放在哪里。

目前,为了获得ID,我正在做以下操作:

var ParagraphIndex = wordDoc.MainDocumentPart.Document.Body.ChildElements
    .Where(w => w.XmlQualifiedName.Name == "p").ToList()
    .FindIndex(f => f.InnerXml.Contains(templateTag));

然而,文档越长,这个索引就越偏离

有没有更好、更准确的方法来获取段落索引?

Open XML Power Tools识别段落索引

为什么不获取带有标记的段落,然后在其后面插入内容?

var searchedParagraph = wordDoc.MainDocumentPart.Document.Body.ChildElements
    .Where(w => w.XmlQualifiedName.Name == "p")
    .FirstOrDefault(f => f.InnerXml.Contains(templateTag));
if (searchedParagraph != null) {
   OpenXmlElement parent = searchedParagraph.Parent;
   //Add Code here to create your paragraphWithContent
   ....
   //End paragraphWithContent 
   parent.InsertAfter(paragraphWithContent, searchedParagraph);
}

像这样的东西。

我不确定这是否正是你遇到的问题,但我试图做一些非常类似的事情(检测Word文档中由某个标记组成的段落,并用新的部分替换它们),但遇到了一个非常类似的问题。

似乎对我有效的是迭代正文的所有元素,无论它们是否是段落。对于每个元素,将计数器增加1以跟踪我们在文档中的位置。如果我们在一个段落中,请检查中的标记,将段落替换为其自己的部分(在我的情况下,使用Open XML Power Tools DocumentBuilder。)

伪码:

foreach (var element in templateWpd.MainDocumentPart.RootElement.Elements<Body>().Single().Elements())
{
    if (element is Paragraph p && p.InnerText == "MyTagToReplace")
    {
        if (withinSource)
        {
            var count = currentSourceEnd - currentSourceStart + 1;
            sources.Add(new Source(templateWml, currentSourceStart, count, true));
            withinSource = false;
        }
        sources.Add(new Source(targetProse));
    }        
    else
    {
        if (withinSource)
        {
            currentSourceEnd = i;
        }
        else
        {
            withinSource = true;
            currentSourceStart = i;
            currentSourceEnd = i;
        }
    }
    i++;
}
if (withinSource)
{
    sources.Add(new Source(templateWml, currentSourceStart, true));
    withinSource = false;
}