简体   繁体   中英

How to loop through HTML elements and populate a Json-object?

I'm looping through all the html tags in an html-file, checking if those tags match conditions, and trying to compose a JSON-object of a following schema:

[
{    title: 'abc',    date: '10.10.10',    body: ' P tags here',    href: ''  },
{    title: 'abc',    date: '10.10.10',    body: ' P tags here',    href: ''  },
{    title: 'abc',    date: '10.10.10',    body: ' P tags here',    href: ''  }
]

But I'd like to create the new entry only for elements, classed "header", all the other elements have to be added to earlier created entry. How do I achieve that?

Current code:

$('*').each((index, element) => {


  if ( $(element).hasClass( "header" ) ) {
      jsonObject.push({
          title: $(element).text()
      });
  };
  if( $(element).hasClass( "date" )) {
      jsonObject.push({
          date: $(element).text()
      });
   }

   //links.push($(element))
});
console.log(jsonObject)

Result is:

  {
    title: 'TestA'
  },
  { date: '10.10.10' },
  {
    title: 'TestB'
  },
  { date: '10.10.11' }

I'd like it to be at this stage something like:

      {
        title: 'TestA'
      ,
       date: '10.10.10' },
      {
        title: 'TestB'
      ,
       date: '10.10.11' }

UPD: Here's the example of HTML file:

<h1 class="header">H1_Header</h1>
<h2 class="date">Date</h2>
<p>A.</p>
<p>B.</p>
<p>С.</p>
<p>D.</p>
<a class="source"><a href="http://">http://</a></a>
<h1 class="header">H1_Header2</h1>
<h2 class="date">Date2</h2>
<p>A2.</p>
<p>B2.</p>
<p>С2.</p>
<p>D2.</p>
<a class="source"><a href="http://2">http://2</a></a>

Thank you for your time!

Based on your example Html , it appears everything you are trying to collect is in a linear order, so you get a title, date, body and link then a new header with the associated items you want to collect, since this appears to not have the complication of having things being ordered in a non-linear fasion, you could do something like the following:

let jsonObject = null;
let newObject = false;
let appendParagraph = false;
let jObjects = [];

$('*').each((index, element) => {
  if ($(element).hasClass("header")) {
      //If newObject is true, push object into array
      if(newObject)
         jObjects.push(jsonObject);
      //Reset the json object variable to an empty object
      jsonObject = {};
      //Reset the paragraph append boolean
      appendParagraph  = false;
      //Set the header property
      jsonObject.header = $(element).text();
      //Set the boolean so on the next encounter of header tag the jsobObject is pushed into the array
      newObject = true;
  };

  if( $(element).hasClass( "date" )) {
      jsonObject.date = $(element).text();
  }

  if( $(element).prop("tagName") === "P") {
      //If you are storing paragraph as one string value
      //Otherwise switch the body var to an array and push instead of append
      if(!appendParagraph){ //Use boolean to know if this is the first p element of object
         jsonObject.body = $(element).text();
         appendParagraph = true; //Set boolean to true to append on next p and subsequent p elements
      } else {
         jsonObject.body += (", " + $(element).text()); //append to the body
      }

  }

  //Add the href property
  if( $(element).hasClass("source")) {
       //edit to do what you wanted here, based on your comment:
       jsonObject.link = $(element).next().html(); 
       //jsonObject.href= $(element).attr('href');
  }
});

//Push final object into array
jObjects.push(jsonObject);

console.log(jObjects);

Here is a jsfiddle for this: https://jsfiddle.net/Lyojx85e/

I can't get the text of the anchor tags on the fiddle (I believe because nested anchor tags are not valid and will be parsed as seperate anchor tags by the browser), but the code provided should work in a real world example. If .text() doesn't work you can switch it to .html() on the link, I was confused on what you are trying to get on this one, so I updated the answer to get the href attribute of the link as it appears that is what you want. The thing is that the anchor with the class doesn't have an href attribute, so I'll leave it to you to fix that part for yourself, but this answer should give you what you need.

$('*').each((index, element) => {
  var obj = {};

  if ( $(element).hasClass( "header" ) ) {
    obj.title = $(element).text();
  };
  if( $(element).hasClass( "date" )) {
    obj.date = $(element).text()
   }

    jsonObject.push(obj);

});

I don't know about jQuery, but with JavaScript you can do with something like this.

 const arr = []; document.querySelectorAll("li").forEach((elem) => { const obj = {}; const title = elem.querySelector("h2"); const date = elem.querySelector("date"); if (title) obj["title"] = title.textContent; if (date) obj["date"] = date.textContent; arr.push(obj); }); console.log(arr);
 <ul> <li> <h2>A</h2> <date>1</date> </li> <li> <h2>B</h2> </li> <li> <date>3</date> </li> </ul>

Always use map for things like this. This should look something like:

let objects = $('.header').get().map(el => {
  return {
    date: $(el).attr('date'),
    title: $(el).attr('title'),
  }
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM