You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OpenXml WmlComparer对比含不同法律样式编号文档的异常问题

问题:OpenXml WmlComparer对比Word文档丢失法律样式编号及删除线格式

使用C#的OpenXml库,通过WmlComparer.Compare方法对比两个Word文档时,多数场景功能正常,但遇到法律样式编号时出现以下问题:

  • 当其中一个文档包含法律样式编号,另一个文档不含时,生成的对比文档会完全丢失法律编号
  • 未为不匹配的编号添加删除线格式
  • 已配置基础的WmlComparerSettings参数,但无法解决上述问题

相关代码

WmlComparerSettings settings = new WmlComparerSettings
{
    AuthorForRevisions = author,
    DetailThreshold = 0
};

var originalDoc = new WmlDocument(originalPath.ToString());
var revisedDoc = new WmlDocument(revisedPath.ToString());

WmlDocument comparedDoc = WmlComparer.Compare(originalDoc, revisedDoc, settings);

解决方案

1. 手动合并编号样式定义

WmlComparer默认不会完整保留两个文档的编号库差异,需要手动复制缺失的编号样式到对比文档中:

  • 分别提取原始文档和修订文档的NumberingDefinitionsPart
  • 将其中一方存在但对比文档缺失的编号实例复制进去,确保编号ID对应正确
// 获取原始与修订文档的编号部分
var originalNumbering = originalDoc.Document.MainDocumentPart.NumberingDefinitionsPart;
var revisedNumbering = revisedDoc.Document.MainDocumentPart.NumberingDefinitionsPart;

// 确保对比文档有编号部分
var comparedNumbering = comparedDoc.Document.MainDocumentPart.NumberingDefinitionsPart;
if (comparedNumbering == null)
{
    comparedNumbering = comparedDoc.Document.MainDocumentPart.AddNewPart<NumberingDefinitionsPart>();
}

// 复制原始文档中缺失的编号实例
foreach (var numInstance in originalNumbering.Numbering.Elements<NumberingInstance>())
{
    if (!comparedNumbering.Numbering.Elements<NumberingInstance>().Any(n => n.NumberID == numInstance.NumberID))
    {
        comparedNumbering.Numbering.Append(numInstance.CloneNode(true));
    }
}

// 复制修订文档中缺失的编号实例
foreach (var numInstance in revisedNumbering.Numbering.Elements<NumberingInstance>())
{
    if (!comparedNumbering.Numbering.Elements<NumberingInstance>().Any(n => n.NumberID == numInstance.NumberID))
    {
        comparedNumbering.Numbering.Append(numInstance.CloneNode(true));
    }
}

2. 手动添加编号的修订标记

针对编号存在/缺失的差异,手动遍历段落并添加删除线或插入标记:

  • 对比原始与修订文档段落的编号ID
  • 对原始有编号、修订无编号的段落,在对比文档中为编号添加删除线修订
  • 对原始无编号、修订有编号的段落,添加插入标记
var originalParagraphs = originalDoc.Document.MainDocumentPart.Document.Body.Elements<Paragraph>().ToList();
var revisedParagraphs = revisedDoc.Document.MainDocumentPart.Document.Body.Elements<Paragraph>().ToList();
var comparedBody = comparedDoc.Document.MainDocumentPart.Document.Body;

for (int i = 0; i < Math.Min(originalParagraphs.Count, revisedParagraphs.Count); i++)
{
    var origPara = originalParagraphs[i];
    var revPara = revisedParagraphs[i];
    var comparedPara = comparedBody.Elements<Paragraph>().ElementAt(i);

    var origNumId = origPara.ParagraphProperties?.NumberingProperties?.NumberingId?.Val;
    var revNumId = revPara.ParagraphProperties?.NumberingProperties?.NumberingId?.Val;

    // 原始有编号,修订无编号:添加删除线标记
    if (origNumId != null && revNumId == null)
    {
        if (origPara.ParagraphProperties?.NumberingProperties != null)
        {
            var deleteMark = new Delete();
            deleteMark.Append(origPara.ParagraphProperties.NumberingProperties.CloneNode(true));
            deleteMark.Author = settings.AuthorForRevisions;
            deleteMark.Date = DateTime.Now;

            comparedPara.ParagraphProperties?.InsertBefore(deleteMark, comparedPara.ParagraphProperties.NumberingProperties);
            comparedPara.ParagraphProperties?.RemoveChild(comparedPara.ParagraphProperties.NumberingProperties);
        }
    }
    // 原始无编号,修订有编号:添加插入标记
    else if (origNumId == null && revNumId != null)
    {
        if (revPara.ParagraphProperties?.NumberingProperties != null)
        {
            var insertMark = new Insert();
            insertMark.Append(revPara.ParagraphProperties.NumberingProperties.CloneNode(true));
            insertMark.Author = settings.AuthorForRevisions;
            insertMark.Date = DateTime.Now;

            comparedPara.ParagraphProperties?.Append(insertMark);
        }
    }
}

3. 优化对比器细节阈值

调整DetailThreshold参数,提高对比器对格式差异的识别精度:

WmlComparerSettings settings = new WmlComparerSettings
{
    AuthorForRevisions = author,
    DetailThreshold = 1 // 提升细节阈值,增强格式差异识别
};

内容的提问来源于stack exchange,提问作者yatin tripathi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:54:51