pub struct Table {
pub rows: Vec<Vec<String>>,
pub location: Option<[u16; 4]>,
pub structure: Option<TableStructure>,
pub cell_blocks: Option<Vec<Vec<Vec<Node>>>>,
pub caption: Option<String>,
pub caption_parent: CaptionParent,
pub caption_location: Option<[u16; 4]>,
pub cells: Option<Vec<TableCell>>,
}Expand description
A simple row-major table. By default rows[0] is the header row; a
TableStructure overlay overrides that and adds column spans.
Fields§
§rows: Vec<Vec<String>>§location: Option<[u16; 4]>Optional layout provenance: the four DocLang <location> values
(x0,y0,x1,y1, each already normalized to the 0–511 resolution) emitted
before the table’s cells. Set only by backends with real geometry (e.g.
the spreadsheet backend, whose cell grid yields a bounding box); left
None by declarative backends, which have no coordinates.
structure: Option<TableStructure>Optional OTSL structure overlay for backends that parse real table
geometry (USPTO CALS): explicit header-row count and horizontal-span
continuations. None → the default (row 0 is the header, no spans).
rows still carries the full text grid (span text replicated) for
Markdown/JSON; DocLang uses this overlay to emit <ched/>/<lcel/>.
cell_blocks: Option<Vec<Vec<Vec<Node>>>>Optional per-cell block content, parallel to rows. A rich cell (an
ODF cell holding a list, several paragraphs, or a nested table) carries
its DocLang blocks here; the DocLang serializer emits them after the
cell token instead of the flat rows text. Markdown/JSON ignore this
and render rows, so their output is unchanged. None (or an empty
Vec for a given cell) → the flat text is used everywhere.
caption: Option<String>Optional caption (docling’s TableItem.captions): the JATS
<table-wrap> label+caption, an HTML <caption>, etc. Markdown renders
it as a text line before the grid; JSON emits a caption text item the
table references; DocLang emits a <caption> as the table’s first child.
None → the table has no caption.
caption_parent: CaptionParentWhere the caption item hangs in the JSON tree (#390); see
CaptionParent. Only the JSON export reads it.
caption_location: Option<[u16; 4]>The caption’s own box on the table’s page (0–511 grid) — the PDF
pipeline’s caption layout region, written as the caption item’s
prov (#609); see Node::Picture’s field of the same name.
cells: Option<Vec<TableCell>>Optional per-cell bounding boxes, same shape as Self::rows: [l, t, r, b] in page points with a top-left origin (the PDF pipeline’s
native space). Set by the ML pipeline’s TableFormer paths — a spanned
cell repeats its anchor’s box across the covered grid positions — and
First-class cells (#240): the authoritative per-cell records —
text, page geometry, spans and header roles — when the backend
produces them (the PDF TableFormer paths do; declarative backends
leave None). Self::rows stays the dense text grid every
serializer renders (a spanning cell’s text is replicated across its
covered positions there); JSON serializes these cells verbatim when
present, and the DocLang structure overlay is derived from them.
Implementations§
Source§impl Table
impl Table
Sourcepub fn cell_text(&self, row: usize, col: usize) -> Option<&str>
pub fn cell_text(&self, row: usize, col: usize) -> Option<&str>
A cell’s text at a grid position, None outside the grid.
Sourcepub fn set_cell_text(
&mut self,
row: usize,
col: usize,
text: impl Into<String>,
) -> bool
pub fn set_cell_text( &mut self, row: usize, col: usize, text: impl Into<String>, ) -> bool
Replace the text at a grid position; false (and no change) outside
the grid. When a first-class cell covers the position, the whole
cell is updated: its record text and every grid position its span
covers, so the repair shows once in Markdown, not once per covered
column.
Sourcepub fn derive_cells(&self) -> Vec<TableCell>
pub fn derive_cells(&self) -> Vec<TableCell>
Derive first-class cells (#240) from the dense grid plus the
TableStructure overlay — how declarative tables (DOCX/XLSX merged
regions, HTML th/spans, ODF covered cells, USPTO CALS) get real
TableCell records without page geometry. Anchors are the positions
not marked as span continuations; extents scan the continuation grids
right/down (matching the DocLang lcel/ucel reading). Header roles
come from the per-cell col_header/row_header grids when present,
else the header_row band, else docling’s declarative default (row 0
is the header). Without any overlay every position is a 1×1 cell.
Sourcepub fn column_header_row_count(&self) -> usize
pub fn column_header_row_count(&self) -> usize
The number of leading grid rows that form the column header block —
docling-core’s TableData._count_column_header_rows (docling-core#767,
2.102, #778), shared by the Markdown serializer
(Self::header_row_count) and the chunker’s dataframe view, which
must agree on where the header ends. Uses the first-class
Self::cells when present (the PDF pipeline’s TableFormer flags),
else the cells derived from the structure overlay.
- A row counts only when a
column_headercell starts on it (docling-core#723): a header spanning several rows is replicated into each row it covers, and counting those would pull the data rows beneath it into the header block. - A row also stops the block when it carries body text (#604,
docling-core#766): a cell starting on it that is not a column
header, has non-blank text and does not start in the table’s first
column, which holds row labels left unmarked even on header rows. A
scanned form flags its first-column labels
column_headeron every row; without the check each such row folded its values into the header. - Row 0 is exempt from that check — model-predicted header rows are often only partly flagged — unless a later row flags a cell starting in the first column: that marks a column of row headers, not a partly flagged header row.
No fallback: a table without flags has no header rows here.
Sourcepub fn header_row_count(&self) -> usize
pub fn header_row_count(&self) -> usize
The number of leading grid rows the Markdown serializer renders as the
header — docling-core’s _count_header_rows:
Self::column_header_row_count, plus upstream’s row-0 fallback for
GFM, which needs a header row: 1 when no flag sits on any grid row
below the first (a spanning header cell counts on every row it
covers), so tables from backends that never set the flag keep row 0
as the header. When flags exist but none makes a header row, the
count is 0 and every row stays in the body under an empty header.
Sourcepub fn span_anchors(&self) -> Vec<Vec<(usize, usize)>>
pub fn span_anchors(&self) -> Vec<Vec<(usize, usize)>>
For every grid position, the position of the cell that covers it — its
anchor (top-left start): itself for an unmerged position, the merge’s
start for one a spanning cell covers. Uses the first-class
Self::cells when present, else the cells derived from the
structure overlay. A rich cell’s blocks (Self::cell_blocks) live on
its anchor only, so a serializer that repeats a merged cell in every
position it covers (docling-core#857) reads them through this.
Sourcepub fn cell_at(&self, row: usize, col: usize) -> Option<&TableCell>
pub fn cell_at(&self, row: usize, col: usize) -> Option<&TableCell>
The first-class cell covering a grid position, if any.
Sourcepub fn cell_bbox(&self, row: usize, col: usize) -> Option<[f32; 4]>
pub fn cell_bbox(&self, row: usize, col: usize) -> Option<[f32; 4]>
A cell’s bounding box ([l, t, r, b], page points, top-left origin);
None when no cell with geometry covers the position.
Sourcepub fn set_cell_bbox(&mut self, row: usize, col: usize, bbox: [f32; 4]) -> bool
pub fn set_cell_bbox(&mut self, row: usize, col: usize, bbox: [f32; 4]) -> bool
Set (or replace) the bounding box of the cell covering a grid
position; false outside the text grid. A table without first-class
cells materializes them first (one 1×1 cell per grid position, texts
from the grid), so declarative tables can be annotated too.
Sourcepub fn find_cell_by_bbox(&self, bbox: [f32; 4]) -> Option<(usize, usize)>
pub fn find_cell_by_bbox(&self, bbox: [f32; 4]) -> Option<(usize, usize)>
The anchor position of the cell whose box overlaps bbox best
(largest intersection-over-union), ties resolved in cell order.
None when nothing overlaps or the table carries no geometry. This
is the lookup half of the repair workflow: find the cell an external
OCR box refers to, then Self::set_cell_text it.