💡 Ejemplo completo y funcional disponible en GitHub: parse-docx-to-markdown-chunks-dotnet
El método antiguo era doloroso
El fragmentado de Markdown basado en encabezados es una ruta de preparación de recuperación en .NET que convierte archivos de Office y PDF en texto del tamaño de una sección antes de incrustarlos. Sin ella, los equipos a menudo vuelcan un archivo Word completo en un solo vector. El párrafo de portada y la cláusula de deber comparten una única incrustación, por lo que la búsqueda por coseno clasifica la sección incorrecta. Me encontré con eso en una guía interna de tres páginas: cada consulta extraía primero el bloque de título porque el índice nunca vio la estructura # / ## que los autores ya habían escrito.
Crear a mano un conversor de DOCX a Markdown implica recorrer los estilos de Open XML, mapear niveles de listas y aún fallar cuando la siguiente carga es un PDF cuyo camino de Markdown formateado devuelve null. Las ventanas de tokens de tamaño fijo ignoran esos encabezados. Los corpora nocturnos entonces mezclan capas vacías con manuales enormes porque nadie verifica primero el recuento de páginas o el tamaño.
El costo real de las incrustaciones de archivos completos: respuestas de secciones incorrectas, gasto desperdiciado en extracción de cargas basura, y ausencia de artefactos
chunk-01.mdque los operadores puedan abrir durante un lote defectuoso.
Hay una mejor manera
GroupDocs.Parser para .NET reemplaza ese caos con cuatro llamadas enfocadas: GetDocumentInfo, GetFormattedText(FormattedTextMode.Markdown), GetText cuando Markdown es null, y un pequeño recorrido de encabezados que escribe chunk-NN.md. El mismo tipo Parser cubre el análisis de Word DOCX y el fallback de texto PDF, por lo que mantienes una única ruta de servicio C#.
Necesitarás:
- .NET 8 SDK
- GroupDocs.Parser 26.10.0 (licencia temporal)
- Un DOCX de Word (el ejemplo tiene 3 páginas / 14820 bytes) y opcionalmente un PDF
dotnet add package GroupDocs.Parser --version 26.10.0
El nuevo método: inspeccionar, extraer, retroceder, dividir
Aquí está la misma preparación de recuperación después del cambio. El ejemplo de consola bajo parse-docx-to-markdown-chunks-dotnet escribe información, Markdown, texto PDF y cuatro fragmentos de encabezado para el DOCX incluido.
Paso 1 - Filtrar con GetDocumentInfo
Solicita el tipo de archivo, el recuento de páginas y el tamaño antes de pagar por una extracción completa.
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());
Registra esos datos junto al ID del trabajo. En el DOCX de ejemplo deberías ver un Microsoft Word Open XML Document, 3 páginas y 14820 bytes.
Paso 2 - Preferir Markdown de GetFormattedText
Para Word y formatos que admiten extracción formateada, conserva los encabezados ATX para el divisor.
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 es una señal para cambiar de ruta, no un error. Escribe en UTF-8 para que las herramientas de fragmentación y los diffs de git permanezcan legibles.
Paso 3 - Retroceder con GetText para PDF
Cuando el modo Markdown devuelve null, mantiene el archivo en la canalización con una capa de texto plano.
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;
Espera .txt, no encabezados # inventados. El host de ejemplo escribe Result/sample-pdf.txt para la rama PDF.
Paso 4 - Dividir Markdown en # y
Recorre las líneas; vacía cuando aparece un nuevo ATX # o ##; escribe 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);
}
}
Elimina primero los archivos chunk-*.md obsoletos. Las líneas más profundas ### permanecen dentro de la sección actual. El DOCX de ejemplo genera cuatro archivos bajo Result/chunks/.
¿Cuándo debería reemplazar las incrustaciones de archivos completos con esta ruta?
Reemplaza las incrustaciones de archivos completos cuando la ingestión combina Word DOCX y PDF y el índice necesita Markdown del tamaño de una sección. Ejecuta GetDocumentInfo primero, prueba Markdown para archivos de Office, llama a GetText cuando el lector formateado es null, y divide solo cuando existen marcadores # / ##. Deja el texto PDF sin estructurar sin tocar hasta que añadas una política de fragmentación separada. Ese orden coincide con la aplicación de consola de ejemplo y mantiene los modos de falla explícitos para los operadores.
Qué cambió para los operadores
| Antes | Después |
|---|---|
| Una incrustación por archivo | Una incrustación por bloque de encabezado |
| Markdown Open XML personalizado | Modo Markdown de GetFormattedText |
| PDF descartado cuando el lector formateado es null | GetText escribe un artefacto de texto |
| No hay verificación previa barata | El recuento de páginas y la verificación de tamaño funcionan |
Descarta cada Parser y TextReader. Aplica una licencia o licencia temporal antes del volumen nocturno. Trata las cargas como entrada no confiable y analiza en un trabajador aislado.
Pruébalo con tus propios archivos
Clona parse-docx-to-markdown-chunks-dotnet, restaura GroupDocs.Parser 26.10.0 y ejecútalo contra documents/sample.docx. Luego apunta los mismos cuatro métodos a uno de tus manuales y abre los archivos chunk-*.md generados.