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

如何移除HTML字符串表格中的空列?已有空行移除代码

移除HTML表格中的空行与空列

我已经实现了移除HTML字符串内表格空行的功能,现在需要补充实现移除所有空列,需注意表格每行的单元格数量可能不一致,且要正确处理colspan属性的情况。以下是完整的解决方案代码:

let str =
  `<head></head><body><h1>table 1</h1><table><thead><tr><th><p>a1</p></th><th></th><th><p>a3</p></th><th><p>a4</p></th><th></th></tr><tr><th>b1</th><th></th><th><p>b3</p></th><th colspan="2"><p>b4</p></th></tr><tr><th>c1</th><th></th><th>c3</th><th>c4</th></tr></thead><tbody><tr><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td></tr><tr><td><p>f1</p></td><td></td><td></td><td><p>f4</p></td><td>f5</td></tr></tbody></table><p>lorem table</p><h2>table 2</h2><table><thead><tr><th><p>a1</p></th><th></th><th><p>a3</p></th><th><p>a4</p></th><th></th></tr><tr><th>b1</th><th></th><th><p>b3</p></th><th colspan="2"><p>b4</p></th></tr><tr><th>c1</th><th></th><th>c3</th><th>c4</th></tr></thead><tbody><tr><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td></tr><tr><td><p>f1</p></td><td></td><td></td><td><p>f4</p></td><td>f55</td></tr></tbody></table></body>`

const emptyCellRegex = /<(t[dh])>(\s*?)<\/\1>/g;
const cellTagRegex = /<(td|th)(.*?)>([\s\S]*?)<\/\1>/gs;

// 判断单元格是否为空
function isCellEmpty(cell) {
  emptyCellRegex.lastIndex = 0;
  return emptyCellRegex.test(cell);
}

// 解析单元格的colspan值
function getColspan(cellAttr) {
  const colspanMatch = cellAttr.match(/colspan="?(\d+)"?/);
  return colspanMatch ? parseInt(colspanMatch[1], 10) : 1;
}

// 第一步:移除空行
let tableTags = str.match(/<table.*?<\/table>/gs);
if (tableTags) {
  for (let table of tableTags) {
    let trTags = table.match(/<tr.*?<\/tr>/gs);
    if (trTags) {
      for (let tr of trTags) {
        let cells = tr.match(cellTagRegex);
        let isEmptyRow = true;
        if (cells) {
          for (let cell of cells) {
            if (!isCellEmpty(cell)) {
              isEmptyRow = false;
              break;
            }
          }
        }
        if (isEmptyRow) {
          str = str.replace(tr, '');
        }
      }
    }
  }
}

// 第二步:移除空列
tableTags = str.match(/<table.*?<\/table>/gs);
if (tableTags) {
  for (let table of tableTags) {
    let trTags = table.match(/<tr.*?<\/tr>/gs);
    if (!trTags) continue;

    // 1. 计算表格总列数(考虑colspan)
    let totalCols = 0;
    for (let tr of trTags) {
      let cells = tr.match(cellTagRegex);
      if (!cells) continue;
      let rowCols = 0;
      for (let cell of cells) {
        const attrMatch = cell.match(/<(td|th)(.*?)>/);
        const colspan = getColspan(attrMatch ? attrMatch[2] : '');
        rowCols += colspan;
      }
      if (rowCols > totalCols) totalCols = rowCols;
    }

    // 初始化列空状态:默认所有列是空的
    const emptyColumns = new Array(totalCols).fill(true);

    // 2. 遍历所有行,更新列空状态
    for (let tr of trTags) {
      let cells = tr.match(cellTagRegex);
      if (!cells) continue;
      let currentCol = 0;
      for (let cell of cells) {
        const attrMatch = cell.match(/<(td|th)(.*?)>/);
        const colspan = getColspan(attrMatch ? attrMatch[2] : '');
        const cellNotEmpty = !isCellEmpty(cell);

        // 非空单元格占用的所有列标记为非空
        if (cellNotEmpty) {
          for (let i = currentCol; i < currentCol + colspan; i++) {
            if (i < totalCols) emptyColumns[i] = false;
          }
        }
        currentCol += colspan;
      }
    }

    // 3. 收集需要保留的列索引
    const keepColumns = emptyColumns.map((isEmpty, idx) => !isEmpty ? idx : null).filter(idx => idx !== null);
    if (keepColumns.length === 0) continue;

    // 4. 重构每行的单元格,移除空列对应部分
    let newTable = table;
    for (let tr of trTags) {
      let cells = tr.match(cellTagRegex);
      if (!cells) continue;

      let newCells = [];
      let currentCol = 0;

      for (let cell of cells) {
        const attrMatch = cell.match(/<(td|th)(.*?)>([\s\S]*?)<\/\1>/);
        if (!attrMatch) continue;
        const tag = attrMatch[1];
        const attrs = attrMatch[2];
        const content = attrMatch[3];
        let colspan = getColspan(attrs);
        let cellEndCol = currentCol + colspan - 1;

        // 计算当前单元格在保留列中的有效跨度
        let validSpan = 0;
        for (let i = currentCol; i <= cellEndCol; i++) {
          if (emptyColumns[i] === false) validSpan++;
        }

        // 有效跨度大于0则保留单元格,调整colspan
        if (validSpan > 0) {
          let newAttrs = attrs;
          if (validSpan !== colspan) {
            newAttrs = newAttrs.replace(/colspan="?\d+"?/, '').trim();
            newAttrs = newAttrs ? `${newAttrs} colspan="${validSpan}"` : `colspan="${validSpan}"`;
          }
          newCells.push(`<${tag}${newAttrs ? ' ' + newAttrs : ''}>${content}</${tag}>`);
        }

        currentCol += colspan;
      }

      // 替换原行,空行直接移除
      if (newCells.length > 0) {
        const newTr = `<tr>${newCells.join('')}</tr>`;
        newTable = newTable.replace(tr, newTr);
      } else {
        newTable = newTable.replace(tr, '');
      }
    }

    // 替换原表格
    str = str.replace(table, newTable);
  }
}

console.log("处理后的HTML:", str);

关键逻辑说明

  • 空行判断:遍历每行所有单元格,只要存在非空单元格,该行就保留。
  • 列空状态标记:结合colspan计算单元格实际占用的列范围,只要某列被任意非空单元格覆盖,就标记为非空列。
  • 表格重构:对每行单元格计算其在保留列中的有效跨度,生成新的单元格并调整colspan;重构后无单元格的行直接移除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 01:15:06