Разбор HTML из строки с помощью DOMParser и возврат массива объектов - PullRequest
0 голосов
/ 13 апреля 2020

Я успешно разбираю HTML из строки, используя DOMParser, но вывод не тот, который мне нужен.

Это 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, если они приходят в порядок, и когда он достигает <img /> or <video /> в этом Я хочу, чтобы они были объектами типа { type: 'image', source: 'url of img' } и продолжались в этом порядке. Поэтому в основном я хочу сохранить порядок, представленный в этом HTML, но объединяю HTML текстов в один объект, как показано в этом примере выше.

Если кто-то может помочь мне с logi, то c быть великим, потому что я не могу понять это

1 Ответ

0 голосов
/ 13 апреля 2020

Вы можете рассмотреть контекст (открытый h1) и добавлять его каждые p, с которыми вы сталкиваетесь. Всякий раз, когда вы найдете другой h1, переопределите этот контекст с помощью нового h1.

Редактировать: неверное прочтение группировки. Выражается по-разному: вы хотите сгруппировать h1 ?, p * в целом. Та же идея имеет место:

Ниже используется flatMap вместо сопоставления, чтобы «игнорировать» тег 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);
...