var XMLParser = {

    xml2hash: function(xmlDocElem, tagItemName) {
        var self = XMLParser;
        var xmlElemArray = new Array;
        var xmlElemRow;
        var objArray = [];
        if(!tagItemName) {
            tagItemName = 'item';
        }
        
        if (xmlDocElem.hasChildNodes()) {
            xmlElemArray = xmlDocElem.getElementsByTagName(tagItemName);
            xmlElemRow = xmlElemArray[0];
            for (var j = 0; j < xmlElemArray.length; j++) {
                xmlElemRow = xmlElemArray[j];
                objArray[j] = self.xmlElem2Obj(xmlElemArray[j]);
            }
        }

        var linkEl = xmlDocElem.getElementsByTagName("link")[0];
        if(linkEl.firstChild) {
            var siteUrl = linkEl.firstChild.nodeValue;
        } else if(linkEl.attributes["href"]) {
            var siteUrl = linkEl.attributes["href"].nodeValue;
        } 
        if(xmlDocElem.getElementsByTagName("title")[0]) {
            var title = xmlDocElem.getElementsByTagName("title")[0].firstChild.nodeValue;
        }

        return title ? { title: title, siteUrl: siteUrl, items: objArray} : null;
    },

    parseBookmarks: function(node) {
        var self = XMLParser;
        var res = [];
        var tags = [];
        self.parseBookmarksNode(res, tags, node.getElementsByTagName("DL")[0]);
        return res ? res : null;
    },



    parseBookmarksNode: function(res, tags, node) {
        var self = XMLParser;
        switch(node.tagName) {
            case "A":
                var curTags = clone(tags);
                res.push({ title: node.firstChild.nodeValue, 
                           url: node.getAttribute("HREF"), 
                           tags: curTags.length>0 ? curTags : null});
                break;
            case "H3":
                tags.push(node.firstChild.nodeValue);
                break;
            case "DL":
                for(var i=0; i<node.childNodes.length; i++) {
                    if(node.childNodes[i].nodeType == 1 && node.childNodes[i].firstChild) {
                        self.parseBookmarksNode(res, tags, node.childNodes[i]);
                    }
                }
                tags.pop();
                break;                
        }
        return res;
    },

    
    xmlElem2Obj: function(xmlElem) {
        var self = XMLParser;
        var ret = new Object();
        self.setPropertiesRecursive(ret, xmlElem);
        return ret;
    },
    
    setPropertiesRecursive: function(obj, node) {
        var self = XMLParser;
        if (node.childNodes.length > 0) {
            for (var i = 0; i < node.childNodes.length; i++) {
                if (node.childNodes[i].nodeType == 1) {
                    if(node.childNodes[i].firstChild) {
                        if(node.childNodes[i].childNodes.length == 1) {
                            obj[node.childNodes[i].tagName] = node.childNodes[i].firstChild.nodeValue;
                        }
                        else {
                            obj[node.childNodes[i].tagName] = [];
                            self.setPropertiesRecursive(obj[node.childNodes[i].tagName], node.childNodes[i]);
                        }
                    }
                     else if (node.childNodes[i].attributes.length>0) {
                        var attrs = {};
                        for(var a = 0; a < node.childNodes[i].attributes.length; a++) {
                            attrs[node.childNodes[i].attributes[a].nodeName] = node.childNodes[i].attributes[a].nodeValue;
                        }
                        obj[node.childNodes[i].tagName] = attrs;
                    } 
                }
            }
        }
    },
    
    cleanXMLObjText: function(xmlObj) {
        var self = XMLParser;
        var cleanObj = xmlObj;
        for (var prop in cleanObj) {
            cleanObj[prop] = cleanText(cleanObj[prop]);
        }
        return cleanObj;
    },
    
    cleanText: function(str) {
        var self = XMLParser;
        var ret = str;
        ret = ret.replace(/\n/g, '');
        ret = ret.replace(/\r/g, '');
        ret = ret.replace(/\'/g, "\\'");
        ret = ret.replace(/\[CDATA\[/g, '');
        ret = ret.replace(/\]]/g, '');
        return ret;
    },
    
    rendered2Source: function(str) {
        var self = XMLParser;
        var proc = str;    
        proc = proc.replace(/</g, '&lt;');
        proc = proc.replace(/>/g, '&gt;');
        return '<pre>' + proc + '</pre>';
    },

    getXMLDocElem: function(xmlDivId, xmlNodeName) {
        var self = XMLParser;
        var xmlElemArray = [];
        var xmlDocElem = null;
        if (document.all) {
                var xmlStr = document.getElementById(xmlDivId).innerHTML;
                var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
                xmlDoc.loadXML(xmlStr);    
                xmlDocElem = xmlDoc.documentElement;
          }
          else {
            xmlElemArray = window.document.body.getElementsByTagName(xmlNodeName);
            xmlDocElem = xmlElemArray[0]; ;
          }
          return xmlDocElem;
    }
}