Test Table Slide【免费下载链接】doclingGet your documents ready for gen AI项目地址: https://gitcode.com/GitHub_Trending/do/docling| | Class1 | Class1 | Class1 | Class2 | Class2 | Class2 | | - | - | - | - | - | - | - | | | A merged with B | A merged with B | C | A | B | C | | R1 | True | False | | False | True | True | | R2 | | | True | False | | | | R3 | False | | | | False | | | R3 | | True | | True | | | | R4 | | | False | | False | | | R4 | | True | | True | False | False | | R4 | True | False | True | False | True | False |With footnote从这份输出中至少能提炼出 docling 表格导出的四个行为特征 - **标题独立成标题行**幻灯片标题 Test Table Slide 被识别为标题文本导出为 # 标题而不是表格内文本 - **合并单元格按“复制填满”策略输出**观察第二行 | A merged with B | A merged with B | C | ...这是一个横向合并两个单元格的标题单元。为保持 Markdown 表格的矩形栅格结构合并后的文本在跨越的每一列上都被重复写出竖向合并同样如此——R3 连续出现两行、R4 连续出现三行正是行方向合并单元格在扁平的 Markdown 网格中被重复填充的结果 - **空单元格保留占位**表格中大量 | | 空段是合并结构中被覆盖的栅格位被如实保留为空单元格 - **表格与文本分离**表下方的 With footnote 是独立段落说明该文本不属于表格体而是独立于表格、紧随其后的正文元素。 ### 2. 第二张幻灯片图形文本与列表 紧接着是第二张幻灯片的内容 markdown # Second slide title A rectangle shape with this text inside. Let’s introduce a list - With foo - Bar - And baz things这里体现了 docling 对幻灯片“形状内文本”的抽取A rectangle shape with this text inside.原本是绘制在矩形形状shape文本框里的文字转换后被还原为普通段落随后Let’s introduce a list是引导语段落紧跟的是无序列表演示。3. 列表与段落如何在连续 Markdown 中并存基准文件的剩余部分展示了一个更常见也更“麻烦”的幻灯片排版场景——同一页面上多组不同样式的列表、带引导文案的列表交错出现1. List item4 2. List item5 3. List item6 - I1 - I2 - I3 - I4 Some info: - Item A - Item B Maybe a list? 1. List1 2. List2 3. List3 - l1 - l2 - l3这些内容在源幻灯片中分属不同文本框与不同段落组。注意两点输出细节编号列表与符号列表被区分凡是源文档使用了自动编号buAutoNum的段落组导出为有序列表使用字符符号buChar或无符号列表标记的段落组导出为无序列表。即便多个列表紧挨着排布docling 也按各自独立的 list group 处理不会合并成一个列表Markdown 输出中不显式标注幻灯片分界与结构化文档JSON/itxt见下节不同纯文本 Markdown 导出是“顺排”的——从基准输出中只能通过标题与内容变化推测幻灯片的切换没有类似---的分页符。二、对照“结构化视图”JSON 与 itxt 揭示的真实层级仅看 Markdown 会漏掉一个重要信息——这些内容到底如何被组织成文档树。同目录下的两份基准给出了答案。legacy_sample.ppt.json是DoclingDocument的完整序列化结果其schema_name为DoclingDocument。从 JSON 的body与groups节点可以看出该.ppt被组织为3 个 chapter 分组的幻灯片slide-0含标题文本、表格、脚注段落、slide-1、以及第三个含多个列表的 group。每个文本、表格都被挂在对应slide-N分组之下表格在第 0 张幻灯片多组列表落在后续幻灯片——这解释了为什么 Markdown 中表格与列表会处于不同位置。legacy_sample.ppt.itxt则用缩进文本直观展示了树形层级item-0 at level 0: unspecified: group _root_ item-1 at level 1: chapter: group slide-0 item-2 at level 2: title: Test Table Slide item-3 at level 2: table with [9x7] item-4 at level 2: paragraph: With footnote item-5 at level 1: chapter: group slide-1 item-6 at level 2: title: Second slide title ... item-9 at level 2: list: group list item-10 at level 3: list_item: With foo从这里可以确认几个与 Markdown 输出严格对应的关键事实表格规模为9 行 × 7 列table with [9x7]与 Markdown 中表头 2 行 数据 7 行的 9 行一致幻灯片标题在文档树中的 label 是title列表被识别为list: group list其下每个条目是list_item段落 label 为paragraph每一张幻灯片是一个chapter分组演示文件被表示为“章—节”式的文档层级这与 docling 对演示文稿的通用建模方式一致itxt 基准文件、JSON 基准文件。三、为什么.ppt能转后端先做“旧到新”的格式桥接要理解这份基准输出的产生过程需要看 docling 的 PowerPoint 后端实现 docling/backend/mspowerpoint_backend.py。该后端的类文档字符串明确写道Legacy.pptfiles (binary PowerPoint 97-2003 format) are first converted to.pptxvia LibreOffice before parsing.在构造函数的初始化逻辑里可以看到这一桥接的直接代码docling/backend/mspowerpoint_backend.py#L148-L149if in_doc.format InputFormat.PPT: path_or_stream convert_to_modern_format(path_or_stream, ppt, pptx)也就是说docling 自身并不直接解析二进制.ppt而是先调用 LibreOffice 将其无头转换为.pptx再交给python-pptxPresentation加载解析。真正的 LibreOffice 调用封装在 docling/backend/docx/drawingml/utils.py 的convert_to_modern_format(source, source_suffix, target_suffix, timeout_s120)函数中其实现要点包括同时接受文件路径与内存字节流BytesIO传入流时会先按源扩展名命名写入临时文件以便 LibreOffice 探测格式以--headless --convert-to target_suffix --outdir tmp调用 LibreOffice 子进程为规避多进程/并发转换时 LibreOffice 对用户配置目录的独占锁冲突转换会使用-env:UserInstallationuri指向一个一次性临时 profile见_isolated_libreoffice_profile转换产物以BytesIO返回供上层直接解析。该后端支持的格式集合是{InputFormat.PPTX, InputFormat.PPT}supported_formats()见docling/backend/mspowerpoint_backend.py#L201-L202转换后通过_walk_linear将每一张幻灯片上的标题、段落、表格、列表、图片等形状抽取为 DoclingDocument 结构。因此你在legacy_sample.ppt.md中看到的表格与列表质量本质上取决于“LibreOffice 重排出的.pptx能否保真还原原版版式”。四、这份基准是如何被验证的端到端回归测试legacy_sample.ppt.md并非孤立的展示样例它是自动化回归测试的“答案”。打开端到端测试 tests/test_backend_legacy_msoffice.py可以看到.doc、.xls、.ppt三种旧版二进制 Office 格式共享同一套验证逻辑_CASES: list[tuple[InputFormat, str]] [ (InputFormat.DOC, tests/data/doc/sources), (InputFormat.XLS, tests/data/xls/sources), (InputFormat.PPT, tests/data/ppt/sources), ]该测试的关键行为包括整个测试文件在 LibreOffice 不可用时被跳过pytest.mark.skipif(get_libreoffice_cmd() is None, ...)印证了格式桥接对 LibreOffice 的硬依赖使用DocumentConverter(allowed_formats[fmt])转换sources目录下的每一个样本然后与groundtruth目录下同名文件比较三类输出doc.export_to_markdown(compact_tablesTrue)与.md基准比对doc._export_to_indented_text(max_text_len70, explicit_tablesFalse)与.itxt基准比对verify_document(doc, ...)与.json基准做带模糊容差的比对由于 LibreOffice 在不同平台上渲染出的图片尺寸略有差异bbox 类比对使用了模糊容差fuzzy tolerance测试文件头部引用了test_data_gen_flag的GEN_TEST_DATA——当该标志开启时比对会进入“重新生成基准”模式允许维护者用当前版本重新固化输出。这意味着任何 PR 只要改变了.ppt的转换逻辑就必须让上述三个基准文件保持一致否则测试失败。所以legacy_sample.ppt.md的稳定直接守护了旧版 PowerPoint 转换功能不被回归破坏。五、动手复现如何亲自把.ppt导出成这份 Markdown你可以用 docling 在本地重现与基准完全一致的输出。环境前提是安装 LibreOffice 且保证libreoffice/soffice在 PATH 中否则后端会抛出 “LibreOffice is required to convert a .ppt file to .pptx” 的 RuntimeError。from pathlib import Path from docling.document_converter import DocumentConverter from docling.datamodel.base_models import InputFormat # 只允许 PPT 输入强制走 LibreOffice 桥接链路 converter DocumentConverter(allowed_formats[InputFormat.PPT]) result converter.convert(Path(legacy_sample.ppt)) doc result.document # 与 tests/data/ppt/groundtruth/legacy_sample.ppt.md 的生成方式一致 print(doc.export_to_markdown(compact_tablesTrue))【免费下载链接】doclingGet your documents ready for gen AI项目地址: https://gitcode.com/GitHub_Trending/do/docling创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考