You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用纯JavaScript将含rowspan/colspan的复杂HTML表格转JSON?

解决方案:复杂HTML表格转指定格式JSON的纯JavaScript实现

核心思路

  1. 先区分表头行与数据行,分别解析两类行的单元格信息,包括文本内容、rowspan和colspan属性
  2. 通过维护待填充队列,将跨行列的单元格内容自动填充到对应位置,生成完整的二维网格
  3. 为每个数据单元格匹配对应列的所有表头文本,用/拼接成JSON键,最终生成目标格式的JSON

实现代码

function tableToJson(tableElement) {
  const rows = Array.from(tableElement.querySelectorAll('tr'));
  const headerRows = [];
  const dataRows = [];
  const result = {};

  // 分离表头行和数据行
  rows.forEach(row => {
    row.querySelector('th') ? headerRows.push(row) : dataRows.push(row);
  });

  // 生成展开后的表头网格和数据网格
  const headerGrid = buildFullGrid(headerRows, true);
  const dataGrid = buildFullGrid(dataRows, false);

  // 为每个数据单元格生成表头拼接键并组装JSON
  dataGrid.forEach((row, rowIdx) => {
    row.forEach((cellText, colIdx) => {
      if (!cellText || cellText.trim() === '') return;
      // 收集当前列的所有有效表头文本
      const headerSegments = headerGrid
        .map(headerRow => headerRow[colIdx]?.trim())
        .filter(Boolean);
      const key = headerSegments.join('/');
      result[key] = cellText.trim();
    });
  });

  return result;
}

// 处理rowspan/colspan,生成完整的二维单元格网格
function buildFullGrid(rows, isHeader) {
  const grid = [];
  // 存储待向下填充的跨行列单元格信息
  const pendingCells = [];

  rows.forEach((row, rowIdx) => {
    const currentRow = [];
    let colIdx = 0;

    // 先处理从上一行遗留的待填充单元格
    while (pendingCells.length > 0) {
      const pending = pendingCells[0];
      if (pending.targetRow !== rowIdx || pending.targetCol > colIdx) break;

      currentRow[colIdx] = pending.content;
      pending.remainingRows--;
      pending.remainingCols--;

      if (pending.remainingRows <= 0 && pending.remainingCols <= 0) {
        pendingCells.shift();
      } else if (pending.remainingCols <= 0) {
        pending.targetCol = colIdx + 1;
        pending.remainingCols = pending.originalColspan - 1;
      }
      colIdx++;
    }

    // 处理当前行的原始单元格
    const cells = Array.from(row.querySelectorAll(isHeader ? 'th' : 'td'));
    cells.forEach(cell => {
      const content = cell.textContent.trim();
      const rowspan = parseInt(cell.getAttribute('rowspan')) || 1;
      const colspan = parseInt(cell.getAttribute('colspan')) || 1;

      // 填充当前单元格占据的所有列
      for (let c = 0; c < colspan; c++) {
        currentRow[colIdx + c] = content;
      }

      // 如果需要跨多行/列,添加到待填充队列
      if (rowspan > 1 || colspan > 1) {
        pendingCells.push({
          targetRow: rowIdx + 1,
          targetCol: colIdx,
          content,
          remainingRows: rowspan - 1,
          remainingCols: colspan - 1,
          originalColspan: colspan
        });
      }

      colIdx += colspan;
    });

    // 补全行内空缺的单元格,保证每行列数一致
    while (colIndex < currentRow.length) {
      currentRow[colIdx] = '';
      colIdx++;
    }

    grid.push(currentRow);
  });

  // 统一所有行的列数,避免列数不一致的问题
  const maxColCount = Math.max(...grid.map(row => row.length));
  return grid.map(row => {
    while (row.length < maxColCount) row.push('');
    return row;
  });
}

// 使用示例
// const targetTable = document.querySelector('table');
// const jsonOutput = tableToJson(targetTable);
// console.log(jsonOutput);

关键说明

  • 网格构建逻辑:核心是buildFullGrid函数,通过待填充队列自动处理跨行列的内容传播,将不规则的表格结构展开成规整的二维网格,解决rowspan/colspan的适配问题
  • 表头拼接规则:每个数据单元格对应表头网格同一列的所有非空文本,用/拼接成唯一键,完美匹配多级表头的需求
  • 通用性:不依赖特定表格结构,只要是标准HTML表格标签(<table>/<tr>/<th>/<td>),就能处理任意组合的跨行列场景

内容的提问来源于stack exchange,提问作者Lance Pollard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 10:05:29