2

The problem:

I have a large string (it's HTML format) and I need to select multiple substrings from it, and then push them into an array of objects. Please note: I cannot change the original string. The example below is a simplified version.

What I need:

An array of objects containing information about "recipes", like so:

const recipes = [ 
{ 
   title: "This is title number 1", 
   imagelink: "/exampleimage1.jpg", 
   recipelink: "www.examplelink1.com" 
}, {
   title: "This is title number 2", 
   imagelink: "/exampleimage2.jpg", 
   recipelink: "www.examplelink2.com" 
}]

What the string looks like:

This is a simplified version of the string. The original one contains more characters and more tags like href etc. So I can't only filter on these substrings. As you can see, the title, link and link to the image are present more than once. It therefore doesn't matter which duplicate is pushed into the array, as long as they belong to their 'parent' recipe.

<section class="item recipe " data-title="This is title number 1" data-record-type="recipe">
    <figure class="">
        <a href="www.examplelink1.com">
            <span class="favorites-wrapper">
                <span class="favorite shadow " data-is-favorite="false" data-recipe-id="11111" data-recipe-title="This is title number 1">
                </span>
            </span>
            <span class="type">recept</span>
            <img src="images/blank-16x11.gif" data-src="/exampleimage1.jpg" class="js-lazyload" data-retina-src="/exampleimage1.jpg" alt="This is title number 1">
        </a>
    </figure>   

    <header>
        <h4> <a href="www.examplelink1.com"> This is title number 1 </a> </h4>  
        <div class="rating">
            <span><div class="icon icon-star active"></div></span>
            <span><div class="icon icon-star active"></div></span>
            <span class="count">(<span>84</span>)</span>    
        </div>  
        <div class="time">15 min.</div> 
    </header>   
</section>

<section class="item recipe " data-title="This is title number 2" data-record-type="recipe">
    <figure class="">
        <a href="www.examplelink2.com">
            <span class="favorites-wrapper">
                <span class="favorite shadow " data-is-favorite="false" data-recipe-id="22222" data-recipe-title="This is title number 2">
                </span>
            </span>
            <span class="type">recept</span>
            <img src="images/blank-16x11.gif" data-src="/exampleimage2.jpg" class="js-lazyload" data-retina-src="/exampleimage2.jpg" alt="This is title number 2">
        </a>
    </figure>   

    <header>
        <h4> <a href="www.examplelink2.com"> This is title number 2 </a> </h4>  
        <div class="rating">
            <span><div class="icon icon-star active"></div></span>
            <span><div class="icon icon-star active"></div></span>
            <span class="count">(<span>84</span>)</span>    
        </div>  
        <div class="time">15 min.</div> 
    </header>   
</section>

I'm not sure if my JavaScript knowledge extends far enough to solve this. Help is much appreciated!

3
  • so you are trying to achieve what? Commented Dec 11, 2017 at 14:50
  • Look into HTML parsing and JavaScript. That's your best approach. Commented Dec 11, 2017 at 14:51
  • @messerbill I'm trying to catch datavalues from this string! Commented Dec 11, 2017 at 14:53

3 Answers 3

1

First you would do a string split using delimiter "section" for example. This will give you an array of all sections in your html string.

const sectionArray = sourceString.split("section");

Next, in a foreach loop handle each value in your new array. eg.

let myObjectArray = [];
let i = 0;

sectionArray.forEach(section => {
   let title = section.substring(section.indexOf('data-title=') + 12, section.length);
   title = title.substring(0, title.indexOf('"'));

   let imagelink = section.substring... 

   myObjectArray[i++] = {title, imagelink, ...};
})

Also, if you're crazy, you could do a mapping into your existing sectionArray like this

sectionArray.map(section => {
    let title = section.substring(section.indexOf('data-title=') + 12, section.length);
    title = title.substring(0, title.indexOf('"'));

    let imagelink = section.substring... 

    return {title, imagelink, ...};
});

Your sectionArray will now be filled with object values.

Good luck!

Sign up to request clarification or add additional context in comments.

2 Comments

Great solution! I'm working server side so not having to use a dummy div is really great. Thanks!
I'm glad it helped you :D Mark it as accepted answer tho :)
0

If you had a str variable that was holding your HTML, you'd create and append it to dummy div. From there map through the sections and assign the key/value pairs accordingly:

const str = `<section class="item recipe " data-title="This is title number 1" data-record-type="recipe">
    <figure class="">
        <a href="www.examplelink1.com">
            <span class="favorites-wrapper">
                <span class="favorite shadow " data-is-favorite="false" data-recipe-id="11111" data-recipe-title="This is title number 1">
                </span>
            </span>
            <span class="type">recept</span>
            <img src="images/blank-16x11.gif" data-src="/exampleimage1.jpg" class="js-lazyload" data-retina-src="/exampleimage1.jpg" alt="This is title number 1">
        </a>
    </figure>   

    <header>
        <h4> <a href="www.examplelink1.com"> This is title number 1 </a> </h4>  
        <div class="rating">
            <span><div class="icon icon-star active"></div></span>
            <span><div class="icon icon-star active"></div></span>
            <span class="count">(<span>84</span>)</span>    
        </div>  
        <div class="time">15 min.</div> 
    </header>   
</section>

<section class="item recipe " data-title="This is title number 2" data-record-type="recipe">
    <figure class="">
        <a href="www.examplelink2.com">
            <span class="favorites-wrapper">
                <span class="favorite shadow " data-is-favorite="false" data-recipe-id="22222" data-recipe-title="This is title number 2">
                </span>
            </span>
            <span class="type">recept</span>
            <img src="images/blank-16x11.gif" data-src="/exampleimage2.jpg" class="js-lazyload" data-retina-src="/exampleimage2.jpg" alt="This is title number 2">
        </a>
    </figure>   

    <header>
        <h4> <a href="www.examplelink2.com"> This is title number 2 </a> </h4>  
        <div class="rating">
            <span><div class="icon icon-star active"></div></span>
            <span><div class="icon icon-star active"></div></span>
            <span class="count">(<span>84</span>)</span>    
        </div>  
        <div class="time">15 min.</div> 
    </header>   
</section>`;

const dummyDiv = document.createElement('div');

dummyDiv.innerHTML += str;

const obj = Array.from(dummyDiv.querySelectorAll('.recipe')).map(section => {
  
  return {
    title: section.dataset.title,
    imagelink: section.querySelector('img').dataset.src,
    recipelink: section.querySelector('a').href
  };
});

console.log(obj);

Comments

0

I would get the string, and place it inside a dummy div something like this:

HTML:
<div id="dummyContent"></div>

JS:
document.getElementById('dummyContent').innerHTML = [string];

and then, look for the section tags, parse the attributes, and then look for the a tags, and parse the info you need. With this info, you fill a object, and then push it into an array, like this:

recipes = [];
$els = document.getElementsByTagName('section');
var i = 0;while(i < $els.length){
  $el = $els[i]; 
  var data = {};
  data.title = $el.getAttribute('data-title');
  data.link = $el.getElementsByTagName('a')[0].getAttribute('href');
  data.img =  $el.getElementsByTagName('img')[0].getAttribute('src');
  receipes.push(data);
  i++;
}

You can extract any other data you need aswell. This example also assumes the first a tag has the information you need, and also the first image has the picture you need, and that there will always be at least 1 a tag and 1 img tag.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.