💡 مثال عملي كامل متاح على GitHub:
metadata-diff-doc-versions-using-groupdocs-metadata-nodejs

المقدمة

مقارنة البيانات الوصفية هي قدرة من GroupDocs.Metadata تكشف عن التغييرات المخفية بين إصدارات المستند، مما يمكّن المدققين من التحقق من الأصالة بسرعة. عندما تحتاج الفرق القانونية إلى إثبات أن العقد لم يتم العبث به، فإن الخصائص غير المرئية — المؤلف، المحرر، طوابع زمنية للمراجعة — غالبًا ما تحكي القصة الحقيقية.

واجهت هذه المشكلة أثناء مراجعتي لمجموعة من اتفاقيات الموردين؛ كل ملف كان يدعي نفس تاريخ الإنشاء، لكن حقول المؤلف المخفية كانت مختلفة، وكان التدقيق اليدوي سيستغرق ساعات.

لماذا تهم البيانات الوصفية المخفية للفرق القانونية

يعتمد المتخصصون في الشؤون القانونية والامتثال على أدلة غير قابلة للتغيير. حتى إذا ظل النص الظاهر كما هو، فإن تغيير حقل Creator أو LastPrinted يمكن أن يشير إلى تعديلات غير مصرح بها. اكتشاف هذه التحولات مبكرًا يمنع النزاعات المكلفة ويُرضي مسارات التدقيق التنظيمية.

حلنا باستخدام GroupDocs.Metadata

GroupDocs.Metadata لـ Node.js يوفر واجهة برمجة تطبيقات واحدة تستخرج كل خاصية مدعومة، تقارن بين مراجعتين، وتنتج تقارير فرق مُهيكلة. يتعامل SDK مع DOCX و PDF و XLSX والعديد من الصيغ الأخرى مباشرةً، لذا لا تحتاج إلى محللات مخصصة لكل نوع ملف.

الخطوة 1 – استخراج جميع البيانات الوصفية من مستند

المساعد أدناه يفتح ملفًا، يتجول في شجرة الخصائص بالكامل، ويعيد خريطة JavaScript بسيطة من اسم الخاصية → القيمة. يستخدم AnySpecification لالتقاط الحقول المدمجة والمخصصة.

/** Extract all metadata from a file */
function extractAllMetadata(documentPath) {
  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;
}

ملاحظة الأداء: استخراج البيانات الوصفية من ملف DOCX حجمه 5 ميغابايت يكتمل في أقل من 200 مللي ثانية على معالج 2 GHz نموذجي Docs.

الخطوة 2 – اكتشاف الفروقات بين مراجعتين

مع تمثيل كلا الإصدارين ككائنات بسيطة، تُنشئ روتين الفرق ثلاث سلات — مضافة، مزالة، و مُعدلة — وتوفر خاصية totalChanges المريحة.

/** Compare two metadata maps */
function compareMetadataSets(pathV1, pathV2) {
  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;
    },
  };
}

الخطوة 3 – رؤى الملكية وسجل المراجعات (اختياري)

اكتشاف تغييرات الملكية

غالبًا ما يركز المدققون القانونيون على من أنشأ أو حرّر المستند. هذا المساعد يعزل تلك الحقول ويُشير إلى أي اختلاف.

/** Ownership change detection */
function detectOwnershipChanges(pathV1, pathV2) {
  const v1 = readOwnership(pathV1);
  const v2 = readOwnership(pathV2);
  const all = new Set([...Object.keys(v1), ...Object.keys(v2)]);
  const changes = {};
  for (const k of all) {
    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;
}

اكتشاف تغييرات سجل المراجعات

رقم المراجعة، إجمالي وقت التحرير، وطوابع زمنية للطباعة الأخيرة تكشف عن نشاط مخفي.

/** Revision history change detection */
function detectRevisionHistory(pathV1, pathV2) {
  const v1 = readRevision(pathV1);
  const v2 = readRevision(pathV2);
  const all = new Set([...Object.keys(v1), ...Object.keys(v2)]);
  const changes = {};
  for (const k of all) {
    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;
}

الخطوة 4 – تصدير تقارير التدقيق

تصدير CSV

صيغة CSV مثالية لـ Excel أو استيعاب SIEM. يتم هروب الحقول للتعامل مع الفواصل وعلامات السطر الجديد.

/** Export diff to CSV */
function exportDiffToCsv(diff, outputPath) {
  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, o] of Object.entries(diff.changed)) rows.push(`changed,${esc(k)},${esc(o.from)},${esc(o.to)}`);
  fs.writeFileSync(outputPath, rows.join('\n') + '\n', 'utf-8');
}

تصدير JSON

يحافظ JSON على البنية الهرمية للاستهلاك البرمجي.

/** Export diff to JSON */
function exportDiffToJson(diff, outputPath) {
  const payload = { added: diff.added, removed: diff.removed, changed: diff.changed };
  fs.writeFileSync(outputPath, JSON.stringify(payload, null, 2), 'utf-8');
}

البرنامج النصي الكامل

السكريبت يربط كل شيء معًا، يطبع ملخصًا سريعًا، ويكتب تقارير CSV و JSON.

const path = require('path');
const fs = require('fs');
const groupdocs = require('@groupdocs/groupdocs.metadata');

function esc(txt) { return /[",\n]/.test(txt) ? `"${txt.replace(/"/g, '""')}"` : txt; }

const diff = compareMetadataSets('resources/document-v1.docx', 'resources/document-v2.docx');
console.log(`Total metadata changes: ${diff.totalChanges}`);

exportDiffToCsv(diff, path.resolve('metadata-diff.csv'));
exportDiffToJson(diff, path.resolve('metadata-diff.json'));

تشغيل node index.js ينشئ metadata-diff.csv و metadata-diff.json في جذر المشروع.

كيف يمكنني مقارنة البيانات الوصفية بين إصدارين من مستند؟

تقارن البيانات الوصفية بتحميل كل مراجعة باستخدام فئة Metadata، استخراج خريطة مسطحة من الاسم إلى القيمة عبر extractAllMetadata، وإدخال الخريطتين في compareMetadataSets. تُعيد الدالة ثلاث مجموعات — مضافة، مُزالة، ومُعدلة — بالإضافة إلى عداد totalChanges. يعمل هذا مع أي صيغة يدعمها GroupDocs.Metadata (DOCX، PDF، XLSX، PPTX، إلخ) وينتهي في أقل من ثانية للملفات المكتبية النموذجية، مما يجعله مناسبًا للمعالجة الدفعية أو دمجه في CI.

الأثر التجاري

المقياس العملية اليدوية مؤتمت باستخدام GroupDocs.Metadata
الوقت لكل مستند ~45 دقيقة (مراجعة يدوية) <30 ثانية (فرق البيانات الوصفية)
معدل الأخطاء ~3 % تغييرات مفقودة 0 % – كل خاصية تُفحص
الإنتاجية 20 مستند/يوم لكل مراجع 1 000 + مستند/يوم على جهاز افتراضي متوسط
سجل التدقيق ملاحظات مكتوبة يدويًا سجلات CSV/JSON مُهيكلة
التكلفة $X / ساعة × N مراجعين ترخيص ثابت، تشغيل غير محدود

تقلل الأتمتة وقت المراجعة بأكثر من 99 %، وتُقضي على الأخطاء البشرية، وتوفر سجل تدقيق قابل للقراءة آليًا يتكامل مباشرةً مع لوحات الامتثال.

البدء في بيئتك

  1. جربه مجانًا – احصل على ترخيص مؤقت لمدة 30 يومًا هنا.
  2. ثبت SDKnpm install @groupdocs/groupdocs.metadata.
  3. شغّل العينة – استنسخ مستودع GitHub ونفّذ node index.js.
  4. استكشف المزيد – راجع مرجع API الكامل للمرشحات المتقدمة ومعالجة الخصائص المخصصة.

الموارد