Duck Observations

发布时间:2026/9/8 23:31:08
Duck Observations Duck Observations【免费下载链接】doclingGet your documents ready for gen AI项目地址: https://gitcode.com/GitHub_Trending/do/docling| Number of freshwater ducks per year | | - || Year | Freshwater Ducks | | - | - | | 2019 | 120 | | 2020 | 135 | | 2021 | 150 | | 2022 | 170 | | 2023 | 160 | | 2024 | 180 |可以看出工作表名被序列化为一个二级标题而正文内容**不是一整张大表**而是被切分成了“一个 1×1 的标题表格”和“一个 7×2 的数据表格”两个独立的 TableItem。这正是 Docling Excel 后端区域探测算法的直接体现。 ## 二、为什么标题没有变成正文文本而是成为一张 1×1 表格 很多读者第一眼会疑惑Number of freshwater ducks per year 明显是个标题为什么在默认输出里它表现为一张孤零零的 1×1 表而不是一段文本 答案藏在 Excel 后端的两个行为中 1. **断连区域会被解析成不同表格**。在 [msexcel_backend.py](https://link.gitcode.com/i/4df4451c4f2f781193a9cef8aec7168c) 的类文档字符串中写明“Cell contents, parsed as tables. If two groups of cells are disconnected between each other, they will be parsed as two different tables.” 结合 JSON 真值中两张表的 prov.bbox 可以发现标题簇占据 t1 → b2数据表簇占据 t3 → b10两者之间存在一整行的空隙。因此基于 Flood FillBFS的连通域探测把该工作表识别为**两个互不连通的单元格簇**各生成一张 TableItem。 2. **treat_singleton_as_text 默认是 False**。在 [MsExcelBackendOptions](https://link.gitcode.com/i/e1b6476442423a2c4ae7f1f65672804b) 中该选项被定义为 python treat_singleton_as_text: bool Field( False, description( Whether to treat singleton cells (1x1 tables with empty neighboring cells) as TextItem instead of TableItem. ), )因为后端默认并不启用该选项所以被孤立出来的 1×1 标题簇不会升级为TextItem而是保持为一张 1×1 的TableItem。对应逻辑位于 msexcel_backend.py只有当treat_singleton_as_textTrue且该表恰好只有一个数据单元格时才会通过doc.add_text(...)把它输出为正文文本。这也解释了为什么 Markdown 真值第一行会出现单列表格| Number of freshwater ducks per year | | - |这是一张“只有表头、没有数据行”的紧凑型单列表它的唯一单元格位于第 0 行column_header: true序列化后生成表头行再用| - |作为分隔行。三、从 JSON 真值看懂单元格语义标注阅读 xlsx_05_table_with_title.xlsx.json 可以从内部结构上验证上述行为文档body下只有一个groups/0其name为Duck Observations、label为sheet即整个工作表被建模为一个 sheet 分组GroupItem这正是 Markdown 中## Duck Observations标题的来源texts数组为空——说明在默认选项下没有产生任何正文文本tables数组包含两张表tables/01 行 1 列单元格文本为Number of freshwater ducks per year语义标志为column_header: true因为该单元格位于第 0 行没有合并跨行跨列row_span/col_span均为 1tables/17 行 2 列。首行Year、Freshwater Ducks均被标注为column_header: true其后 2019–2024 共 6 行数值单元格的column_header均为false。单元格层面的column_header/row_header/row_section布尔标志正是 Docling 在文档中保留的表格语义元数据。它来自后端的建表逻辑在 msexcel_backend.py 中每个 Excel 单元格被转换为TableCell时执行column_headerexcel_cell.row 0——即只要单元格处于第 0 行就被视为列头。这让数据表的表头行与普通数据行在结构化层面得到明确区分为后续面向 RAG 的切片、表格导出乃至 HTML 渲染提供了可靠依据。四、从 itxt 真值看文档层级xlsx_05_table_with_title.xlsx.itxt 用缩进文本直观呈现了同一份文档的树形结构item-0 at level 0: unspecified: group _root_ item-1 at level 1: sheet: group Duck Observations item-2 at level 2: table with [1x1] item-3 at level 2: table with [7x2]它验证了三个关键信息整个工作表内容都挂在一个sheet分组下该分组直接包含两张表格子节点两张表的尺寸分别是[1x1]与[7x2]与 Markdown/JSON 真值完全一致。对于希望调试“为什么我的表被拆开了”的读者itxt是比 JSON 更快的定位工具。五、真值文件如何在测试中被使用tests/data/xlsx/groundtruth/下的三份产物会被 test_backend_msexcel.py 中的两处测试消费5.1 端到端回归测试默认选项test_e2e_excel_conversions见 test_backend_msexcel.py用默认DocumentConverter依次转换tests/data/xlsx/sources/下所有工作簿然后使用 docling_core 的MsExcelMarkdownDocSerializer以MarkdownParams(compact_tablesTrue, layersDEFAULT_CONTENT_LAYERS)序列化 Markdown并与.md真值比对使用doc._export_to_indented_text(...)与.itxt真值比对使用verify_document(..., fuzzyTrue)与.json真值比对。因为默认转换没有启用treat_singleton_as_text标题单元格被保留成 1×1 表格所以.md真值中出现两张表——这与默认 e2e 的比对设定是自洽的。5.2 选项行为测试开启 treat_singleton_as_texttest_table_with_title见 test_backend_msexcel.py则专门验证反向行为显式构造MsExcelBackendOptions(treat_singleton_as_textTrue)并注入ExcelFormatOption后再转换同一文件此时断言结果变为assert len(doc.texts) 1 # 标题变成了一个 TextItem assert len(doc.tables) 1 # 只剩 7x2 的数据表 assert doc.texts[0].text Number of freshwater ducks per year assert table.data.num_rows 7 and table.data.num_cols 2对照读这两处测试就能完整理解同一份源文件在不同选项下“标题究竟是正文还是表”的输出差异也说明了真值文件.md默认选项与test_table_with_title开启选项并不矛盾而是覆盖了两种合法配置。六、自己动手复现与验证在仓库环境中可用以下方式复现该真值默认选项下应得到与.md文件一致的输出from docling.document_converter import DocumentConverter from docling.datamodel.base_models import InputFormat converter DocumentConverter(allowed_formats[InputFormat.XLSX]) result converter.convert( tests/data/xlsx/sources/xlsx_05_table_with_title.xlsx ) doc result.document print(doc.export_to_markdown()) print(doc._export_to_indented_text(max_text_len70, explicit_tablesFalse))如需复现“标题升级为正文文本”的路径把MsExcelBackendOptions通过ExcelFormatOption传入即可from docling.document_converter import DocumentConverter, ExcelFormatOption from docling.datamodel.base_models import InputFormat from docling.datamodel.backend_options import MsExcelBackendOptions options MsExcelBackendOptions(treat_singleton_as_textTrue) converter DocumentConverter( allowed_formats[InputFormat.XLSX], format_options{InputFormat.XLSX: ExcelFormatOption(backend_optionsoptions)}, ) doc converter.convert( tests/data/xlsx/sources/xlsx_05_table_with_title.xlsx ).document print(list(doc.texts)[0].text) # Number of freshwater ducks per year print(list(doc.tables)[0].data.num_rows, x, list(doc.tables)[0].data.num_cols)【免费下载链接】doclingGet your documents ready for gen AI项目地址: https://gitcode.com/GitHub_Trending/do/docling创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考