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

如何用正则从压缩后的HTML字符串中移除表格空行与空列?

移除压缩HTML字符串中表格的空行与空列

解决思路

直接用正则处理HTML容易因为嵌套标签、colspan等属性出错,最佳方案是借助浏览器的DOM解析能力,先把字符串转成DOM结构,再遍历表格处理空行和空列,最后转回压缩后的HTML字符串。

完整实现代码

let htmlString =
`
<h2>lorem</h2><table style="width:100%"><tr><th>Company</th><th></th><th>Country</th></tr><tr><td>Alfreds Futterkiste</td><td></td><td>Germany</td></tr><tr><td>Centro comercial Moctezuma</td><td></td><td>Mexico</td></tr><tr><td></td><td></td><td></td></tr></table><p>Lorem ipsum dolor quas!</p><p>Lorem ipsum dolor</p>
`
// complex example:
let htmlString2 =
`
<table><thead><tr><th><p>xyz</p></th><th></th><th><p><strong>2019</strong></p></th><th><p><strong>2018</strong></p></th><th></th></tr><tr><th></th><th></th><th><p><strong>xyz</strong></p></th><th colspan="2"><p><strong>xyz</strong></p></th></tr><tr><th></th><th></th><th></th><th></th></tr></thead><tbody><tr><td><p><strong>x</strong></p></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><strong>xyz</strong></p></td><td></td><td><p><strong>359,423</strong></p></td><td><p>349,380</p></td><td></td></tr></tbody></table>
`

const removeEmptyColumnAndRow = (htmlString) => {
  // 创建DOM解析器
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlString, 'text/html');

  // 遍历所有表格
  doc.querySelectorAll('table').forEach(table => {
    // 第一步:移除所有空行(所有单元格文本为空的行)
    const rows = Array.from(table.querySelectorAll('tr'));
    rows.forEach(row => {
      const cells = Array.from(row.querySelectorAll('th, td'));
      const isEmpty = cells.every(cell => cell.textContent.trim() === '');
      if (isEmpty) row.remove();
    });

    // 获取处理空行后的有效行
    const validRows = Array.from(table.querySelectorAll('tr'));
    if (validRows.length === 0) return;

    // 第二步:标记所有空列
    // 先计算表格总列数(考虑colspan)
    let totalColumns = 0;
    validRows[0].querySelectorAll('th, td').forEach(cell => {
      totalColumns += parseInt(cell.getAttribute('colspan')) || 1;
    });
    const columnIsEmpty = new Array(totalColumns).fill(true);

    // 遍历所有行,更新列的空状态
    validRows.forEach(row => {
      let currentCol = 0;
      const cells = Array.from(row.querySelectorAll('th, td'));
      cells.forEach(cell => {
        const colspan = parseInt(cell.getAttribute('colspan')) || 1;
        // 只要单元格有内容,它覆盖的列都不为空
        if (cell.textContent.trim() !== '') {
          for (let i = currentCol; i < currentCol + colspan; i++) {
            if (i < columnIsEmpty.length) columnIsEmpty[i] = false;
          }
        }
        currentCol += colspan;
      });
    });

    // 第三步:移除空列,同时调整colspan属性
    validRows.forEach(row => {
      let currentCol = 0;
      const cells = Array.from(row.querySelectorAll('th, td'));
      const keepCells = [];

      cells.forEach(cell => {
        const colspan = parseInt(cell.getAttribute('colspan')) || 1;
        // 计算当前单元格覆盖的非空列数量
        let nonEmptyCount = 0;
        for (let i = currentCol; i < currentCol + colspan; i++) {
          if (i < columnIsEmpty.length && !columnIsEmpty[i]) nonEmptyCount++;
        }

        // 有非空列则保留单元格,调整colspan
        if (nonEmptyCount > 0) {
          if (nonEmptyCount !== colspan) {
            cell.setAttribute('colspan', nonEmptyCount);
          }
          keepCells.push(cell);
        }
        currentCol += colspan;
      });

      // 更新行内容
      row.innerHTML = '';
      keepCells.forEach(cell => row.appendChild(cell));
      // 如果处理后行变为空,移除它
      if (row.children.length === 0) row.remove();
    });
  });

  // 将处理后的DOM转回压缩的HTML字符串
  return doc.body.innerHTML.replace(/\s+/g, '');
}

console.log(removeEmptyColumnAndRow(htmlString));

关键细节说明

  • 空行判断:遍历行内所有<th>和<td>,只有当所有单元格的文本内容(去除空格后)都为空时,才移除该行。
  • 空列判断:考虑colspan属性的影响,一个单元格可能覆盖多列,只要该单元格有内容,它覆盖的所有列都标记为非空。
  • colspan调整:移除空列后,自动调整剩余单元格的colspan值,保证表格结构不被破坏。
  • 压缩输出:最后用正则替换掉所有空白字符,保持原HTML的压缩格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:15:24