在 C# 中的 OpenXml SDK 中使用 MergeField FieldCodes 时,为什么字段代码会消失或碎片化?

The*_*tor 5 c# openxml-sdk

我已经成功地使用 C# OpenXml SDK(来自 NuGet 的非官方 Microsoft Package 2.5)一段时间了,但最近注意到以下代码行返回不同的结果,具体取决于 Microsoft Word 在文件获取时的心情保存:

var fields = document.Descendants<FieldCode>();
Run Code Online (Sandbox Code Playgroud)

据我所知,在首先创建文档时(在 Windows 8.1 上使用 Word 2013),如果您使用 Insert->QuickParts->Field 并从 Field names 左侧窗格中选择 MergeField,然后提供一个 Field name在字段属性中,然后单击“确定”,然后字段代码就如我所料地正确保存在文档中。

然后,当使用上述代码行时,我将收到 1 个字段的字段代码计数。如果我随后编辑此文档(甚至不理会这个字段),随后的保存可能意味着我的查询中不再返回此字段代码。

另一种同样好奇的情况是,当我看到 FieldCode 节点拆分为多个项目时。所以,而不是看到说:

" MERGEFIELD  Author  \\* MERGEFORMAT "
Run Code Online (Sandbox Code Playgroud)

作为节点名称,我将看到:

" MERGEFIELD  Aut"
"hor  \\* MERGEFORMAT"
Run Code Online (Sandbox Code Playgroud)

拆分为两个 FieldCode 节点值。我不知道为什么会这样,但它确实让我匹配节点的能力更加令人兴奋。这是预期的行为吗?一个已知的错误?我真的不想打开原始 xml 并编辑此文档才能工作,直到我明白发生了什么。非常感谢大家。

Jam*_*ass 3

Word 经常会出于我不明白的原因将文本拆分为多个文本。当搜索、比较、整理等时,我们使用将多个运行合并为单个文本运行的方法对正文进行预处理。

    /// <summary>
    /// Combines the identical runs.
    /// </summary>
    /// <param name="body">The body.</param>
    public static void CombineIdenticalRuns(W.Body body)
    {

        List<W.Run> runsToRemove = new List<W.Run>();

        foreach (W.Paragraph para in body.Descendants<W.Paragraph>())
        {
            List<W.Run> runs = para.Elements<W.Run>().ToList();
            for (int i = runs.Count - 2; i >= 0; i--)
            {
                W.Text text1 = runs[i].GetFirstChild<W.Text>();
                W.Text text2 = runs[i + 1].GetFirstChild<W.Text>();
                if (text1 != null && text2 != null)
                {
                    string rPr1 = "";
                    string rPr2 = "";
                    if (runs[i].RunProperties != null) rPr1 = runs[i].RunProperties.OuterXml;
                    if (runs[i + 1].RunProperties != null) rPr2 = runs[i + 1].RunProperties.OuterXml;
                    if (rPr1 == rPr2)
                    {
                        text1.Text += text2.Text;
                        runsToRemove.Add(runs[i + 1]);
                    }
                }
            }
        }
        foreach (W.Run run in runsToRemove)
        {
            run.Remove();
        }
    }
Run Code Online (Sandbox Code Playgroud)