💡 مثال كامل يعمل متاح على GitHub: parse-docx-to-markdown-chunks-dotnet

الطريقة القديمة كانت مؤلمة

تقسيم Markdown بناءً على العناوين هو مسار إعداد استرجاع في .NET يحول ملفات Office و PDF إلى نص بحجم القسم قبل عملية التضمين. بدون ذلك، غالبًا ما تقوم الفرق بإلقاء ملف Word كامل في متجه واحد. الفقرة الغلافية والبند الواجب يتشاركان تضمينًا واحدًا، لذا تصنف عملية البحث الكوسيني القسم الخطأ. صادفت ذلك في دليل داخلي من ثلاث صفحات: كل استعلام كان يجلب كتلة العنوان أولاً لأن الفهرس لم يرَ بنية # / ## التي كتبها المؤلفون بالفعل.

إنشاء محول DOCX إلى Markdown يدويًا يعني التنقل عبر أنماط Open XML، وربط مستويات القوائم، وما زال يفشل عندما يكون التحميل التالي ملف PDF تُعيد مسار Markdown المُنسق الخاص به قيمة null. نوافذ الرموز ذات الحجم الثابت تتجاهل تلك العناوين. ثم تُخلط مجموعات البيانات الليلية أصدافًا فارغة مع كتيبات ضخمة لأن لا أحد يفرض حظرًا على عدد الصفحات أو الحجم أولاً.

التكلفة الحقيقية لتضمينات الملف الكامل: إجابات أقسام خاطئة، إنفاق استخراج مهدور على تحميلات غير مفيدة، وعدم وجود قطع chunk-01.md يمكن للمشغلين فتحها أثناء دفعة سيئة.

هناك طريقة أفضل

GroupDocs.Parser لـ .NET يستبدل هذا الفوضى بأربع استدعاءات مركزة: GetDocumentInfo، GetFormattedText(FormattedTextMode.Markdown)، GetText عندما يكون Markdown قيمته null، ومُتجول عناوين صغير يكتب chunk-NN.md. نفس نوع Parser يغطي تحليل Word DOCX والعودة إلى نص PDF، لذا تحتفظ بمسار خدمة C# واحد.

ستحتاج إلى:

  • .NET 8 SDK
  • GroupDocs.Parser 26.10.0 (رخصة مؤقتة)
  • ملف Word DOCX (العينة هي 3 صفحات / 14820 بايت) واختياريًا PDF
dotnet add package GroupDocs.Parser --version 26.10.0

الطريقة الجديدة: الفحص، الاستخراج، الرجوع، التقسيم

إليك نفس إعداد الاسترجاع بعد التبديل. عينة وحدة التحكم تحت parse-docx-to-markdown-chunks-dotnet تكتب المعلومات، Markdown، نص PDF، وأربع قطع عناوين للـ DOCX المرفق.

الخطوة 1 - التحقق باستخدام GetDocumentInfo

اطلب نوع الملف، عدد الصفحات، والحجم قبل أن تدفع لاستخراج كامل.

using var parser = new Parser(sourcePath);
var info = parser.GetDocumentInfo();

var sb = new StringBuilder();
sb.AppendLine($"Source: {Path.GetFileName(sourcePath)}");
sb.AppendLine($"File type: {info?.FileType}");
sb.AppendLine($"Pages: {info?.PageCount}");
sb.AppendLine($"Size: {info?.Size} bytes");
File.WriteAllText(outputPath, sb.ToString());

سجّل تلك الحقائق بجانب معرف المهمة. في عينة DOCX يجب أن ترى Microsoft Word Open XML Document، 3 صفحات، و14820 بايت.

الخطوة 2 - تفضيل Markdown من GetFormattedText

بالنسبة إلى Word والأنساق التي تدعم الاستخراج المنسق، احتفظ بعناوين ATX للمقسم.

using var parser = new Parser(sourcePath);
using TextReader? reader = parser.GetFormattedText(
    new FormattedTextOptions(FormattedTextMode.Markdown));

if (reader == null)
{
    return null;
}

string markdown = reader.ReadToEnd();
File.WriteAllText(outputPath, markdown, Encoding.UTF8);
return markdown;

قيمة null هي إشارة لتبديل المسارات، ليست عطلًا. اكتب بـ UTF-8 حتى تظل أدوات القطع واختلافات git قابلة للقراءة.

الخطوة 3 - الرجوع باستخدام GetText لملف PDF

عندما تُعيد وضعية Markdown قيمة null، احتفظ بالملف في خط الأنابيب بطبقة نص عادي.

using var parser = new Parser(sourcePath);
using TextReader? reader = parser.GetText();
if (reader == null)
{
    return null;
}

string text = reader.ReadToEnd();
File.WriteAllText(outputPath, text, Encoding.UTF8);
return text;

توقع .txt، وليس عناوين # المخترعة. المضيف العيني يكتب Result/sample-pdf.txt لفرع PDF.

الخطوة 4 - تقسيم Markdown على # و

تجول عبر السطور؛ أفرغ عندما يظهر ATX جديد # أو ##؛ اكتب chunk-NN.md.

var chunks = new List<string>();
var current = new StringBuilder();
using (var reader = new StringReader(markdown))
{
    string? line;
    while ((line = reader.ReadLine()) != null)
    {
        bool isHeading = line.StartsWith("# ", StringComparison.Ordinal)
            || line.StartsWith("## ", StringComparison.Ordinal);
        if (isHeading && current.Length > 0)
        {
            chunks.Add(current.ToString().TrimEnd());
            current.Clear();
        }
        current.AppendLine(line);
    }
}

احذف ملفات chunk-*.md القديمة أولاً. السطور الأعمق ### تبقى داخل القسم الحالي. عينة DOCX تنتج أربعة ملفات تحت Result/chunks/.

متى يجب أن أستبدل تضمينات الملف الكامل بهذا المسار؟

استبدل تضمينات الملف الكامل عندما يخلط الإدخال بين Word DOCX و PDF ويحتاج الفهرس إلى Markdown بحجم القسم. شغّل GetDocumentInfo أولاً، جرّب Markdown لملفات Office، استدعِ GetText عندما يكون القارئ المنسق قيمته null، وقم بالتقسيم فقط عندما توجد علامات # / ##. اترك نص PDF غير المهيكل كما هو حتى تضيف سياسة قطع منفصلة. هذا الترتيب يتطابق مع تطبيق وحدة التحكم العيني ويحافظ على وضوح أوضاع الفشل للمشغلين.

ما الذي تغير للمشغلين

قبل بعد
تضمين واحد لكل ملف تضمين واحد لكل كتلة عنوان
Markdown مخصص لـ Open XML وضع Markdown لـ GetFormattedText
PDF يُهمل عند القارئ المنسق null GetText يكتب قطعة نصية
لا فحص مسبق رخيص عدد الصفحات وحجم البوابة يعمل

قم بتحرير كل Parser و TextReader. طبّق رخصة أو رخصة مؤقتة قبل حجم العمل الليلي. اعتبر التحميلات كمدخلات غير موثوقة وحللها في عامل معزول.

جرّبه على ملفاتك الخاصة

استنسخ parse-docx-to-markdown-chunks-dotnet، استعد GroupDocs.Parser 26.10.0، وشغّل ضد documents/sample.docx. ثم وجه نفس الأربع طرق إلى أحد كتيباتك وافتح ملفات chunk-*.md المُولدة.