Friday, April 2, 2010

Traversing XML (having nested and repeating enteries) using JQuery to create menu

XML is an essential part of the software development activity, traversing XML is much easier if it is well

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>  

Monday, April 20, 2009

Remove new line CRLF (\r\n) or line break

Removing the new line tags (CRLF) from a string

$string = "some thing new
line one
line two";

$new_string = preg_replace("/\r\n/", " ", $string);

you may also replace the line break with
tag as following

$new_string = preg_replace("/\r\n/", "
", $string);

Wednesday, February 25, 2009

Sorting an array by key on day, month, year or time


function date_compare($x, $y){
  $x = strtotime($x);
  $y = strtotime($y);
  if ($x == $y) return 0;
  return (($x > $y)?1:-1);
}
$array = array (
  'Jan 01, 2008' => 1,
  'Oct 31, 2008' => 10,
  'Nov 01, 2008' => 11,
  'Dec 01, 2008' => 12,
  'Jul 01, 2008' => 7,
  'Aug 01, 2008' => 8,
  'Sep 01, 2008' => 9,
);

Before sorting print the array

print_r($array);

Now Sort the array

uksort($array, 'date_compare');

After sorting print the array

print_r($array);

Sorting an array by time, date, month or year


function date_compare($x, $y){
  $x = strtotime($x);
  $y = strtotime($y);
  if ($x == $y) return 0;
  return (($x > $y)?1:-1);
}
$array = array (
 'Jan 01, 2008',
 'Oct 31, 2008',
 'Nov 01, 2008',
 'Dec 01, 2008',
 'Jul 01, 2008',
 'Aug 01, 2008',
 'Sep 01, 2008'
);

Before sorting print the array

print_r($array);

Now Sort the array

usort($array, 'date_compare');

After sorting print the array

print_r($array);

Thursday, November 13, 2008

Calculating difference between two dates in days in PHP

Calculating the days between two dates is so easy in php, you can even calculate the hours, minutes and seconds between two dates

$date1 = "2008-06-11";
$date2 = "2009-05-09";

$diff = strtotime($date2) - strtotime($date1);
$days = $diff/(60*60*24);

Tuesday, November 4, 2008

PHP: post variables without using form

There are several ways for posting variables without using forms in PHP i.e CURL, SOAP library or sockets
Well, I'll use socket to post variables to a URL, URL may be a script file such as example.php
As the variables are posted using socket the URL may return some response, we can get that response back from that socket

First step is to make a request packet which will post variables to that URL, to construct a packet we should know the following

  • method (you may use get or post) and http or https (for secure URLs you should use https)

  • host name (where the URL is hosted, i.e www.example.com)

  • Content type (i.e form)

  • Content length
I am now going to write a simple packet which will send variable1 and variable2 to the example.php


$packet = "POST example.php HTTP/1.0\r\n";
$packet .= "Host: www.example.com\r\n";
$packet .= "Content-Type: application/x-www-form-urlencoded\r\n";
$packet .= "Content-Length: 265\r\n";
$packet .= "Connection: close\r\n\r\n";
$packet .= "variable1=value1&variable2=value2\r\n";


Second step is to send this packet over the socket, for this purpose I will use sendPacket function which I have written below


$response = sendPacket($packet, 'secure.hostelworld.com');
echo $response;


Just include the following function in your script and enjoy


function sendPacket(&$packet, $host, $port=80, $error_no=null, $error_string=null, $request_timeout=30, $proxy=null, $proxy_regexp=null) {

$response = null;
//opening connection
if ($proxy) {
if (!preg_match($proxy_regexp, $proxy)) die("invalid proxy");
$proxy = explode(":", $proxy);
if (!($ack = fsockopen($proxy[0], $proxy[1], $error_no, $error_string, $request_timeout))) {
die("No response from proxy");
}
//sending packet
fputs($ack, $packet);

while (!feof($ack) or !eregi((chr(0x0d) . chr(0x0a) . chr(0x0d) . chr(0x0a)), $response)) {

$response .= fread($ack, 1);
}

} else {

if (!($ack = fsockopen(gethostbyname($host), $port, $error_no, $error_string, $request_timeout))) {

die("$host:$port not responding");
}

//sending packet
fputs($ack, $packet);
while (!feof($ack)) {
$response .= fgets($ack);
}
}

fclose($ack);
return $response;
}

Wednesday, October 15, 2008

How to get rid of write protected alert for flash drives

It is very simple for XP users
go to start menu click on run
type "regedit" in your run command and press enter
it will show registery editor
browse through following path
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies
you will get key "WriteProtect" with value "1" just change this value to "0" and exit registery editor

you have done it
you may need to restart your windows