【问题标题】:Parse HTML from a string with DOMParser and return Array of Objects使用 DOMParser 从字符串中解析 HTML 并返回对象数组
【发布时间】:2020-07-25 12:46:14
【问题描述】:

我使用 DOMParser 成功地从字符串解析 HTML,但输出不是我想要的。

这是我的 HTML 示例

codesandbox url

    const html = `
      <h1>Lorem ipsum head 1</h1>
      <p>Lorem ipsum paragraph 2</p>
      <p>Lorem ipsum paragraph 3</p>    
      <img src="http://www.exampleimage.com" />
      <p>Lorem ipsum paragraph 4</p>
      <p>Lorem ipsum paragraph 5</p>
      <video src="http://www.examplevideo.com"></video>
      <h1>Lorem ipsum head 6</h1>    
    `;


    const parser = new DOMParser();
    const DOM = parser.parseFromString(html, "text/html");

    const body = DOM.querySelector("body");

    const json = Array.from(body.children).map((element, i) => {
      if (element.tagName === "IMG") {
        return {
          type: "image",
          source: element.src
        };
      }

      if (element.tagName === "VIDEO") {
        return {
          type: "video",
          source: element.src
        };
      }

      return {
        type: "text",
        source: `<${element.tagName.toLowerCase()}>${
          element.innerText
        }</${element.tagName.toLowerCase()}>`
      };
    });

    console.log(json);

HTML 输入

<h1>Lorem ipsum head 1</h1>
<p>Lorem ipsum paragraph 2</p>
<p>Lorem ipsum paragraph 3</p>    
<img src="http://www.exampleimage.com" />
<p>Lorem ipsum paragraph 4</p>
<p>Lorem ipsum paragraph 5</p>
<video src="http://www.examplevideo.com"></video>
<h1>Lorem ipsum head 6</h1>

我试图实现的基于这个 HTML 的最终输出是这样的

// [
//   {
//     'type': 'text',
//     'source': '<h1>Lorem ipsum head 1</h1><p>Lorem ipsum paragraph 2</p><p>Lorem ipsum paragraph 3</p>'
//   },
//   {
//     'type': 'image',
//     'source': 'https://example.com/mJet2.jpg'
//   },
//   {
//     'type': 'text',
//     'source': '<p>Lorem ipsum paragraph 4</p><p>Lorem ipsum paragraph 5</p>'
//   },
//   {
//     'type': 'video',
//     'source': '<video src="http://www.examplevideo.com" />'
//   }
// ]

但是我得到的输出是每个标签我得到对象{ type: 'text', source: '' },但是我想对文本标签h1、p、p进行分组,如果它们按顺序排列并且当它点击&lt;img /&gt; or &lt;video /&gt;时我希望那些像{ type: 'image', source: 'url of img' } 这样的对象并按该顺序继续。所以基本上我想保持该 HTML 中表示的顺序,但保持将 HTML 文本分组到一个对象中,如上例所示。

如果有人可以帮助我解决逻辑会很棒,因为我无法弄清楚

【问题讨论】:

  • 您应该添加您的预期输出来说明您要达到的目标@Indigo
  • @grodzi 如您所见,我已经解释过:基于此 HTML 我试图实现的最终输出是这样的

标签: javascript html algorithm sorting html-parsing


【解决方案1】:

您可能需要考虑一个上下文(打开的h1)并在遇到的每个p 中附加它。每当您找到另一个 h1 时,使用新的 h1 覆盖该上下文。

编辑:误读分组。表达方式不同: 您想将 h1?, p* 完全分组。 同样的想法也成立:

下面使用 flatMap 代替 map 来“忽略” p 标签(因为已经连接到 h1 上下文)

const html = `
      <h1>Lorem ipsum head 1</h1>
      <p>Lorem ipsum paragraph 2</p>
      <p>Lorem ipsum paragraph 3</p>    
      <img src="http://www.exampleimage.com" />
      <p>Lorem ipsum paragraph 4</p>
      <p>Lorem ipsum paragraph 5</p>
      <video src="http://www.examplevideo.com"></video>
      <h1>Lorem ipsum head 6</h1>    
      <p>onagain</p>
    `;


    const parser = new DOMParser();
    const DOM = parser.parseFromString(html, "text/html");

    const body = DOM.querySelector("body");
    let lastOpenedTag = null
    const json = Array.from(body.children).flatMap((element, i) => {
      if (element.tagName === "IMG") {
        lastOpenedTag = null
        return {
          type: "image",
          source: element.src
        };
      }

      if (element.tagName === "VIDEO") {
        lastOpenedTag = null
        return {
          type: "video",
          source: element.src
        };
      }
      const back = {
        type: "text",
        source: `<${element.tagName.toLowerCase()}>${
          element.innerText
        }</${element.tagName.toLowerCase()}>`
      }
      if (element.tagName === 'P') {
        if (lastOpenedTag === null) {
          lastOpenedTag = back
        } else {
          lastOpenedTag.source += element.outerHTML
          return []
        }
      }
      if (element.tagName === 'H1') {
        lastOpenedTag = back
      }
      return back;
    });

    console.log(json);

【讨论】:

    猜你喜欢
    • 2018-06-29
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 2019-12-09
    • 2013-06-13
    • 2020-07-08
    • 1970-01-01
    相关资源
    最近更新 更多