This repository demonstrates how to extract, compare, and report metadata differences between two versions of a document using GroupDocs.Metadata for .NET. Whether you are performing legal e‑discovery or auditing document revisions, these examples provide practical solutions for precise metadata analysis.
This repository addresses the following use cases:
- Legal compliance auditing: Identify unauthorized changes in document ownership across versions.
- Forensic document analysis: Detect hidden revision activity such as edit timestamps and author swaps.
- Automated compliance reporting: Generate CSV or JSON audit logs for regulatory review.
- Version control integration: Compare metadata programmatically within CI pipelines.
In many enterprise workflows, developers need to verify that document metadata has not been tampered with during version updates. However, manually inspecting properties in Word or PDF files is error‑prone and does not scale. Additionally, extracting the full set of built‑in and custom properties requires low‑level parsing that most SDKs hide behind complex APIs. GroupDocs.Metadata addresses these challenges by providing a unified, high‑level interface for reading and comparing metadata across document formats.
- ❌ Manual property inspection is time‑consuming and inconsistent.
- ❌ Detecting subtle ownership changes (Author, LastSavedBy) often requires custom code.
- ❌ Auditing revision timestamps and edit counts is not exposed in standard UI tools.
- ❌ Exporting diff results into analysis‑ready formats (CSV/JSON) demands extra serialization logic.
GroupDocs.Metadata provides a comprehensive solution for metadata comparison in document versioning. By leveraging its fluent API, developers can extract every property, compute structured diffs, and serialize results for downstream processing. Key capabilities include:
✅ Full property extraction – Reads all built‑in and custom metadata fields across supported formats. ✅ Structured diff generation – Categorizes added, removed, and changed properties into a clear object model. ✅ Ownership change detection – Focuses on identity‑bearing tags such as Author and Company. ✅ Revision activity analysis – Highlights changes in RevisionNumber, TotalEditingTime, and LastPrinted. ✅ Export to CSV/JSON – Produces audit‑ready reports that integrate with Excel, SIEMs, or data warehouses.
Here's a typical workflow for implementing Compare Metadata Between Document Versions:
- Extract metadata: Load each document version and collect all properties into dictionaries.
- Compute diff: Compare the two dictionaries to identify added, removed, and changed entries.
- Detect ownership changes: Filter diff results for author‑related tags.
- Analyze revision history: Isolate time‑based properties and calculate deltas.
- Export report: Serialize the diff to CSV or JSON for auditing.
To use these examples, you'll need:
- .NET 6.0: The project targets .NET 6 runtime.
- GroupDocs.Metadata NuGet package: Version 23.10 (released Oct 2023) is referenced in the project file.
- Temporary license key: Obtain a 30‑day trial key from the Temporary License badge above.
compare-metadata-between-document-versions/
│
├── Methods
├── resources
├── CompareMetadataVersions.csproj
├── Program.cs
├── document-v1.docx
├── document-v2.docx
├── CompareMetadataSets.cs
├── DetectOwnershipChanges.cs
├── DetectRevisionHistory.cs
├── ExportDiffToCsv.cs
├── ExportDiffToJson.cs
└── ExtractAllMetadata.cs
File Organization:
- Methods – Contains helper classes that perform extraction, diffing, and export operations.
- resources – Holds sample Word documents (v1 and v2) used by the demo.
- CompareMetadataVersions.csproj – Project definition with NuGet dependencies.
- Program.cs – Entry point that orchestrates the workflow.
- CompareMetadataSets.cs – Implements full metadata comparison between two versions.
- DetectOwnershipChanges.cs – Isolates and reports changes in author‑related properties.
- DetectRevisionHistory.cs – Analyzes revision‑related metadata such as edit timestamps.
- ExportDiffToCsv.cs – Writes the diff to a CSV file for Excel consumption.
- ExportDiffToJson.cs – Writes the diff to a JSON file for API integration.
- ExtractAllMetadata.cs – Core routine that extracts every accessible metadata property.
When to Use: When you need to audit changes between document revisions for compliance or legal review.
This example extracts all metadata from two document versions, computes a structured diff, and categorizes added, removed, and changed properties.
var v1 = ExtractAllMetadata.Run(pathV1);
var v2 = ExtractAllMetadata.Run(pathV2);
var diff = new MetadataDiff();
foreach (var kvp in v2)
{
if (!v1.ContainsKey(kvp.Key))
{
diff.Added[kvp.Key] = kvp.Value;
}
else if (v1[kvp.Key] != kvp.Value)
{
diff.Changed[kvp.Key] = (v1[kvp.Key], kvp.Value);
}
}
foreach (var kvp in v1)
{
if (!v2.ContainsKey(kvp.Key))
{
diff.Removed[kvp.Key] = kvp.Value;
}
}
return diff;What This Solves: Provides a programmatic way to see exactly which metadata fields changed, eliminating manual inspection.
Real-World Application: Legal teams can generate audit trails that pinpoint ownership or property modifications across document versions.
When to Use: When you must verify that the document's author, manager, or company information has not been altered.
The snippet isolates identity‑bearing tags (Author, LastSavedBy, Manager, Company) from two versions and reports any differences.
var v1Values = GetOwnershipProperties(pathV1);
var v2Values = GetOwnershipProperties(pathV2);
var changes = new Dictionary<string, (string, string)>();
var allKeys = new HashSet<string>(v1Values.Keys);
foreach (var key in v2Values.Keys) allKeys.Add(key);
foreach (var key in allKeys)
{
var oldV = v1Values.TryGetValue(key, out var o) ? o : "<missing>";
var newV = v2Values.TryGetValue(key, out var n) ? n : "<missing>";
if (oldV != newV)
{
changes[key] = (oldV, newV);
}
}
return changes;What This Solves: Highlights any shift in ownership metadata, a key indicator of potential document tampering.
Real-World Application: Forensic auditors can quickly surface author changes that may affect document authenticity.
When to Use: When you need to track editing activity such as revision numbers or total editing time.
This code extracts revision‑related properties from each version and reports numeric or timestamp deltas.
var v1 = GetRevisionProperties(pathV1);
var v2 = GetRevisionProperties(pathV2);
var changes = new Dictionary<string, (string, string)>();
var allKeys = new HashSet<string>(v1.Keys);
foreach (var k in v2.Keys) allKeys.Add(k);
foreach (var key in allKeys)
{
var oldV = v1.TryGetValue(key, out var o) ? o : "<missing>";
var newV = v2.TryGetValue(key, out var n) ? n : "<missing>";
if (oldV != newV)
{
changes[key] = (oldV, newV);
}
}
return changes;What This Solves: Exposes hidden edit activity that standard viewers do not display.
Real-World Application: Compliance officers can verify that document revisions align with change‑control policies.
When to Use: When audit results need to be reviewed in spreadsheet tools or imported into data pipelines.
The method writes added, removed, and changed metadata entries to a CSV file with four columns.
var sb = new StringBuilder();
sb.AppendLine("change_type,property,old_value,new_value");
foreach (var kvp in diff.Added)
{
sb.AppendLine($"added,{CsvEscape(kvp.Key)},,{CsvEscape(kvp.Value)}");
}
foreach (var kvp in diff.Removed)
{
sb.AppendLine($"removed,{CsvEscape(kvp.Key)},{CsvEscape(kvp.Value)},");
}
foreach (var kvp in diff.Changed)
{
sb.AppendLine($"changed,{CsvEscape(kvp.Key)},{CsvEscape(kvp.Value.OldValue)},{CsvEscape(kvp.Value.NewValue)}");
}
File.WriteAllText(outputPath, sb.ToString());What This Solves: Generates a ready‑to‑import CSV audit report without custom parsing.
Real-World Application: Teams can feed the CSV into Excel dashboards or compliance reporting tools.
When to Use: When downstream systems consume structured audit data via APIs or need a human‑readable format.
The snippet builds a JSON object with separate arrays for added, removed, and changed properties.
var sb = new StringBuilder();
sb.AppendLine("{");
sb.AppendLine(" \"added\": {");
WriteMap(sb, diff.Added);
sb.AppendLine(" },");
sb.AppendLine(" \"removed\": {");
WriteMap(sb, diff.Removed);
sb.AppendLine(" },");
sb.AppendLine(" \"changed\": {");
var changedItems = 0;
foreach (var kvp in diff.Changed)
{
var comma = ++changedItems < diff.Changed.Count ? "," : string.Empty;
sb.AppendLine($" \"{Escape(kvp.Key)}\": {{ \"from\": \"{Escape(kvp.Value.OldValue)}\", \"to\": \"{Escape(kvp.Value.NewValue)}\" }}{comma}");
}
sb.AppendLine(" }");
sb.AppendLine("}");
File.WriteAllText(outputPath, sb.ToString());What This Solves: Provides a stable JSON schema that can be version‑controlled or fed into compliance dashboards.
Real-World Application: Security teams can archive JSON audit logs for long‑term evidence preservation.
When to Use: When you need a complete snapshot of every metadata field before performing any comparison.
The method opens a document, walks the full property tree, and returns a dictionary of name‑value pairs.
var result = new Dictionary<string, string>();
using (var metadata = new MetadataFacade(documentPath))
{
if (metadata.FileFormat == FileFormat.Unknown)
{
return result;
}
var properties = metadata.FindProperties(p => p.Name != null);
foreach (var property in properties)
{
var key = property.Name;
var value = property.InterpretedValue?.ToString() ?? property.Value?.ToString() ?? string.Empty;
result[key] = value;
}
}
return result;What This Solves: Supplies the foundational data set required for any downstream diff or audit operation.
Real-World Application: Developers can integrate this extractor into CI pipelines to automatically flag unexpected metadata changes.
By using GroupDocs.Metadata for Compare Metadata Between Document Versions, you gain:
- Time savings: Automates extraction and diffing that would otherwise require manual inspection.
- Accuracy: Guarantees consistent property retrieval across all supported formats.
- Compliance readiness: Generates audit‑grade CSV/JSON reports aligned with regulatory requirements.
- Scalability: Handles large batches of documents without custom parsers.
- Maintainability: Centralized codebase simplifies updates when new metadata standards emerge.
GroupDocs.Metadata, .NET, metadata extraction, document versioning, metadata diff, ownership detection, revision history, CSV export, JSON export, e‑discovery, forensic audit, legal compliance, document security, metadata comparison, C#, GroupDocs, metadata API, document metadata, audit report, metadata analysis, metadata diffing, metadata automation, metadata tools, metadata SDK
Ready to get started? View Documentation | Get Support | Request License