/**
 * Create a new Document object. If no arguments are specified,
 * the document will be empty. If a root tag is specified, the document
 * will contain that single root tag. If the root tag has a namespace
 * prefix, the second argument must specify the URL that identifies the
 *namespace.
 */
XMLNewDocument = function(rootTagName, namespaceURL) {
    if (!rootTagName) rootTagName = "";
    if (!namespaceURL) namespaceURL = "";

    if (document.implementation && document.implementation.createDocument) {
        // This is the W3C standard way to do it
        return document.implementation.createDocument(namespaceURL, 
                       rootTagName, null);
    }
    else { // This is the IE way to do it
        // Create an empty document as an ActiveX object
        // If there is no root element, this is all we have to do
        var doc = new ActiveXObject("MSXML2.DOMDocument");

        // If there is a root tag, initialize the document
        if (rootTagName) {
            // Look for a namespace prefix
            var prefix = "";
            var tagname = rootTagName;
            var p = rootTagName.indexOf(':');
            if (p != -1) {
                prefix = rootTagName.substring(0, p);
                tagname = rootTagName.substring(p+1);
            }

            // If we have a namespace, we must have a namespace prefix
            // If we don't have a namespace, we discard any prefix
            if (namespaceURL) {
                if (!prefix) prefix = "a0"; // What Firefox uses
            }
            else prefix = "";

            // Create the root element (with optional namespace) as a
            // string of text
            var text = "<" + (prefix?(prefix+":"):"") + tagname +
                (namespaceURL
                 ?(" xmlns:" + prefix + '="' + namespaceURL +'"')
                 :"") +
                "/>";
            // And parse that text into the empty document
            doc.loadXML(text);
        }
        return doc;
    }
}; 

/**
 * Synchronously load the XML document at the specified URL and
 * return it as a Document object
 */
XMLLoad = function(url) {
    // Create a new document with the previously defined function
    var xmldoc = XMLNewDocument();
    xmldoc.async = false;  // We want to load synchronously
    xmldoc.load(url);      // Load and parse
    return xmldoc;         // Return the document
}; 

/**
 * Asynchronously load and parse an XML document from the specified URL.
 * When the document is ready, pass it to the specified callback function.
 * This function returns immediately with no return value.
 */
XMLLoadAsync = function(url, callback) {
    var xmldoc = XMLNewDocument();

    // If we created the XML document using createDocument, use
    // onload to determine when it is loaded
    if (document.implementation && document.implementation.createDocument) {
        xmldoc.onload = function() { callback(xmldoc); };
    }
    // Otherwise, use onreadystatechange as with XMLHttpRequest
    else {
        xmldoc.onreadystatechange = function() {
            if (xmldoc.readyState == 4) callback(xmldoc);
        };
    }

    // Now go start the download and parsing
    xmldoc.load(url);
}; 

/**
 * Parse the XML document contained in the string argument and return
 * a Document object that represents it.
 */
XMLParse = function(text) {
try {
    if (typeof DOMParser != "undefined") {
        // Mozilla, Firefox, and related browsers
        return (new DOMParser()).parseFromString(text, "application/xml");
    }
    else if (typeof ActiveXObject != "undefined") {
        // Internet Explorer.
        var doc = XMLNewDocument( );   // Create an empty document
        doc.loadXML(text);              //  Parse text into it
        return doc;                     // Return it
    }
    else {
        // As a last resort, try loading the document from a data: URL
        // This is supposed to work in Safari. Thanks to Manos Batsis and
        // his Sarissa library (sarissa.sourceforge.net) for this technique.
        var url = "data:text/xml;charset=utf-8," + encodeURIComponent(text);
        var request = new XMLHttpRequest();
        request.open("GET", url, false);
        request.send(null);
        return request.responseXML;
    }
  }
  catch (e) {
     alert("parser error:\n" + e);
  }
}; 

XMLCreateNode = function(doc, nodeName, nodeValue) {
    var node = doc.createElement(nodeName);
    
    if (nodeValue != null) {
        //node.childNodes[0].nodeValue = nodeValue;
        var textnode = doc.createTextNode(nodeValue);
        node.appendChild(textnode);
    }
    
    return node;
}


XMLGetSpaces = function(count) {
   var s = "";
   for (var i = 0; i < count; i++)
       s += "  ";
   return s;
}

XMLGetNodeText = function(node) {
//writeln("getnodetext " + node.nodeName);
    if (node == null)
        return "";
        
    if (node.childNodes.length > 0) {
        var child = node.childNodes[0];
        if (child.nodeType == 3)
            return child.nodeValue;
    }
    
    return "";
}


XMLGetNode = function(node, nodeName) {
    nodes = node.getElementsByTagName(nodeName);
    if (nodes.length == 0)
        return null;
    return nodes[0];
}
    
XMLGetNodeList = function(node, nodeName) {
    n = node.getElementsByTagName(nodeName);
    return n;
}

XMLFindNodeText = function(node, nodeName) {
    n = XMLGetNode(node, nodeName);
    return XMLGetNodeText(n);
}

XMLGetXML = function(node, indent, pretty) {
    var i;
    var xmlStr = "";

    if (node.nodeType == 3)
        return;
    var text = XMLGetNodeText(node);
    
    if (pretty) xmlStr += XMLGetSpaces(indent, " ");
    
    if (text == "") {
        xmlStr += "<" + node.nodeName + ">";
        if (pretty) xmlStr += "\n";
        if (node.childNodes.length > 0)
            for (var i = 0; i < node.childNodes.length; i++)
                xmlStr += XMLGetXML(node.childNodes[i], indent + 1, pretty);
        if (pretty) xmlStr += XMLGetSpaces(indent);
        xmlStr += "</" + node.nodeName + ">";
        if (pretty) xmlStr += "\n";
    }
    else {
        xmlStr += "<" + node.nodeName + ">" + text + "</" + node.nodeName + ">";
        if (pretty) xmlStr += "\n";
    }
    
    return xmlStr;
}

function XMLDoc() {
    this.root = null;
    this.doc = null;
    this.curNode = null;
    this.xmlStr = "";
    
    this.parse = function(xmlstr) {
        this.doc = XMLParse(xmlstr);
        this.root = this.doc.documentElement;
        this.curNode = this.root;
    }
    
    this.pushNewNode = function(nodeName) {
        var node = XMLCreateNode(this.doc, nodeName, null);
        this.curNode.appendChild(node);
        this.curNode = node;
    }
    
    this.popNode = function() {
        if (this.curNode != this.root)
            this.curNode = this.curNode.parentNode;
    }
    
    this.addTextNode = function(nodeName, nodeText) {
        var node = XMLCreateNode(this.doc, nodeName, nodeText);
        this.curNode.appendChild(node);
    }

    this.toXML = function(pretty) {
        this.xmlStr = "";
        this.xmlStr = XMLGetXML(this.root, 0, pretty);
        return this.xmlStr;
    } 
}

XMLAjaxRequest=function()
{
    var xmlHttp;

    try {
        // Firefox, Opera 8.0+, Safari
        xmlHttp=new XMLHttpRequest();
    }
    catch (e) {
        // Internet Explorer
        try {
            xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e) {
            try {
                xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e) {
                alert("Your browser does not support AJAX!");
                return false;
            }
        }
     }
  
     return xmlHttp;
 }
 