# How Does OLM OCR Handle Tables in Documents? A Deep Dive into Table Parsing

> Discover how OLM OCR processes tables by translating markup into a graph structure, preserving cell coordinates, header links, and adjacencies for accurate data extraction.

- Repository: [Ai2/olmocr](https://github.com/allenai/olmocr)
- Tags: deep-dive
- Published: 2026-07-02

---

**OLM OCR handles tables by converting HTML and Markdown markup into a graph-based `TableData` structure that tracks cell coordinates, header relationships, and directional adjacencies.**

The OLM OCR pipeline extracts and normalizes tabular data from OCR-generated documents through a dedicated table parsing module. Understanding how does OLM OCR handle tables reveals a sophisticated approach to preserving document structure for downstream language modeling tasks.

## The TableData Structure

At the core of OLM OCR table parsing is the `TableData` class defined in [`olmocr/bench/table_parsing.py`](https://github.com/allenai/olmocr/blob/main/olmocr/bench/table_parsing.py) at line 9. This dataclass serves as the canonical representation for tables extracted from both HTML and Markdown sources.

### Cell Mapping and Header Tracking

The `TableData` structure maintains a coordinate-based mapping system:

- **`cell_text`**: A dictionary mapping `(row, col)` tuples to the textual content of each cell.
- **`heading_cells`**: A set containing coordinates of all header cells (equivalent to `<th>` tags in HTML or the separator row in Markdown).

This design allows OLM OCR to distinguish between data cells and structural headers regardless of the source format, enabling precise semantic understanding of tabular layouts.

### Graph-Based Navigation

Beyond simple coordinate mapping, `TableData` implements directional relationship graphs:

- **`up_relations`**, **`down_relations`**, **`left_relations`**, **`right_relations`**: These dictionaries store adjacency information between cells, accounting for complex layouts involving merged cells.

The class provides helper methods `top_heading_relations()` and `left_heading_relations()` that traverse these graphs to identify which header cells semantically "cover" a given data cell. This graph approach handles irregular table layouts where rows or columns may be missing, tracked via the `is_rectangular` flag.

## Parsing HTML Tables with Complex Layouts

The `parse_html_tables()` function starting at line 390 in [`olmocr/bench/table_parsing.py`](https://github.com/allenai/olmocr/blob/main/olmocr/bench/table_parsing.py) extracts all `<table>` elements from HTML strings and returns a list of `TableData` objects.

```python
from olmocr.bench.table_parsing import parse_html_tables

html = """
<table>
  <thead>
    <tr><th>Metric</th><th>Value</th></tr>
  </thead>
  <tbody>
    <tr><td>Precision</td><td>0.92</td></tr>
    <tr><td>Recall</td><td>0.88</td></tr>
  </tbody>
</table>
"""

tables = parse_html_tables(html)
tbl = tables[0]

print(tbl.cell_text)  # {(0,0): 'Metric', (0,1): 'Value', (1,0): 'Precision', ...}

print(tbl.heading_cells)  # {(0,0), (0,1)}

```

### Handling Rowspan and Colspan Attributes

The parser correctly interprets `rowspan` and `colspan` attributes through the `_safe_span_int` helper function. An occupancy algorithm ensures that merged cells are properly represented in the coordinate system, maintaining adjacency relationships even when physical HTML cells span multiple logical positions.

### Header Detection and Rectangularity

Cells contained within `<thead>` tags automatically populate the `heading_cells` set. The parser evaluates whether the resulting table maintains a strict rectangular grid, setting `is_rectangular` to `False` when encountering ragged rows or columns. This preserves the fidelity of irregular tables common in scanned documents while still providing navigable structure.

## Parsing Markdown Tables

For pipe-delimited Markdown tables, the `parse_markdown_tables()` function in the same module provides equivalent functionality. This parser:

1. Detects the separator row (e.g., `|---|---|`) to identify headers
2. Trims extraneous pipe characters and whitespace
3. Passes the normalized row specifications to `_build_table_data_from_specs()`, which constructs the `TableData` instance using the same internal representation as HTML tables

```python
from olmocr.bench.table_parsing import parse_markdown_tables

md = """
| Product | Price |
|---------|-------|
| Apple   | $1.00 |
| Orange  | $0.80 |
"""

md_tables = parse_markdown_tables(md)
md_tbl = md_tables[0]

print(md_tbl.left_heading_relations(2, 1))  # {(2,0)} - "Price" is left-headed by "Product" row

```

## Integration in Training and Evaluation

OLM OCR table parsing integrates directly into the model training and evaluation pipeline. As implemented in `allenai/olmocr`, the table parser serves critical functions in three key areas:

**Synthetic Data Generation**: The module [`olmocr/synth/mine_html_templates.py`](https://github.com/allenai/olmocr/blob/main/olmocr/synth/mine_html_templates.py) calls `parse_html_tables()` to extract table structures from generated HTML templates, creating structured training prompts that teach the model to recognize tabular layouts.

**Training Pipeline**: Files [`olmocr/train/grpo_train.py`](https://github.com/allenai/olmocr/blob/main/olmocr/train/grpo_train.py) and [`olmocr/train/dataloader.py`](https://github.com/allenai/olmocr/blob/main/olmocr/train/dataloader.py) invoke `parse_html_tables()` on OCR output during training. This allows the model to consume table-aware representations for downstream tasks such as table-based question answering and document understanding.

**Evaluation Metrics**: The graph-based representation enables precise comparison between predicted and ground-truth tables by comparing cell coordinates, header classifications, and adjacency relationships rather than relying on simple text matching.

## Summary

- **OLM OCR table parsing** centers on the `TableData` class in [`olmocr/bench/table_parsing.py`](https://github.com/allenai/olmocr/blob/main/olmocr/bench/table_parsing.py), which represents tables as coordinate-based cell mappings with directional adjacency graphs.
- **HTML parsing** via `parse_html_tables()` handles complex attributes like `rowspan` and `colspan`, supports header detection through `<thead>` tags, and tracks rectangularity.
- **Markdown parsing** through `parse_markdown_tables()` normalizes pipe-delimited tables into the same internal representation.
- **Integration points** include synthetic data generation ([`mine_html_templates.py`](https://github.com/allenai/olmocr/blob/main/mine_html_templates.py)) and training workflows ([`grpo_train.py`](https://github.com/allenai/olmocr/blob/main/grpo_train.py), [`dataloader.py`](https://github.com/allenai/olmocr/blob/main/dataloader.py)), enabling table-aware language modeling.

## Frequently Asked Questions

### How does OLM OCR handle merged cells in tables?

OLM OCR handles merged cells through directional relation dictionaries (`up_relations`, `down_relations`, `left_relations`, `right_relations`) in the `TableData` class. When parsing HTML, the `_safe_span_int` function interprets `rowspan` and `colspan` attributes, and the occupancy algorithm ensures adjacency relationships remain navigable even when cells span multiple rows or columns.

### What file formats does the OLM OCR table parser support?

The table parser supports both **HTML tables** (via `parse_html_tables()`) and **Markdown tables** (via `parse_markdown_tables()`). Both parsers convert input into the same `TableData` representation, allowing downstream components to process tables uniformly regardless of whether they originated from HTML-rendered PDFs or Markdown documents.

### Where is table parsing used in the OLM OCR training pipeline?

According to the source code in `allenai/olmocr`, table parsing appears in [`olmocr/train/grpo_train.py`](https://github.com/allenai/olmocr/blob/main/olmocr/train/grpo_train.py) and [`olmocr/train/dataloader.py`](https://github.com/allenai/olmocr/blob/main/olmocr/train/dataloader.py) for processing OCR output during model training, and in [`olmocr/synth/mine_html_templates.py`](https://github.com/allenai/olmocr/blob/main/olmocr/synth/mine_html_templates.py) for extracting table structures when generating synthetic training data. This enables the model to learn from structured tabular representations rather than flat text.

### Can OLM OCR parse irregular or non-rectangular tables?

Yes. The `TableData` structure includes an `is_rectangular` flag that tracks whether the table maintains a strict grid. The graph-based relation system allows navigation between cells even when rows have unequal lengths or columns are missing, preserving the semantic structure of irregular tables commonly found in scanned documents.