HD.util.XML = {
	get : function(url, callback) {
		YAHOO.util.Connect.asyncRequest("GET", url, {success : function(response) {
			callback(response.responseXML);
		}});
	},
	
	getAsJson : function(url, callback) {
		HD.util.XML.get(url, function(response) {
			var json = HD.util.XML.parse(response);
			callback(json);
		});
	},
	
	parse : function(xml) {
		return HD.util.XML.xml2json(xml, "");
	},
	/*	This work is licensed under Creative Commons GNU LGPL License.

	License: http://creativecommons.org/licenses/LGPL/2.1/
   Version: 0.9
	Author:  Stefan Goessner/2006
	Web:     http://goessner.net/ 
	*/
	xml2json : function(xml, tab) {
	   var X = {
	      toObj: function(xml) {
	         var o = {};
	         if (xml.nodeType==1) {   // element node ..
	            if (xml.attributes.length)   // element with attributes  ..
	               for (var i=0; i<xml.attributes.length; i++)
	                  o["@"+xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue||"").toString();
	            if (xml.firstChild) { // element has child nodes ..
	               var textChild=0, cdataChild=0, hasElementChild=false;
	               for (var n=xml.firstChild; n; n=n.nextSibling) {
	                  if (n.nodeType==1) hasElementChild = true;
	                  else if (n.nodeType==3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) textChild++; // non-whitespace text
	                  else if (n.nodeType==4) cdataChild++; // cdata section node
	               }
	               if (hasElementChild) {
	                  if (textChild < 2 && cdataChild < 2) { // structured element with evtl. a single text or/and cdata node ..
	                     X.removeWhite(xml);
	                     for (var n=xml.firstChild; n; n=n.nextSibling) {
	                        if (n.nodeType == 3)  // text node
	                           o["#text"] = X.escape(n.nodeValue);
	                        else if (n.nodeType == 4)  // cdata node
	                           o["#cdata"] = X.escape(n.nodeValue);
	                        else if (o[n.nodeName]) {  // multiple occurence of element ..
	                           if (o[n.nodeName] instanceof Array)
	                              o[n.nodeName][o[n.nodeName].length] = X.toObj(n);
	                           else
	                              o[n.nodeName] = [o[n.nodeName], X.toObj(n)];
	                        }
	                        else  // first occurence of element..
	                           o[n.nodeName] = X.toObj(n);
	                     }
	                  }
	                  else { // mixed content
	                     if (!xml.attributes.length)
	                        o = X.escape(X.innerXml(xml));
	                     else
	                        o["#text"] = X.escape(X.innerXml(xml));
	                  }
	               }
	               else if (textChild) { // pure text
	                  if (!xml.attributes.length)
	                     o = X.escape(X.innerXml(xml));
	                  else
	                     o["#text"] = X.escape(X.innerXml(xml));
	               }
	               else if (cdataChild) { // cdata
	                  if (cdataChild > 1)
	                     o = X.escape(X.innerXml(xml));
	                  else
	                     for (var n=xml.firstChild; n; n=n.nextSibling)
	                        o["#cdata"] = X.escape(n.nodeValue);
	               }
	            }
	            if (!xml.attributes.length && !xml.firstChild) o = null;
	         }
	         else if (xml.nodeType==9) { // document.node
	            o = X.toObj(xml.documentElement);
	         }
	         else
	            alert("unhandled node type: " + xml.nodeType);
	         return o;
	      },
	      toJson: function(o, name, ind) {
	         var json = name ? ("\""+name+"\"") : "";
	         if (o instanceof Array) {
	            for (var i=0,n=o.length; i<n; i++)
	               o[i] = X.toJson(o[i], "", ind+"\t");
	            json += (name?":[":"[") + (o.length > 1 ? ("\n"+ind+"\t"+o.join(",\n"+ind+"\t")+"\n"+ind) : o.join("")) + "]";
	         }
	         else if (o == null)
	            json += (name&&":") + "null";
	         else if (typeof(o) == "object") {
	            var arr = [];
	            for (var m in o)
	               arr[arr.length] = X.toJson(o[m], m, ind+"\t");
	            json += (name?":{":"{") + (arr.length > 1 ? ("\n"+ind+"\t"+arr.join(",\n"+ind+"\t")+"\n"+ind) : arr.join("")) + "}";
	         }
	         else if (typeof(o) == "string")
	            json += (name&&":") + "\"" + o.toString() + "\"";
	         else
	            json += (name&&":") + o.toString();
	         return json;
	      },
	      innerXml: function(node) {
	         var s = ""
	         if ("innerHTML" in node)
	            s = node.innerHTML;
	         else {
	            var asXml = function(n) {
	               var s = "";
	               if (n.nodeType == 1) {
	                  s += "<" + n.nodeName;
	                  for (var i=0; i<n.attributes.length;i++)
	                     s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue||"").toString() + "\"";
	                  if (n.firstChild) {
	                     s += ">";
	                     for (var c=n.firstChild; c; c=c.nextSibling)
	                        s += asXml(c);
	                     s += "</"+n.nodeName+">";
	                  }
	                  else
	                     s += "/>";
	               }
	               else if (n.nodeType == 3)
	                  s += n.nodeValue;
	               else if (n.nodeType == 4)
	                  s += "<![CDATA[" + n.nodeValue + "]]>";
	               return s;
	            };
	            for (var c=node.firstChild; c; c=c.nextSibling)
	               s += asXml(c);
	         }
	         return s;
	      },
	      escape: function(txt) {
	         return txt.replace(/[\\]/g, "\\\\")
	                   .replace(/[\"]/g, '\\"')
	                   .replace(/[\n]/g, '\\n')
	                   .replace(/[\r]/g, '\\r');
	      },
	      removeWhite: function(e) {
	         e.normalize();
	         for (var n = e.firstChild; n; ) {
	            if (n.nodeType == 3) {  // text node
	               if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node
	                  var nxt = n.nextSibling;
	                  e.removeChild(n);
	                  n = nxt;
	               }
	               else
	                  n = n.nextSibling;
	            }
	            else if (n.nodeType == 1) {  // element node
	               X.removeWhite(n);
	               n = n.nextSibling;
	            }
	            else                      // any other node
	               n = n.nextSibling;
	         }
	         return e;
	      }
	   };
	   if (xml.nodeType == 9) // document node
	      xml = xml.documentElement;
	   var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t");
	   var temp = "{\n" + tab + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "\n}";
	   temp = "(" + temp + ")";
	   return eval(temp);
	}
};
