Skip to main content

Transform XLSX files into LLM-friendly semantic XML

Project description

xlsx2semantic

Transform XLSX into LLM-friendly semantic XML.

Raw Excel XML is unreadable — cell references like <c r="B7" t="s"><v>74</v></c> mean nothing to an LLM. xlsx2semantic converts that into structured, self-describing XML that any language model can instantly understand.

Before (raw OOXML)                          After (semantic XML)
─────────────────────                       ────────────────────
<c r="B7" s="59" t="s">                    <record row="7" state="Alabama">
  <v>74</v>                                   <total_number>745938</total_number>
</c>                                          <total_percent>100</total_percent>
<c r="C7" s="60">                           </record>
  <v>745938</v>
</c>

Why?

Problem xlsx2semantic
LLMs can't parse raw OOXML cell references Headers become tag names, data becomes readable records
Shared strings are just index numbers Automatically resolved to actual text
Merged cells break structure Propagated correctly across the grid
Multi-level headers are ambiguous Combined into hierarchical tag names
Style indices are opaque Resolved to human-readable font, color, format info
One sheet with multiple tables Structural anchors auto-detect each table region

Quick Start

Install

pip install xlsx2semantic

Python

from xlsx2semantic import parse_file

# No hints needed — tables are auto-detected
result = parse_file("enrollment.xlsx")

for sheet, xml in result.semantic_xml.items():
    print(xml)

Output:

<semantic-table>
  <title>Public school enrollment by race/ethnicity</title>
  <schema>
    <row-key index="2" attribute="state"/>
    <column index="3" tag="total_number"/>
    <column index="4" tag="total_percent"/>
  </schema>
  <records count="52">
    <record row="8" state="Alabama">
      <total_number>745938</total_number>
      <total_percent>100</total_percent>
    </record>
    <record row="9" state="Alaska">
      <total_number>132731</total_number>
      <total_percent>100</total_percent>
    </record>
  </records>
</semantic-table>

CLI

# Semantic XML (default) — auto-detects table structure
xlsx2semantic data.xlsx

# With explicit layout hints (optional override)
xlsx2semantic data.xlsx --title-range "B2:*2" --header-range "B4:*6" --row-meta-col B

# Save to file
xlsx2semantic data.xlsx -o output.xml

# Different output modes
xlsx2semantic data.xlsx --mode cell      # enriched <cell> tags
xlsx2semantic data.xlsx --mode raw-xml   # original OOXML
xlsx2semantic data.xlsx --mode all       # everything

Install CLI extras: pip install xlsx2semantic[cli]

Automatic Table Detection (Structural Anchors)

xlsx2semantic uses a SpreadsheetLLM-inspired approach to automatically detect table regions without manual hints:

  1. Cell clustering — Non-empty cells are grouped into connected regions by row/column proximity. Clusters separated by empty rows or columns become separate tables.
  2. Title detection — Full-width merged cells at the top of a region are recognized as titles.
  3. Header detection — Row heterogeneity (text/numeric ratio) identifies header rows vs data rows. Text-dominant rows at the top of a cluster become headers; the first numeric-majority row starts the data region.
  4. Multi-level header merging — Hierarchical headers across multiple rows are combined into structured tag names (e.g. 학생_수용_현황_1_신청_학생_수_1학년).
  5. Row-key auto-detection — The leftmost column that is predominantly text (>80%) while other columns are numeric is automatically identified as the row key.

Single Table

result = parse_file("report.xlsx")  # no hints needed

Multiple Tables in One Sheet

When a sheet contains multiple tables separated by empty rows or columns, each is detected independently:

<sheet>
  <semantic-table index="1">
    <schema>...</schema>
    <records count="10">...</records>
  </semantic-table>
  <semantic-table index="2">
    <schema>...</schema>
    <records count="5">...</records>
  </semantic-table>
</sheet>

Layout Hints (Optional Override)

For edge cases where auto-detection needs guidance, explicit layout hints still work:

result = parse_file(
    "report.xlsx",
    title_range="B2:*2",       # title rows (B2, cols to end of sheet)
    header_range="B4:*6",      # header area (rows 4-6, cols to end)
    row_meta_col="B",          # row label column → becomes record attribute
)
Pattern Meaning
B4:Z6 Exact range: col B–Z, row 4–6
B4:*6 Col B to end of sheet, row 4–6
B4:Z* Col B–Z, row 4 to end of sheet
B4:** Col B to end, row 4 to end

Multi-Level Header Support

Real-world spreadsheets often have hierarchical headers spanning multiple rows. xlsx2semantic merges them into a single, structured tag name — both in auto-detect mode and with explicit hints.

Original Excel layout (rows 4–6):

Row 4:  |         | Total   |         | Race/Ethnicity                    | ...
Row 5:  |         |         |         | American Indian | Asian           | ...
Row 6:  | State   | Number  | Percent | Number | Percent | Number | Percent | ...

These multi-level headers become:

<schema>
  <row-key index="2" attribute="state"/>
  <column index="3" tag="total_number"/>
  <column index="4" tag="total_percent"/>
  <column index="5" tag="race_ethnicity_american_indian_number"/>
  <column index="6" tag="race_ethnicity_american_indian_percent"/>
  <column index="7" tag="race_ethnicity_asian_number"/>
  <column index="8" tag="race_ethnicity_asian_percent"/>
</schema>

Each header level is joined with _, so the full hierarchy is preserved in a flat, LLM-readable tag name. Duplicate values from merged cells are automatically deduplicated.

Three Output Layers

xlsx2semantic gives you three views of the same spreadsheet:

Layer Description Access
Raw XML Original OOXML extracted from ZIP result.xml_entries
Cell XML <c><cell> with resolved styles, types, values result.cell_xml
Semantic XML Headers as tags, data as records result.semantic_xml

Cell XML Example

<cell ref="B7" row="7" col="2" styleIndex="59"
      font="Arial 11pt Bold" numberFormat="#,##0" fill="solid FF333399"
      type="sharedString" rawValue="74" value="Alabama"/>

Every opaque attribute is resolved:

  • t="s"type="sharedString", value="Alabama"
  • s="59"font="Arial 11pt Bold", numberFormat="#,##0"

How It Works

┌──────────┐     ┌─────────────┐     ┌──────────────┐     ┌───────────────┐     ┌──────────────┐
│ .xlsx    │────▶│ ZIP Extract │────▶│ Shared Str   │────▶│ Structural    │────▶│ Semantic     │
│ (OOXML)  │     │ Raw XML     │     │ Style Resolve│     │ Anchor Detect │     │ Transform    │
└──────────┘     └─────────────┘     └──────────────┘     └───────────────┘     └──────────────┘
                       │                    │                     │                     │
                  xml_entries           cell_xml            table regions         semantic_xml
  1. ZIP Extract — XLSX is a ZIP archive. Extract all XML entries.
  2. Shared Strings — Resolve <v>74</v>"Alabama" via sharedStrings.xml.
  3. Style Resolve — Map s="59" → font, number format, fill, alignment via styles.xml.
  4. Structural Anchor Detection — Cluster non-empty cells into table regions; detect titles, headers, data boundaries, and row-key columns.
  5. Semantic Transform — Generate semantic XML for each detected table.

Performance

  • Streaming parseriterparse instead of DOM parsing for low memory usage on large files.
  • Parallel processing — Sheets are parsed concurrently via multiprocessing when ≥2 sheets are present.

Use Cases

  • RAG pipelines — Feed structured spreadsheet data into retrieval systems
  • LLM tool use — Let agents query spreadsheet data via semantic XML
  • Data extraction — Convert messy government/financial Excel reports into clean structure
  • Spreadsheet QA — Ask natural language questions about tabular data

Development

git clone https://github.com/kangminjugit/xlsx2semantic.git
cd xlsx2semantic
pip install -e ".[dev,cli]"
pytest -v

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xlsx2semantic-0.1.3.tar.gz (26.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

xlsx2semantic-0.1.3-py3-none-any.whl (26.2 kB view details)

Uploaded Python 3

File details

Details for the file xlsx2semantic-0.1.3.tar.gz.

File metadata

  • Download URL: xlsx2semantic-0.1.3.tar.gz
  • Upload date:
  • Size: 26.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.12

File hashes

Hashes for xlsx2semantic-0.1.3.tar.gz
Algorithm Hash digest
SHA256 4d46d725d1e39f0642aa473ce922ea70dffcd61e3b55f6f7f4290eef35bc1ce4
MD5 c41d367bbb2d4a8d2dd04f17573676e0
BLAKE2b-256 797127ffdfdf347d5c72805257f4bc88ffc7bb0204bf0827161605736b5f0242

See more details on using hashes here.

File details

Details for the file xlsx2semantic-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: xlsx2semantic-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 26.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.12

File hashes

Hashes for xlsx2semantic-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 e781c0ea653f6d24c59e9b189f3e112c2daee74357ac190bfd1c31fb253fd97e
MD5 83e102e39797b3b19931a2055a956a57
BLAKE2b-256 dad726191a09ef75626c53482f9aa6216fc145dbe58c21f95716c75378554bab

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page