3
\$\begingroup\$

I will preface by saying that this data set is much larger than what I have here. I'm having to loop through an XML file to get data and display it on a site with jQuery. I have to use jQuery because I'm working within a framework that I can't edit so I'm having to manipulate the data after the fact. This is causing the site I'm working on to slow significantly. I know that that's just the nature of what I'm doing but I'm running a loop inside a loop which I know can be pretty slow, especially when deal with 1,000 entries in an XML file. I'm curious if there's a way for me to do this in a more efficient way.

I'm basically looping through the data and on each iteration I'm grabbing that entries attributes and then having to loop through all the data within that iteration to compare the data with the rest of the data in the file. It seems like there's a better way to do this but I can't seem to figure it out.

If you need more clarification, let me know and I will provide it. I've pared the data down quite a bit so it's easier to handle and look at.

My XML is set up like this:

<Data>
    <Category>
        <category_number>1</category_number>
        <parent_number>4</parent_number>
        <category_name>This is a test Category</category_name>
    </Category>
    <Category>
        <category_number>2</category_number>
        <parent_number>3</parent_number>
        <category_name>This is another test Category</category_name>
    </Category>
    <Category>
        <category_number>3</category_number>
        <parent_number>4</parent_number>
        <category_name>This is yet another test Category</category_name>
    </Category>
</Data>

My HTML is set up like this:

<!--THIS WOULD BE THE UNORDERED LIST FOR CATEGORY 4; IT HAS A CLASS OF '4'-->
<ul class="4">
    <li>This is a parent category. Category 4. A new list will be put in here with this categories child categories.</li>
</ul>
<ul class="2">
    <li>This is a parent category. Category 2. A new list will be put in here with this categories child categories.</li>
</ul>

My jQuery is as follows:

$.ajax({
    url: "/sample_url.xml",
    type: "GET",
    dataType: "html",
    success: function(data) {
        var xml = $.parseXML(data);
        $(xml).find('category_number').each(function(){
            category_number = $(this).text();
            var parent_number = $(this).parent().find('parent_number').text();
            var category_name = $(this).parent().find('category_name').text();

            var sub_array = [];

            //GET CATEGORIES SUB-CATEGORIES
            $(this).closest('Data').find('parent_number').each(function(){
                if($(this).text()==category_number){
                    var category_id = $(this).parent().find('category_number').text();
                    sub_array.push('<li>' + $(this).parent().find('category_name').text() + '</li>');
                }
            });

            $('ul#category_list').each(function(){
                if($(this).attr('class')==parent_number){
                    $(this).append('<li><ul id="' + category_number + '"></ul></li>');
                    $('ul#' + category_number).html(sub_array.join(""));
                }
            });
        });
    }
});
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Don't use selector all the time. DOM locating waste most resource and time. as less selector as possible. use variable cache the jQuery object.

Data is look like a root:

var $data = $("Data");

Rather than parse start with "category_number", why not start with "Category"

$(xml).find('Category').each(function(){
    //do something.
});

Also, you could use filter() or map() to reduce the code:

// filter() example
function getSubCategory(pid){
    $catalist = $data.find("Category").filter(function(){
       return $(this).find("parent_number").text()==pid;
    })

    return $catalist;

}

// map() example
var subCatString=$subCatList.map(function(sum,item){
    var $subCat=$(item) ;
    var vcum=$subCat.find("category_number").text();
    return '<li>'+vcum+'</li>'
}).get().join();

Combine them together (HTML, see this JSFiddle, don't use AJAX):

var $xml= $("xml");
var $data=$xml.find("Data");
var $displayList=$("ul#category_list");


$xml.find("Category").each(function(){
    var $catageory=$(this);
    var $cnum=$catageory.find("category_number");
    var $pnum=$catageory.find("parent_number");
    var $cname=$catageory.find("category_name"); 

    var $subCatList=getSubCategory($cnum.text());
    var subCatString=$subCatList.map(function(sum,item){
        var $subCat=$(item) ;
        var vcum=$subCat.find("category_number").text();
        return '<li>'+vcum+'</li>'
    }).get().join();


    var $ul=$("<ul/>",{class:$cnum.text()});

    $ul.append(subCatString);

    $displayList.append($("<li/>").html($ul));



});


function getSubCategory(pid){
    $catalist = $data.find("Category").filter(function(){
       return $(this).find("parent_number").text()==pid;
    })

    return $catalist;

}
\$\endgroup\$
2
  • \$\begingroup\$ This all looks great. My biggest question though, is you say don't use AJAX. My XML is it's own file that is being referenced by the jQuery. How would I import that data into the page without using AJAX? \$\endgroup\$ Commented Mar 10, 2014 at 13:15
  • \$\begingroup\$ @MxmastaMills sorry for misunderstand. it is that my example is not using Ajax, because I use jsfiddle which is no point to use ajax. To save the time, I use mix xml and html in jsfiddle as document example. you may just adopt my code into your ajax code, that all. \$\endgroup\$
    – caoglish
    Commented Mar 11, 2014 at 0:24

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.