HTML 转 Markdown 时 colspan 表格错列怎么办:三种修复方法与回归测试
Colspan tables shredded my HTML-to-Markdown output — Markdown can't express merged cells
作者的 HTML 转 Markdown 服务在处理含 colspan/rowspan 合并单元格的定价页时输出错列,下游 RAG 管线因此引用了错误的套餐价格。作者验证的修复包括将合并值复制到每个被覆盖单元格、对复杂 rowspan 表格原样输出 <table> HTML 并提供模式开关,回归测试还发现并修复了单元格内竖线字符未转义导致的拆列问题。
A user fed a cloud vendor's pricing page through my HTML-to-Markdown endpoint and got back a table where every plan's price sat in the wrong column. The page's comparison table used colspan for a tier header spanning three cells and rowspan for a plan name covering two rows.
My converter processed each row independently — row <td> count became pipe count. Rows under a colspan came out shorter, and whichever Markdown parser consumed the file aligned what came next with whatever column was open. A RAG pipeline downstream then quoted the wrong plan for a feature, which is how I found out: the answer looked confident and was completely wrong.
Three approaches I tried:
- Unroll colspans by duplicating the merged value into every covered cell. Ugly in source, but every parser aligns it identically. This worked.
-
Rowspan is nastier — cell offsets shift for all following rows, so duplicating values downward made a 30-row spec sheet explode into mush. For those tables I now emit the original
<table>HTML verbatim. Most renderers and LLMs handle embedded HTML tables fine, and nothing misaligns. - Knob, not heuristic-by-default: a flag lets callers force one table mode or the other. Some pipelines sanitize HTML and need pure Markdown no matter what.
The regression test caught a second bug immediately: round-trip the output through a Markdown-to-HTML renderer and compare cell counts per row against the source table. Two tables failed — cells containing literal pipe characters were splitting into two cells, shifting everything after them. Escaping | inside converted cells fixed it.
The lesson I'd pass along: Markdown's table syntax is lossy by design. It cannot represent merged cells. If fidelity matters, detect which tables can't survive the translation and route around the limitation instead of pretending the output is fine.
I shipped all of this in the converter I host as an API — same pipeline, table mode as an option, after the user who hit it asked what the fix was.
来源:Google AI:DEV 作者专属(RSS) · dev.to