Get started with GroupDocs.Metadata for Node.js via Java to compare metadata across document versions. This repository provides ready-to-use examples that demonstrate extracting, diffing, and exporting metadata. Perfect for developers who need to audit document changes.
- Extract every accessible metadata property from a document.
- Detect ownership and authorship changes between versions.
- Identify revision‑history differences such as edit counts and timestamps.
- Generate structured diff reports in JSON and CSV formats.
- Export audit reports for compliance pipelines.
- Apply these techniques in e‑discovery and forensic investigations.
- About This Repository
- Key Features
- Prerequisites
- Repository Structure
- Implementation Examples
- Keywords
This repository contains practical examples for implementing metadata comparison using GroupDocs.Metadata for Node.js via Java. GroupDocs.Metadata enables developers to extract, compare, and export document metadata across formats such as DOCX, PDF, and XLSX. These examples are designed for forensic analysts and compliance engineers working with legal documents who need to track ownership, revision, and custom property changes. Each sample demonstrates a real‑world scenario and follows best practices for audit‑ready reporting.
GroupDocs.Metadata provides powerful document processing capabilities:
| Feature | Description |
|---|---|
| Extract All Metadata | Walks the full property tree and returns a name‑to‑value map for any supported document. |
| Compare Metadata Sets | Computes added, removed, and changed properties between two versions. |
| Detect Ownership Changes | Highlights differences in Creator, Editor, Manager, and Company fields. |
| Detect Revision History | Reports numeric and timestamp deltas for RevisionNumber, TotalEditingTime, LastPrinted, etc. |
| Export Diff to JSON/CSV | Serializes the diff into stable schemas for compliance pipelines and SIEM ingestion. |
- Metadata extraction from DOCX files using the
extractAllMetadatahelper. - Diff generation that categorises changes as added, removed, or modified.
- Ownership change detection for legal‑team audit trails.
- Revision history analysis exposing hidden editing activity.
- Report export to both JSON and CSV for downstream processing.
Before you begin, ensure you have:
- Node.js – version 16 or later.
- GroupDocs.Metadata license – a temporary license can be obtained from the link above.
- Java runtime – required by the GroupDocs.Metadata Java bridge.
compare-metadata-between-document-versions/
│
├── methods
│ ├── compareMetadataSets.js
│ ├── detectOwnershipChanges.js
│ ├── detectRevisionHistory.js
│ ├── exportDiffToCsv.js
│ ├── exportDiffToJson.js
│ └── extractAllMetadata.js
├── resources
│ ├── document-v1.docx
│ ├── document-v2.docx
│ └── input
│ └── document-v1.docx
├── index.js
├── package.json
└── package-lock.json
- compareMetadataSets.js – Compares two metadata maps and returns a diff object.
- detectOwnershipChanges.js – Finds changes in identity‑bearing properties.
- detectRevisionHistory.js – Reports revision‑related metadata deltas.
- exportDiffToCsv.js – Writes the diff to a CSV audit file.
- exportDiffToJson.js – Writes the diff to a JSON audit file.
- extractAllMetadata.js – Core helper that extracts every metadata property.
- index.js – Sample driver that orchestrates the workflow.
- package.json – Project metadata and dependencies.
- package-lock.json – Exact dependency tree for reproducible builds.
The code loads both documents, extracts all properties, and builds three maps: added, removed, and changed. It also provides a totalChanges getter for quick summary.
const v1 = extractAllMetadata(pathV1);
const v2 = extractAllMetadata(pathV2);
const added = {};
const removed = {};
const changed = {};
for (const k of Object.keys(v2)) {
if (!(k in v1)) added[k] = v2[k];
else if (v1[k] !== v2[k]) changed[k] = { from: v1[k], to: v2[k] };
}
for (const k of Object.keys(v1)) {
if (!(k in v2)) removed[k] = v1[k];
}
return {
added,
removed,
changed,
get totalChanges() {
return Object.keys(this.added).length + Object.keys(this.removed).length + Object.keys(this.changed).length;
},
};What This Example Shows:
It demonstrates a generic diff algorithm that works with any document type supported by GroupDocs.Metadata. The result can be fed directly into export utilities.
The snippet reads ownership‑related tags (Creator, Editor, Manager, Company) from each version and reports any differences, using <missing> placeholders for absent values.
const v1 = readOwnership(pathV1);
const v2 = readOwnership(pathV2);
const allKeys = new Set([...Object.keys(v1), ...Object.keys(v2)]);
const changes = {};
for (const k of allKeys) {
const oldV = v1[k] !== undefined ? v1[k] : '<missing>';
const newV = v2[k] !== undefined ? v2[k] : '<missing>';
if (oldV !== newV) changes[k] = { from: oldV, to: newV };
}
return changes;What This Example Shows:
It isolates identity‑bearing metadata, which is crucial for legal teams to prove or refute tampering claims.
Example 3: Detects revision‑related metadata changes such as RevisionNumber, TotalEditingTime, and LastPrinted.
The function focuses on time‑based and revision counters, exposing editing activity invisible to end users.
const v1 = readRevision(pathV1);
const v2 = readRevision(pathV2);
const allKeys = new Set([...Object.keys(v1), ...Object.keys(v2)]);
const changes = {};
for (const k of allKeys) {
const oldV = v1[k] !== undefined ? v1[k] : '<missing>';
const newV = v2[k] !== undefined ? v2[k] : '<missing>';
if (oldV !== newV) changes[k] = { from: oldV, to: newV };
}
return changes;What This Example Shows:
It reveals how many times a document was edited and when it was last printed, supporting forensic timelines.
The code builds a CSV with columns change_type,property,old_value,new_value, suitable for Excel or SIEM ingestion.
const rows = ['change_type,property,old_value,new_value'];
for (const [k, v] of Object.entries(diff.added)) rows.push(`added,${esc(k)},,${esc(v)}`);
for (const [k, v] of Object.entries(diff.removed)) rows.push(`removed,${esc(k)},${esc(v)},`);
for (const [k, obj] of Object.entries(diff.changed)) rows.push(`changed,${esc(k)},${esc(obj.from)},${esc(obj.to)}`);
fs.writeFileSync(outputPath, rows.join('\n') + '\n', 'utf-8');What This Example Shows:
It creates a flat file that can be loaded directly into compliance dashboards or data‑warehouse pipelines.
The snippet writes a stable JSON schema containing added, removed, and changed sections.
const payload = {
added: diff.added,
removed: diff.removed,
changed: diff.changed,
};
fs.writeFileSync(outputPath, JSON.stringify(payload, null, 2), 'utf-8');What This Example Shows:
The JSON format is ideal for programmatic diffing across multiple audit runs or for attaching to e‑discovery packages.
The function opens the file with GroupDocs.Metadata, iterates over all discovered properties, and builds a plain JavaScript object.
const result = {};
const metadata = new groupdocs.Metadata(documentPath);
try {
const properties = metadata.findProperties(new groupdocs.AnySpecification());
for (let i = 0; i < properties.getCount(); i++) {
const p = properties.get_Item(i);
const name = p.getName();
const value = valueToString(p);
result[name] = value;
}
} finally {
metadata.close();
}
return result;What This Example Shows:
It provides the foundational data structure used by the diff and export utilities, handling both built‑in and custom properties.
GroupDocs.Metadata, Node.js, Java bridge, metadata extraction, metadata comparison, document audit, e‑discovery, forensic analysis, ownership detection, revision history, JSON export, CSV export, DOCX, PDF, XLSX, legal compliance, change tracking, property diff, temporary license, API, document processing
Need help? Get Free Support | Get Temporary License