1

I have an HTML definition list, and I want to use jQuery to turn that into a nested JavaScript array. What's the simplest way to do this? Thanks for your help.

My input looks like this:

<dl>
  <dt>A</dt>
   <dd>A1</dd>
  <dt>B</dt>
   <dd>B1</dd>
   <dd>B2</dd>
</dl>

I want my output to look like this:

[['A', 'A1'], ['B', 'B1', 'B2']]
Anirvan
  • 6,214
  • 5
  • 39
  • 53

5 Answers5

4
var final_array = []; 

$('dl dt').each(function(){
   var dt_dds = [];   /* array to hold the dt_dds */ 
   dt_dds.push( $(this).text() );  /* push the dt */ 
   dds = $(this).nextUntil('dt'); /* get all dd's until the next dt */ 
   dds.each(function(){  dt_dds.push( $(this).text() )}); /** push all dd's into the array*/ 
   final_array.push( dt_dds ); 
})

console.log( final_array ); 

Here's a fiddle.

aziz punjani
  • 25,586
  • 9
  • 47
  • 56
1

You could try something like this:

var a = [];
var b = [];

var dlc = $("dl").children();

dlc.each(function (i) {
    if (this.nodeName == "DT") {
       if (b.length) a.push(b);
       b = [$(this).html()]; 
    } else {
       b.push($(this).html());   
    }
    if (i == (dlc.length-1)) {
        a.push(b);
        console.log(a);
    }
});
Steve Lewis
  • 1,302
  • 7
  • 8
1

This isn't very elegant but you can iterate through the child elements of the <dl> tag, build an array for each set of <dt>/<dd> tags and .push that array into an output array:

//setup two arrays, one as a final output and one that will hold each sub-array
var output = [],
    temp   = [];

//iterate through each child element of the `<dl>` element
$('dl').children().each(function () {

    //if this element is a `<dt>` tag
    if (this.tagName == 'DT') {

        //if the `temp` array is not empty
        if (0 in temp) {

            //`.push` the `temp` array onto the `output` array
            output.push(temp);
        }

        //add the text of this `<dt>` tag to the `temp` array as the first key (erasing any data that was inside the `temp` array)
        temp = [$(this).text()];
    } else {

        //if the tag found was anything other than a `<dt>` tag (I'm assuming it's a `<dd>` tag) then `.push` its text into the `temp` array
        temp.push($(this).text());
    }
});

//make sure to add the last iteration of the `temp` array to the `output` array
output.push(temp);

//for the structure supplied in the question, the output looks like this: [["A", "A1"], ["B", "B1", "B2"]]

A demonstration of this code can be found at: http://jsfiddle.net/qkjKp/

Jasper
  • 75,717
  • 14
  • 151
  • 146
1

You can use .map() to do that:

var array = $('dl dt').map(function() {
  // Get the ['A1'] and ['B1', 'B2']
   var items = $(this).nextUntil('dt', 'dd').map(function() {
    return $(this).text();
  }).get();

  // Prepend the dt's value
  items.unshift($(this).text());

  // Needs to be wrapped in a second array so that .map() doesn't flatten.
  return [ items ];
}).get();

Demo: http://jsfiddle.net/LjZDt/1/

More info about that technique here: http://encosia.com/use-jquery-to-extract-data-from-html-lists-and-tables/

Dave Ward
  • 59,815
  • 13
  • 117
  • 134
  • This is great, elegant, and the shortest answer posted. I ended up accepting a [marginally longer approach](http://stackoverflow.com/questions/8175208/turning-html-dl-into-a-nested-javascript-array-with-jquery/8175320#8175320) because it struck me as a bit more readable, but I'd also mark yours as accepted if I could. Thanks, Dave. – Anirvan Nov 18 '11 at 01:03
1

nextUntil(...) will do the trick to get the proper dd's

var result = [];

$("dt").each(function() {
    var el = $(this),
        tmp = [el.text()];

    el.nextUntil("dt").each(function() {
        tmp.push($(this).text());
    });

    result.push(tmp);
});

console.log(result);

fiddle

Anirvan
  • 6,214
  • 5
  • 39
  • 53
Andreas
  • 21,535
  • 7
  • 47
  • 56