【问题标题】:Using JavaScript, how do I transform an HTML string into an array of HTML tags and text content?使用 JavaScript,如何将 HTML 字符串转换为 HTML 标签和文本内容数组?
【发布时间】:2021-01-05 03:38:32
【问题描述】:

我有一个 HTML 字符串,例如:

<p>
    <strong><em>Lorem Ipsum </em></strong>is simply dummy text of the printing <em>and</em> typesetting industry.
</p>

我想把它转换成一个 JavaScript 数组,如下所示:

['<p>', '<strong>', '<em>', 'Lorem Ipsum ', '</em>', '</strong>', 'is simply dummy text of the printing ', '<em>', 'and', '</em>', 'typesetting industry.', '</p>']

即它接受 HTML 字符串并将其分解为一组标签和 HTML 内容。

我已尝试按照this 问题使用DomParser()

const str = `<p><strong><em>Lorem Ipsum </em></strong>is simply dummy text of the printing <em>and</em> typesetting industry.</p>`;

const doc = new DOMParser().parseFromString(str, 'text/html');
const arr = [...doc.body.childNodes]
  .map(child => child.outerHTML || child.textContent);

但是,这只是返回:

['<p><strong><em>Lorem Ipsum </em></strong>is simply dummy text of the printing <em>and</em> typesetting industry.</p>']

我也尝试搜索各种基于正则表达式的解决方案,但无法找到任何能完全按照我的要求分解字符串的解决方案。

有什么建议吗?

谢谢

【问题讨论】:

  • 重点是什么?如果您使用const frag = document.createElement('div'); frag.innerHTML = thatString; 创建一个div,那么您可以从该frag 获取元素。

标签: javascript html domparser


【解决方案1】:

我会创建一个递归函数来遍历给定节点并返回其子节点的文本表示数组:

const str = `<p><strong><em>Lorem Ipsum </em></strong>is simply dummy text of the printing <em>and</em> typesetting industry.</p>`;

const doc = new DOMParser().parseFromString(str, 'text/html');
const parseNode = node => {
  const output = [];
  for (const child of node.childNodes) {
    if (child.nodeType === Node.TEXT_NODE) {
      output.push(child.textContent);
    } else if (child.nodeType === Node.ELEMENT_NODE) {
      output.push(`<${child.tagName}>`);
      output.push(...parseNode(child));
      output.push(`</${child.tagName}>`);
    }
  }
  return output;
};
console.log(parseNode(doc.body));

如果你也需要保留属性,你可以取元素的outerHTML 并取前导非括号:

const str = `<p style="color:green"><strong><em>Lorem Ipsum </em></strong>is simply dummy text of the printing <em>and</em> typesetting industry.</p>`;

const doc = new DOMParser().parseFromString(str, 'text/html');
const parseNode = node => {
  const output = [];
  for (const child of node.childNodes) {
    if (child.nodeType === Node.TEXT_NODE) {
      output.push(child.textContent);
    } else if (child.nodeType === Node.ELEMENT_NODE) {
      const attribs = child.outerHTML.match(/<\s*[^>\s]+([^>]*)/)[1];
      output.push(`<${child.tagName}${attribs}>`);
      output.push(...parseNode(child));
      output.push(`</${child.tagName}>`);
    }
  }
  return output;
};
console.log(parseNode(doc.body));

如果需要不展开自闭标签,检查元素的outerHTML是否包含&lt;/

const str = `<p style="color:green"><input readonly value="x"/><strong><em>Lorem Ipsum </em></strong>is simply dummy text of the printing <em>and</em> typesetting industry.</p>`;

const doc = new DOMParser().parseFromString(str, 'text/html');
const parseNode = node => {
  const output = [];
  for (const child of node.childNodes) {
    if (child.nodeType === Node.TEXT_NODE) {
      output.push(child.textContent);
    } else if (child.nodeType === Node.ELEMENT_NODE) {
      const attribs = child.outerHTML.match(/<\s*[^>\s]+([^>]*)/)[1];
      output.push(`<${child.tagName}${attribs}>`);
      if (child.outerHTML.includes('</')) {
        // Not self closing:
        output.push(...parseNode(child));
        output.push(`</${child.tagName}>`);
      }
    }
  }
  return output;
};
console.log(parseNode(doc.body));

【讨论】:

  • 你能把幻数转换成常数吗?
  • 这是否考虑到自闭合标签?
  • @MatinKajabadi 如果扩展它们对您来说是个问题,我想您可以检查outerHTML 是否包含&lt;/
  • @MatinKajabadi 我的解析器,还是 DOMParser? DOMParser 将尽可能准确地解释标记。如果元素必须是有效的自闭合元素,浏览器将省略outerHTML中的结束标记。
猜你喜欢
  • 2020-11-26
  • 2020-08-17
  • 1970-01-01
  • 2021-01-24
  • 1970-01-01
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 2013-08-14
相关资源
最近更新 更多