HTML & web

HTML’s rowspan and colspan, how to expand them into a two-dimensional table

When you are working with an HTML document that contains complex table headers, directly extracting<td>text often yields corrupted data. A setting withrowspan="

阅读文本 / Reading text
This paper uses synthetic samples to demonstrate the processing method. The code has been verified using examples in an isolated environment; this does not guarantee effectiveness for all real files or products. Before processing important files, please retain the original copies and verify them against the boundaries and acceptance criteria specified in the text. When you are working with an HTML document that contains complex table headers, directly extracting <td> text often yields corrupted data. A setting with rowspan="3" The cell appears only once in the DOM tree, but it occupies three rows in the logical table. If subsequent code assumes that each row has the same number of columns, the program will either throw an index-out-of-bounds exception or incorrectly concatenate data belonging to the next row with the current row. An even more insidious risk is memory explosion: malicious or corrupted HTML might declare a colspan="99999" , if the script blindly allocates memory, it will exhaust resources in an instant. The core of solving this problem is not to look for some off-the-shelf “table-to-CVS” magic function, but rather to manually maintain a state machine for a two-dimensional grid. You need to scan the DOM nodes line by line while keeping track of which coordinates have already been occupied by above‑lying merged cells. When you encounter an occupied coordinate, skip it; when you come across a new cell, fill multiple grid positions according to its span attribute. This process must include explicit checks on size constraints, shifting the parsing behavior from “trusting input” to “defensive validation.” synthesis example and boundary condition design To verify the correctness of the expansion logic, we need to construct a minimal yet complete synthetic HTML sample. This sample should not be derived from real-world business data but should instead be specifically designed to cover critical paths. The correct input should encompass three typical cases: ordinary cells, horizontal merging (colspan), and vertical merging (rowspan). For example, in a 3-row-by-3-column logical table, the first cell in the first row rowspan="2" , the second cell in the second row colspan="2" . The expected output is a standard two-dimensional list, with the positions that have been merged and overwritten filled with None or a specific placeholder, rather than leaving it blank and causing inconsistent row lengths. For the example above, the value in the first column of the second row should be identical to that in the first column of the first row (since it is a rowspan continuation), while the second and third columns of the second row should contain values; similarly, the first column of the third row should also continue the value from the first row. errors or boundary inputs are equally important. Consider a statement that declares colspan="10000" but in reality, the table contains only 3 columns of data, or rowspan exceeds the actual number of rows in the table. There are even more challenging conflicts: two cells have span ranges that logically overlap, which typically indicates an error in the HTML source itself. When handling such inputs, the code should neither crash nor silently accept them. A reasonable strategy is to set a maximum grid threshold (e.g., 1000x1000); once the computed target dimensions exceed this value, immediately throw a clear exception or return partial results along with a warning. For overlapping conflicts, one can choose to prioritize the earlier-appearing cell, ignore the later illegal overwrite, and log the coordinate conflict. Python implementation with protection mechanism The following example uses BeautifulSoup to parse HTML and expand tables. It does not rely on any third-party table-specific libraries, instead relying entirely on DOM traversal and coordinate state management. Note: This code is for instructional demonstration and must be used after locking beautifulsoup4 Run in a standalone environment of the specified version; the example uses only an in-memory HTML string and does not involve network requests, file deletions, or credential operations. If you need to process external files, first read the file contents into a string variable and pass it in. from bs4 import BeautifulSoup def expand_html_table(html_content, max_rows=1000, max_cols=1000): """ 将含rowspan/colspan的HTML表格展开为二维列表。 包含网格尺寸防护,防止恶意或错误标签导致内存溢出。 """ soup = BeautifulSoup(html_content, 'html.parser') table = soup.find('table') if not table: return [] grid = [] rows = table.find_all('tr') for r_idx, tr in enumerate(rows): if r_idx >= max_rows: raise ValueError(f"表格行数超过安全上限 {max_rows}") # 确保当前行存在 while len(grid) <= r_idx: grid.append([]) c_idx = 0 cells = tr.find_all(['td', 'th']) for cell in cells: # 找到下一个未被占用的列位置 while c_idx < len(grid[r_idx]) and grid[r_idx][c_idx] is not None: c_idx += 1 # 防御性解析:非数字属性默认为1 try: colspan = int(cell.get('colspan', 1)) rowspan = int(cell.get('rowspan', 1)) except (ValueError, TypeError): colspan, rowspan = 1, 1 text = cell.get_text(strip=True) # 安全检查:防止单个单元格撑爆网格 if c_idx + colspan > max_cols or r_idx + rowspan > max_rows: raise ValueError( f"单元格跨度({rowspan}x{colspan})在位置({r_idx},{c_idx})" f"超出安全网格{max_rows}x{max_cols}" ) # 填充所有被该单元格覆盖的坐标 for i in range(rowspan): target_row = r_idx + i while len(grid) <= target_row: grid.append([]) for j in range(colspan): target_col = c_idx + j while len(grid[target_row]) <= target_col: grid[target_row].append(None) # 仅当目标位置为空时才写入(处理冲突) if grid[target_row][target_col] is None: grid[target_row][target_col] = text c_idx += colspan return grid # 合成测试用例(仅用于验证逻辑,非生产实测) TEST_HTML = """ <table> <tr><td rowspan="2">A</td><td>B</td><td>C</td></tr> <tr><td colspan="2">D</td></tr> <tr><td>E</td><td>F</td><td>G</td></tr> </table> """ result = expand_html_table(TEST_HTML) assert result == [ ['A', 'B', 'C'], ['A', 'D', 'D'], ['E', 'F', 'G'] ], f"展开结果不符合预期: {result}" The key to this code lies in its double-layered safeguard: the outer loop checks the total number of rows, while the inner loop verifies, before populating a cell, whether the span of that individual cell would cause the grid to exceed its bounds. while dynamically expands rows and columns in a loop, thereby avoiding the risk of pre-allocating extremely large arrays. Assertion statements verify the expected output of synthetic examples, but this only confirms that the logic is correct for the current input; it does not guarantee that the implementation has been validated through empirical testing on a variety of real-world documents. Acceptance Criteria and Manual Review Thresholds code can successfully run the synthetic example, but that does not mean it can handle dirty data in a production environment. The table below summarizes common observations encountered in real-world document processing and the corresponding handling decisions, distinguishing between issues that can be resolved automatically and scenarios requiring manual intervention. Observation of the phenomenon automatic processing decision Cases requiring manual review The rowspan/colspan value is a non-numeric string is treated as 1 by default, and warning logs are recorded This type of issue frequently occurs in the same table, suspected to be due to OCR recognition errors or template corruption cell span causes inconsistency in the number of logical columns is based on the maximum number of columns, with short rows padded with None The number of columns differs from the expected range (e.g., >30%), which may indicate that the table structure has been corrupted nested table (table within td) Only expand the outermost table, leaving the inner HTML fragments intact. business semantics depend on nested table content, requiring a customized recursive expansion strategy grid size has reached the safety threshold throws an exception, refusing to process this table After confirming that it is a legitimate oversized table rather than malicious input, adjust the parameters and retry. merged cell text contains newline characters retains the original line breaks and is not cleaned up Whether a newline character is typesetting noise or a structured-data delimiter depends on the context. Note that this table describes the behavioral boundaries of the parsing logic, not a guarantee of end-to-end translation quality. The code demonstration only verifies the correctness of coordinate expansion; actual acceptance testing requires comparing against the original document’s visual layout to ensure that critical data points have not been lost or misaligned during the conversion process. References and Next Steps Beautiful Soup official documentation: https://www.crummy.com/software/BeautifulSoup/bs4/doc/#navigating-the-tree HTML Table Specification (MDN): Understanding the Valid Values of rowspan/colspan and Browser Tolerance Behaviors Next steps: Run the above code using your own de-identified HTML sample, and record the types and frequencies of exceptions triggered. If boundary issues occur frequently, evaluate whether to switch to a platform-based processing solution. uses this checklist for document translation The body text, links, code, and structure of the web document should be processed separately. Include the protected sections in the acceptance checklist, then evaluate the post-translation readability and page display. OmniDoc (product entry point) provides an entry point for translating multi-format documents, and the official website highlights its OCR, terminology database, and bilingual alignment features. For teams that prefer to start processing directly from files, this is a path worth evaluating with real-world samples. Please use de-identified files that you are authorized to upload, and verify the results against the checklist provided in this document; we do not claim that OmniDoc utilizes the open-source libraries or internal algorithms referenced herein, nor do we substitute examples for formal product performance testing. - 1 -
Updated 2026-10-08