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
DiffOperationis immutable and implementsIEquatable<DiffOperation>— useEqualsto compare two edits rather than reference equality.- Locate the common prefix with
FindCommonStartPartsfirst, then pass its length into thestartIndexoverload ofFindCommonEndPartsto avoid a short common prefix being double-counted as part of the suffix. - Use
AssemblySourceTextandAssemblyDestinationTextto verify a sequence ofDiffOperationvalues round-trips to the exact original and revised text before you rely on it elsewhere. - Treat
Operation.Equalruns as no-ops when rendering a visual diff, and only highlightDeleteandInsertruns. - 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
| Issue | Cause | Fix |
|---|---|---|
AssemblySourceText / AssemblyDestinationText output doesn’t match the originals | The diffs list is incomplete or its DiffOperation entries are out of order | Include every edit in the sequence, in the original order the edits occurred |
FindCommonEndParts returns an unexpected result on short, similar strings | The common suffix search overlaps text already matched by FindCommonStartParts | Pass the length returned by FindCommonStartParts as the startIndex argument |
Equals returns false for edits that look identical | The Text values differ by whitespace or case | Normalize text (trim / case-fold) before constructing DiffOperation values you intend to compare |
| Diff output looks noisy or unnecessarily fragmented | Raw DiffOperation sequences are not yet canonicalized | Run 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 / Method | Description |
|---|---|
Operation | Enum classifying an edit as Equal, Delete, or Insert |
DiffOperation | A single edit: an Operation paired with the Text it applies to |
DiffOperation.Operation | The Operation value for this edit |
DiffOperation.Text | The run of text this edit applies to |
DiffOperation.Equals | Compares two edits for equality by Operation and Text |
DiffOperation.ToString | Renders an edit as a string for logging or display |
DiffUtils | Static helper class with text-diffing utilities |
DiffUtils.FindCommonStartParts | Finds the common prefix shared by two strings |
DiffUtils.FindCommonEndParts | Finds the common suffix shared by two strings, optionally starting from an index |
DiffUtils.AssemblySourceText | Reassembles the original text from a list of DiffOperation values |
DiffUtils.AssemblyDestinationText | Reassembles the revised text from a list of DiffOperation values |