structured but it becomes terrible when XML is not well structured.
I got such rough structured XML (products.xml) to create menu.
<products>
<category>
<categoryid>2</categoryid>
<categoryname>Lunch</categoryname>
<category>
<categoryid>5</categoryid>
<categoryname>Snacks</categoryname>
<product>
<productid>003</productid>
<productname>Hot Dog</productname>
<productdesc>Big old greasy breakfast</productdesc>
<productprice>20.00</productprice>
<tax-sales>13</tax-sales>
<tax-service>10</tax-service>
</product>
</category>
<category>
<categoryid>6</categoryid>
<categoryname>Dinner</categoryname>
<category>
<categoryid>7</categoryid>
<categoryname>Chinese</categoryname>
<category>
<categoryid>8</categoryid>
<categoryname>Starters</categoryname>
<product>
<productid>003</productid>
<productname>Dumplings</productname>
<productdesc>Big old greasy breakfast</productdesc>
<productprice>20.00</productprice>
<tax-sales>13</tax-sales>
<tax-service>10</tax-service>
</product>
</category>
</category>
<category>
<categoryid>11</categoryid>
<categoryname>Mexican</categoryname>
<category>
<categoryid>8</categoryid>
<categoryname>Starters</categoryname>
<product>
<productid>003</productid>
<productname>Dumplings</productname>
<productdesc>Big old greasy breakfast</productdesc>
<productprice>20.00</productprice>
<tax-sales>13</tax-sales>
<tax-service>10</tax-service>
</product>
</category>
<product>
<productid>001</productid>
<productname>soup</productname>
<productdesc>2 pieces of toast with butter and jam</productdesc>
<productprice>12.00</productprice>
<tax-sales>13</tax-sales>
<tax-service>10</tax-service>
</product>
</category>
<product>
<productid>001</productid>
<productname>soup</productname>
<productdesc>2 pieces of toast with butter and jam</productdesc>
<productprice>12.00</productprice>
<tax-sales>13</tax-sales>
<tax-service>10</tax-service>
</product>
</category>
</category>
</products>
You could see that nodes are nested and repeating within other nodes for example
<category>
<categoryid>6</categoryid>
<categoryname>Dinner</categoryname>
<category>
<categoryid>7</categoryid>
<categoryname>Chinese</categoryname>
<category>
<categoryid>8</categoryid>
<categoryname>Starters</categoryname>
Hence with JQuery, XML traversing is very easy but with such situation it wasn't so easy to traverse.
There was an other problem in XML also that the category depth was dynamic, it could be to nth level.
The only solution I thought is the using recursion.
So, here we go.
I have used JQuery 1.4.2, you could download from JQuery
first of all add jquery source in your header like
<script language="javascript" type="text/javascript" src="js/jquery/1.4.2/jquery.min.js"></script>
rest javascript code is as below
<script language="javascript" type="text/javascript" >
// XML directory where xml files are saved
var XML_DIR = './xml/';
//CSS classes for category and products
var CATEGORY_CLASS_NAME = "button_products_category";
var PRODUCT_CLASS_NAME = "button_products_product";
$(document).ready(function()
{
$.ajax({
type: "GET",
url: XML_DIR + "products.xml",
dataType: "xml",
success: traverse
});
});
function traverse(xml) {
var ul = document.createElement('ul');
ul.setAttribute('id', 'category');
$(xml).find('products').children().each(function() {
var categoryName = $(this).find('categoryname:first').text();
var categoryId = $(this).find('categoryid:first').text();
var li = createLi(categoryName, categoryId, CATEGORY_CLASS_NAME);
getProducts($(this), li);
//Getting inner categories if exist
getNestedCategories($(this), li);
ul.appendChild(li);
});
// setting empty the category list
$('div#category').empty()
.append(ul);
}
function getNestedCategories(node, li) {
var ul = document.createElement('ul');
node.children().each(function() {
if ($(this)[0].tagName == 'category') {
var categoryName = $(this).find('categoryname:first').text();
var categoryId = $(this).find('categoryid:first').text();
var ili = createLi(categoryName, categoryId, CATEGORY_CLASS_NAME);
//Using recursion to getting nested categories
if ($(this).find('category').children().length > 0 ) {
getNestedCategories($(this), ili);
}
//Getting products for each category
getProducts($(this), ili);
ul.appendChild(ili);
li.appendChild(ul);
}
});
li.appendChild(ul);
}
function getProducts(node, mli) {
var ul = document.createElement('ul');
node.children().each(function(){
if ($(this)[0].tagName == 'product') {
ul.appendChild(createLi($(this).find('productname').text(), $(this).find('productid').text(), PRODUCT_CLASS_NAME));
}
});
mli.appendChild(ul);
}
function createLi(nodeName, nodeId, class) {
var li = document.createElement('li');
var button = document.createElement('input');
button.setAttribute('type', 'button');
button.setAttribute('value', nodeName);
button.setAttribute('id', nodeId);
button.className = class;
li.appendChild(button);
return li;
}
</script>