Document Comparison

Document Comparison

This guide shows how to compare two runs of text and produce the sequence of edits between them using the Aspose.PDF FOSS text-diff engine for .NET. The entry point for this comparison model is DiffOperation, a single edit tagged with an Operation (Equal, Delete, or Insert), together with the DiffUtils helper class for locating common text and reassembling a diff back into its source and destination text. A separate optimization pass, described in Diff Optimization, canonicalizes raw diff output produced this way before it is rendered or applied.


The Diff Model: Operation and DiffOperation

Operation is the enum that classifies each edit in a diff: Equal marks a run of text that is unchanged, Delete marks a run removed from the source, and Insert marks a run added in the destination. DiffOperation pairs an Operation value with the Text it applies to, and implements IEquatable<DiffOperation> so two edits can be compared for equality.

using Aspose.Pdf.Comparison.Diff;

// A single edit consists of an Operation and the run of text it applies to.
var unchanged = new DiffOperation(Operation.Equal, "Aspose.PDF ");
var removed = new DiffOperation(Operation.Delete, "for .NET Framework");
var added = new DiffOperation(Operation.Insert, "FOSS for .NET");

Console.WriteLine(unchanged.Operation); // Equal
Console.WriteLine(added.Text);          // "FOSS for .NET"

Locating Common Text with DiffUtils

DiffUtils is a static helper class used by the diff engine to find the common prefix and suffix shared by two strings before the differing middle section is diffed. FindCommonStartParts locates the common prefix, and FindCommonEndParts locates the common suffix; an overload of FindCommonEndParts accepts a startIndex so the suffix search can be bounded to text that follows an already-located prefix.

string original = "The quick brown fox";
string revised = "The quick red fox jumps";

var commonStart = DiffUtils.FindCommonStartParts(original, revised);
var commonEnd = DiffUtils.FindCommonEndParts(original, revised);

Reassembling Text from a Diff

Once a diff is expressed as a sequence of DiffOperation values, DiffUtils can reconstruct either side of the comparison: AssemblySourceText rebuilds the original text from the Equal and Delete runs, and AssemblyDestinationText rebuilds the revised text from the Equal and Insert runs.

using System.Collections.Generic;

var diffs = new List<DiffOperation>
{
    new DiffOperation(Operation.Equal, "The quick "),
    new DiffOperation(Operation.Delete, "brown"),
    new DiffOperation(Operation.Insert, "red"),
    new DiffOperation(Operation.Equal, " fox")
};

string sourceText = DiffUtils.AssemblySourceText(diffs);
string destinationText = DiffUtils.AssemblyDestinationText(diffs);

Console.WriteLine(sourceText);      // "The quick brown fox"
Console.WriteLine(destinationText); // "The quick red fox"

Comparing and Reporting Edits

DiffOperation overrides Equals, GetHashCode, and ToString, so edits can be compared for equality or written to logs and test output without extra conversion code.

var a = new DiffOperation(Operation.Equal, "PDF");
var b = new DiffOperation(Operation.Equal, "PDF");

bool same = a.Equals(b); // true - same Operation and Text
Console.WriteLine(a.ToString());

Tips and Best Practices

  • DiffOperation is immutable and implements IEquatable<DiffOperation> — use Equals to compare two edits rather than reference equality.
  • Locate the common prefix with FindCommonStartParts first, then pass its length into the startIndex overload of FindCommonEndParts to avoid a short common prefix being double-counted as part of the suffix.
  • Use AssemblySourceText and AssemblyDestinationText to verify a sequence of DiffOperation values round-trips to the exact original and revised text before you rely on it elsewhere.
  • Treat Operation.Equal runs as no-ops when rendering a visual diff, and only highlight Delete and Insert runs.
  • This engine diffs text, not documents directly — extract the text you want to compare (for example, from a page or document) before building a diff.

Common Issues

IssueCauseFix
AssemblySourceText / AssemblyDestinationText output doesn’t match the originalsThe diffs list is incomplete or its DiffOperation entries are out of orderInclude every edit in the sequence, in the original order the edits occurred
FindCommonEndParts returns an unexpected result on short, similar stringsThe common suffix search overlaps text already matched by FindCommonStartPartsPass the length returned by FindCommonStartParts as the startIndex argument
Equals returns false for edits that look identicalThe Text values differ by whitespace or caseNormalize text (trim / case-fold) before constructing DiffOperation values you intend to compare
Diff output looks noisy or unnecessarily fragmentedRaw DiffOperation sequences are not yet canonicalizedRun the sequence through the optimization pass described in Diff Optimization

FAQ

What does the Diff engine compare?

It compares runs of text and produces a sequence of DiffOperation values describing the edits — unchanged, deleted, or inserted text — needed to turn one string into another.

What edit types does Operation support?

Three: Equal for unchanged text, Delete for text removed from the source, and Insert for text added in the destination.

How do I check whether two edits are the same?

Call Equals on a DiffOperation instance, or compare its Operation and Text properties directly.

Can I get back the original and revised text from a diff?

Yes — pass the list of DiffOperation values to DiffUtils.AssemblySourceText for the original text and DiffUtils.AssemblyDestinationText for the revised text.

Does this page cover merging or cleaning up a diff?

No — canonicalizing a raw diff (merging adjacent runs, sliding edits across equalities) is covered separately in Diff Optimization.


API Reference Summary

Class / MethodDescription
OperationEnum classifying an edit as Equal, Delete, or Insert
DiffOperationA single edit: an Operation paired with the Text it applies to
DiffOperation.OperationThe Operation value for this edit
DiffOperation.TextThe run of text this edit applies to
DiffOperation.EqualsCompares two edits for equality by Operation and Text
DiffOperation.ToStringRenders an edit as a string for logging or display
DiffUtilsStatic helper class with text-diffing utilities
DiffUtils.FindCommonStartPartsFinds the common prefix shared by two strings
DiffUtils.FindCommonEndPartsFinds the common suffix shared by two strings, optionally starting from an index
DiffUtils.AssemblySourceTextReassembles the original text from a list of DiffOperation values
DiffUtils.AssemblyDestinationTextReassembles the revised text from a list of DiffOperation values

See Also