1

I have two arrays from two different xml files, one stores category information, one stores products under categories. They are connected via categoryID. Samples of the xml files are below. I read these xml files and save the data using ajax.

 categories.xml
    <Categories>
        <CategoryID>1</CategoryID>
        <CategoryName>Beverages</CategoryName>
        <Description>Soft drinks, coffees, teas, beer, and ale</Description>
    </Categories>
    <Categories>
        <CategoryID>2</CategoryID>
        <CategoryName>Condiments</CategoryName>
        <Description>Sweet and savory sauces, relishes, spreads, and seasonings</Description>
    </Categories>



products.xml
    <Products>
        <ProductID>1</ProductID>
        <ProductName>Chai</ProductName>
        <CategoryID>1</CategoryID>
        <QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit>
        <UnitPrice>18</UnitPrice>
    </Products>
    <Products>
        <ProductID>2</ProductID>
        <ProductName>Chang</ProductName>
        <CategoryID>1</CategoryID>
        <QuantityPerUnit>24 - 12 oz bottles</QuantityPerUnit>
        <UnitPrice>19</UnitPrice>
    </Products>

I read two files like below

$.ajax({
    type: 'GET',
    url: 'categories.xml',
    dataType: "xml",
    success: function(data) {
        $(data).find('CategoriesRoot Categories').each(function(i){
            cateid = $(this).find('CategoryID').text();
            catename = $(this).find('CategoryName').text();
            catedescription = $(this).find('Description').text();
            categoryarray[i] = new Array();
            categoryarray[i][0] = cateid;
            categoryarray[i][1] = catename;
            categoryarray[i][2] = catedescription;
        });
        $.ajax({
            type: 'GET',
            url: 'products.xml',
            dataType: "xml",
            success: function(data) {
                $(data).find('ProductsRoot Products').each(function(j){
                    proid = $(this).find('ProductID').text();
                    proname = $(this).find('ProductName').text();
                    catid = $(this).find('CategoryID').text();
                    quantity = $(this).find('QuantityPerUnit').text();
                    price = $(this).find('UnitPrice').text();
                    productarray[j] = new Array();
                    productarray[j][0] = proid;
                    productarray[j][1] = proname;
                    productarray[j][2] = catid;
                    productarray[j][3] = quantity;
                    productarray[j][4] = price;

                });

And I need to show nested order list like below

i.food 
  a) product
  b) another product
ii. drink
  a) coke
  b) juice

To do that, I have the loop inside ajax below

for(var k=0;k<categoryarray.length;k++){
  if(categoryarray[k][0]!==""){
    $('.cate ol').append('<li id="Cate_' + k + '">'+categoryarray[k][1]+'</li>');
      for(var l=0;l<productarray.length;l++){
        if(categoryarray[k][0]==productarray[l][2]){
          $('#Cate_' + k).append('<ol id="Pro_' + l + '" type="a"></ol>');
          $('#Pro_' + l).append("<li>"+productarray[l][1]+"</li>");
        }
      } 
    }
  }     

But it shows the first category and then fills all the products and other categories under it with a repeated and random order like this. At the end, the other seven categories are listed with order as ii-viii.

i.Beverages(1st cate)
  a.Chai(1 pro of 1st cate)
  b.Condiments(2nd cate)
    a.Aniseed Syrup(1st pro of 2nd cate)
    b.Confections(3rd cate(no pro under it))
    c.Dairy Products(4th cate(no pro under it))
    d.Grains/Cereals(5th cate)
      a.hamburger bun(1st pro of 5th cate)
      b.Meat/Poultry(6th cate)
        a.beef burger(1st pro of 6th cate)
        b.Produce(7th cate)
        c.Seafood(8th cate)
          a.tiger prawns(1st pro of 8th cate)
          b.cooked prawns(2nd pro of 8th cate)
        a.chicken burger(2nd pro of 7th cate)
        b.Produce(7th cate)
        c.Seafood(8th cate)
         .....

Can anyone help me figure out where I did wrong? P.S. I put only a part of codes here. If you are confused about what I am asking, feel free to ask me! Many thanks!!!!

张剑桥
  • 67
  • 7
  • can you post your array product array and category array? are they separate or in same objects? – BeeBee8 May 27 '18 at 15:45
  • @BhushanBabar Hi Bhushan! They are from two different xml file. the category array contains 8 types, each has three attributes "categoryID, categoryName & categoryDescription"; the product array has 13 types with five variables each "productID, productName, categoryID, quantity & price". They are connected via categoryID. – 张剑桥 May 27 '18 at 15:54
  • you need to post them in your question, at least two from each. – BeeBee8 May 27 '18 at 15:55
  • @BhushanBabar Hi Bhushan! I have edited the post with samples of both xml files. – 张剑桥 May 27 '18 at 16:02
  • How are you retrieving the data? – Mikey May 27 '18 at 16:47
  • @Mikey Hi Mikey! I have updated my post with the method I used to read xml files. – 张剑桥 May 27 '18 at 16:58

1 Answers1

2

Create a data structure that will help you build the list easier.

Suppose you have the following data:

categories.xml

<?xml version="1.0" encoding="UTF-8"?>
<Categories>
    <Category>
        <ID>1</ID>
        <Name>Beverages</Name>
        <Description>Soft drinks, coffees, teas, beer, and ale</Description>
    </Category>
    <Category>
        <ID>2</ID>
        <Name>Condiments</Name>
        <Description>Sweet and savory sauces, relishes, spreads, and seasonings</Description>
    </Category>
</Categories>

products.xml

<?xml version="1.0" encoding="UTF-8"?>
<Products>
    <Product>
        <ID>1</ID>
        <Name>Chai</Name>
        <CategoryID>1</CategoryID>
        <QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit>
        <UnitPrice>18</UnitPrice>
    </Product>
    <Product>
        <ID>2</ID>
        <Name>Chang</Name>
        <CategoryID>1</CategoryID>
        <QuantityPerUnit>24 - 12 oz bottles</QuantityPerUnit>
        <UnitPrice>19</UnitPrice>
    </Product>
    <Product>
        <ID>3</ID>
        <Name>Chen</Name>
        <CategoryID>2</CategoryID>
        <QuantityPerUnit>6 - 20 oz bottles</QuantityPerUnit>
        <UnitPrice>5</UnitPrice>
    </Product>
    <Product>
        <ID>4</ID>
        <Name>Chow</Name>
        <CategoryID>2</CategoryID>
        <QuantityPerUnit>12 - 40 oz mustard</QuantityPerUnit>
        <UnitPrice>14</UnitPrice>
    </Product>
</Products>

Let's build an object where the key is the category ID and the value is the category data with an additional field products to hold all its related products.

{
    '1': {
        name: 'Beverages',
        description: 'Soft drinks, coffees, teas, beer, and ale',
        products: [ ... ]
    },
    '2': {
        name: 'Condiments',
        description: 'Sweet and savory sauces, relishes, spreads, and seasonings',
        products: [ ... ]
    }
}

When building the object, the key is important because when we will be iterating over the products, we'll be able to easily add them to their respective category's products array as shown below:

var data = {};

categories.find('Category').each(function () {
    var category = $(this);
    var id = category.find('ID').text();
    data[id] = {
        id: id,
        name: category.find('Name').text(),
        description: category.find('Description').text(),
        products: []
    };
})

products.find('Product').each(function () {
    var product = $(this);
    var categoryId = product.find('CategoryID').text();
    if (data.hasOwnProperty(categoryId)) {
        data[categoryId].products.push({
            id: product.find('ID').text(),
            name: product.find('Name').text(),
            quantityPerUnit: product.find('QuantityPerUnit').text(),
            unitPrice: product.find('UnitPrice').text()
        });
    }
});

Once we have this object, we can now build the HTML by running two nested loops.

var list  = '<ol type="i">';
$.each(data, function (i, category) {
    list += '<li>' + category.name
    list += '<ol type="a">';
    $.each(category.products, function (j, product) {
        list += '<li>' + product.name + '</li>';
    });
    list += '</ol>';
    list += '</li>';
})
list += '</ol>';

Putting everything together

<!-- placeholder to hold list -->
<div id="products"></div>

<script>
$(function () {
    // simplified way to get 2 ajax responses
    $.when(
        $.get('categories.xml'),
        $.get('products.xml')
    ).done(function (catRes, prodRes) {
        var categories = $($.parseXML(catRes[2].responseText)).find('Categories'),
            products = $($.parseXML(prodRes[2].responseText)).find('Products');

        // build a data structure to organize both responses
        var data = {};

        categories.find('Category').each(function () {
            var category = $(this);
            var id = category.find('ID').text();
            data[id] = {
                id: id,
                name: category.find('Name').text(),
                description: category.find('Description').text(),
                products: []
            };
        })

        products.find('Product').each(function () {
            var product = $(this);
            var categoryId = product.find('CategoryID').text();
            if (data.hasOwnProperty(categoryId)) {
                data[categoryId].products.push({
                    id: product.find('ID').text(),
                    name: product.find('Name').text(),
                    quantityPerUnit: product.find('QuantityPerUnit').text(),
                    unitPrice: product.find('UnitPrice').text()
                });
            }
        });

        // build HTML using data structure
        var list  = '<ol type="i">';
        $.each(data, function (i, category) {
            list += '<li>' + category.name
            list += '<ol type="a">';
            $.each(category.products, function (j, product) {
                list += '<li>' + product.name + '</li>';
            });
            list += '</ol>';
            list += '</li>';
        })
        list += '</ol>';

        $('#products').html(list);
    });
});
</script>

Useful links:

Mikey
  • 6,728
  • 4
  • 22
  • 45