typescript 在JavaScript中如何解析HTML字符串转换为表格数据(2d数组)

kx5bkwkv  于 6个月前  发布在  TypeScript
关注(0)|答案(1)|浏览(88)

我喜欢在客户端解析html字符串。我们使用带有TypeScript的React作为前端框架。在解析html的同时,我还喜欢获取与元素关联的样式。它可以是内联样式,继承自父元素或在head部分的样式标记中使用某个类定义(没有外部css文件引用)。我们的目标是解析html字符串并将其转换为具有backgroundColor,textColor,fontSize等样式的表格格式数据。
我知道DOMParser可以用来解析html字符串。我们可以使用隐藏的iFrame来加载html文档并获得每个元素的计算样式。
我想知道在这种情况下是否有其他的库可以帮助我们?还有,有没有其他的方法可以在不使用iframe的情况下获得样式,因为我们喜欢使用web worker来计算html解析?
第一个月

<html>
  <head>
    <style>
      li {
        color: red;
      }

      .highlight {
        background-color: yellow;
      }
    </style>
  </head>
  <body>
    <!--StartFragment-->
    <h1>The ol and ul elements</h1>

    <h1>The ol and ul elements</h1>
    <p style="font-size: 16px">The ol element defines an ordered list:</p>
    <ol>
      <li>Coffee</li>
      <li>Tea</li>
      <li>Milk</li>
    </ol>

    <p class="highlight">The ul element defines an unordered list:</p>
    <ul>
      <li>Coffee</li>
      <li>Tea</li>
      <li>Milk</li>
    </ul>
    <h1>The table element</h1>

    <table>
      <tbody>
        <tr>
          <th>Month</th>
          <th>Savings</th>
        </tr>
        <tr>
          <td>January</td>
          <td>$100</td>
        </tr>
        <tr>
          <td>February</td>
          <td>$80</td>
        </tr>
      </tbody>
    </table>
    <!--EndFragment-->
  </body>
</html>

字符串
解析后,预期的输出将是一个JavaScript对象数组,其中的每一项都将具有从html字符串解析而来的文本和样式属性。最后,这个2d数组将被处理并用于呈现为表格结构。
x1c 0d1x的数据
非常感谢任何帮助或指导。提前感谢!

3duebb1j

3duebb1j1#

这可以使用一点DOM Manipulation和JS来完成。我决定用JS来实现这一点,但这段代码可以很容易地修改为与react一起使用。考虑下面的代码。

function getDocumentFromString() {
  const sampleHtmlString = `
<html>
  <head>
    <style>
      li {
        color: red;
      }

      .highlight {
        background-color: yellow;
      }
    </style>
  </head>
  <body>
    <!--StartFragment-->
    <h1>The ol and ul elements</h1>

    <p style="font-size: 16px">The ol element defines an ordered list:</p>
    <ol>
      <li>Coffee</li>
      <li>Tea</li>
      <li>Milk</li>
    </ol>

    <p class="highlight">The ul element defines an unordered list:</p>
    <ul>
      <li>Coffee</li>
      <li>Tea</li>
      <li>Milk</li>
    </ul>
    <h1>The table element</h1>

    <table>
      <thead>
        <tr>
          <th>Month</th>
          <th>Savings</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>January</td>
          <td>$100</td>
        </tr>
        <tr>
          <td>February</td>
          <td>$80</td>
        </tr>
      </tbody>
    </table>
    <!--EndFragment-->
  </body>
</html>
`;

  const domParser = new DOMParser();
  const strDocument = domParser.parseFromString(sampleHtmlString, 'text/html');

  return strDocument;
}

function getInlineStyles(element) {
  const styles = Array.from(element.style);
  return styles.reduce((acc, curr) => acc.concat(`${curr}:${element.style[curr]};`), '');
}

function getClassName(element) {
  return Array.from(element.classList).join(' ');
}

function parseHeading1(element) {
  return [
    {
      text: element.innerText,
      style: 'font-size:20px;font-weight:600'.concat(getInlineStyles(element)),
      className: getClassName(element),
    },
  ];
}

function parseParagraph(element) {
  return [
    {
      text: element.innerText,
      style: ''.concat(getInlineStyles(element)),
      className: getClassName(element),
    },
  ];
}

function parseOrderedList(element) {
  return Array(...element.children).map((child, idx) => ([
    {
      text: idx + 1,
      style: 'color:red'.concat(getInlineStyles(child)),
      className: getClassName(child),
    },
    {
      text: child.innerText,
      style: 'color:red'.concat(getInlineStyles(child)),
      className: getClassName(child),
    },
  ]));
}

function parseUnorderedList(element) {
  return Array(...element.children).map((child) => ([
    {
      text: child.innerText,
      style: 'color:red'.concat(getInlineStyles(element)),
      className: getClassName(child),
    },
  ]));
}

function parseTable(element) {
  const header = element.querySelectorAll('thead tr th');
  const body = element.querySelectorAll('tbody tr');

  const headingElements = Array(...header).map(th => ({
    text: th.innerText,
    style: 'font-weight:600'.concat(getInlineStyles(th)),
    className: getClassName(th),
  }));
  const bodyElements = Array(...body)
    .map(tr => {
      const cells = Array(...tr.querySelectorAll('td'));
      return cells.map(cell => ({
        text: cell.innerText,
        style: ''.concat(getInlineStyles(cell)),
        className: getClassName(cell),
      }))
    });

  return [
    headingElements,
    ...bodyElements,
  ]
}

function convertElementsToTabular(elements) {
  const result = [];
  let noOfColumns = 1;
  Array(...elements).forEach(element => {
    switch (element.tagName) {
      case 'H1':
        result.push(parseHeading1(element));
        break;
      case 'P':
        result.push(parseParagraph(element));
        break;
      case 'OL':
        noOfColumns = Math.max(noOfColumns, 2);
        result.push(...parseOrderedList(element));
        break;
      case 'UL':
        result.push(...parseUnorderedList(element));
        break;
      case 'TABLE':
        result.push(...parseTable(element));
        break;
    }
  });

  console.log(result)
  return result;
}

function parseTableStructureToHtml(tableStructure) {
  const getTableCell = cell => `<td ${cell.style && 'style='.concat(cell.style)} ${cell.className && 'class='.concat(cell.className)}>${cell.text}</td>`;
  const getTableRow = row => `<tr>${row.map(getTableCell).join('')}</tr>`;
  const getTable = data => `<tbody>${data.map(getTableRow).join('')}</tbody>`;

  console.log(getTable(tableStructure))
  return `<table>
      <tbody>
        ${getTable(tableStructure)}
      </tbody>
    </table>`;
}

function main() {
  const strDocument = getDocumentFromString();
  const elementsOnScreen = strDocument.querySelector('body').children;
  const tableStructure = convertElementsToTabular(elementsOnScreen);
  
  const htmlStr = parseTableStructureToHtml(tableStructure);
  document.getElementById('main-container').innerHTML = htmlStr;
}

字符串
让我们一个功能一个功能地过流程。

main-这是调用其他方法的main方法
getDocumentFromString-根据传递给它的字符串返回一个DOM对象。得到的DOM用于剩下的处理。
convertElementsToTabular-遍历屏幕上的所有元素,并使用每个元素的tagName来确定如何处理它。

基于tagName,调用不同的方法来处理元素,如parseHeading 1parseParagraphparseOrderedListparseUnorderedListparseTable
如果你的用例包含更多类型的标签(H2,H3,SPAN等),你只需要在这里添加更多的用例和相应的回调。

parseHeading 1parseParagraphparseOrderedListparseUnorderedListparseTable-这些方法返回一个数组,其中包含要在结果表中显示的文本。每个元素包含-

  1. text
  2. style-它使用getInlineStyles方法从示例字符串中获取样式,还允许您添加自己的样式以自定义标记的外观。
  3. className-使用getClassName方法从示例字符串中获取元素的类名。

parseTableStructureToHtml-解析convertElementsToTabular返回的数组,并根据数据返回一个包含表格行和单元格标签的字符串。

然后,这个html字符串被插入到页面上的div中以呈现它。
希望这对你有帮助!

相关问题