//Possible prefixes ActiveX strings for DOM DOcument
var ARR_ACTIVEX = ["MSXML4.DOMDocument", "MSXML3.DOMDocument", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XmlDom"];

//When the proper prefix is found, store it here
var STR_ACTIVEX = "";

//browser detection
var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1;
var isMoz = document.implementation && document.implementation.createDocument;

//-----------------------------------------------------------------
// IE Initialization
//-----------------------------------------------------------------

//if this is IE, determine which string to use
if (isIE) {
    //define found flag
    var bFound = false;

    //iterate through strings to determine which one to use (NCZ, 1/30/02)
    for (var i=0; i < ARR_ACTIVEX.length && !bFound; i++) {

        //set up try...catch block for trial and error of strings (NCZ, 1/30/02)
        try {

            //try to create the object, it will cause an error if it doesn't work (NCZ, 1/30/02)
            var objXML = new ActiveXObject(ARR_ACTIVEX[i]);

            //if it gets to this point, the string worked, so save it and return
            //the DOM Document (NCZ, 1/30/02)
            STR_ACTIVEX = ARR_ACTIVEX[i];
            bFound = true

        } catch (objException) {
        } //End: try
    } //End: for

    //if we didn't find the string, send an error (NCZ, 1/30/02)
    if (!bFound)
       throw "No DOM DOcument found on your computer."

} //End: if

//-----------------------------------------------------------------
// Mozilla Initialization
//-----------------------------------------------------------------
if (isMoz && !window.opera) {

    //add the loadXML() method to the Document class
    Document.prototype.loadXML = function(strXML) {

        //change the readystate
        changeReadyState(this, 1);

        //create a DOMParser
        var objDOMParser = new DOMParser();

        //create new document from string
        var objDoc = objDOMParser.parseFromString(strXML, "text/xml");

        //make sure to remove all nodes from the document
		while (this.hasChildNodes())
			this.removeChild(this.lastChild);

        //add the nodes from the new document
        for (var i=0; i < objDoc.childNodes.length; i++) {

            //import the node
            var objImportedNode = this.importNode(objDoc.childNodes[i], true);

            //append the child to the current document
            this.appendChild(objImportedNode);

        } //End: for

        //we can't fire the onload event, so we fake it
        handleOnLoad(this);

    } //End: function

    //add the getter for the .xml attribute
    Node.prototype.__defineGetter__("xml", _Node_getXML);



    //add the readystate attribute for a Document
    Document.prototype.readyState = "0";

    //save a reference to the original load() method
    Document.prototype.__load__ = Document.prototype.load;

    //create our own load() method
    Document.prototype.load = _Document_load;

    //add the onreadystatechange attribute
    Document.prototype.onreadystatechange = null;

    //add the parseError attribute
    Document.prototype.parseError = 0;

} //End: if


//-----------------------------------------------------------------
// Factory jsXML
//-----------------------------------------------------------------
// Author(s)
//  Nicholas C. Zakas (NCZ), 1/30/02
//
// Description
//  This factory will serve as the entry point for other XML-related
//  implementations.
//
// Parameters
//  (none)
//-----------------------------------------------------------------
function jsXML() { }

//-----------------------------------------------------------------
// Function jsXML.createDocument()
//-----------------------------------------------------------------
// Author(s)
//  Nicholas C. Zakas (NCZ), 1/30/02
//
// Description
//  This function creates a XML Document according to which browser
//  is being used.
//
// Parameters
//  strNamespaceURI (String) - the namespace for this document (optional).
//  strRootTagName (String) - the tag name for the documentElement (optional).
//
// Returns
//  The XML Document object that was created.
//-----------------------------------------------------------------
jsXML.createDOMDocument = function() {
    var strNamespaceURI = arguments[0];
    var strRootTagName = arguments[1];

    //variable for the created DOM Document
    var objDOM = null;

    //determine if this is a standards-compliant browser like Mozilla
    if (isMoz) {

        //create the DOM Document the standards way
        objDOM = document.implementation.createDocument(strNamespaceURI, strRootTagName, null);

        //add the event listener for the load event
        objDOM.addEventListener("load", _Document_onload, false);

    } else if (isIE) {

        //create the DOM Document the IE way
        objDOM = new ActiveXObject(STR_ACTIVEX);

        //if there is a root tag name, we need to preload the DOM
        if (strRootTagName) {

            //If there is both a namespace and root tag name, then
            //create an artifical namespace reference and load the XML.
            if (strNamespaceURI) {
                objDOM.loadXML("<a0:" + strRootTagName + " xmlns:a0=\"" + strNamespaceURI + "\" />");
            } else {
                objDOM.loadXML("<" + strRootTagName + "/>");
            }

        }
    }
    else{
        objDOM = new XMLHttpRequest();
    }
    //return the object
    return objDOM;
}

//-----------------------------------------------------------------
// Functon _Node_getXML()
//-----------------------------------------------------------------
// Author(s)
//  Nicholas C. Zakas (NCZ), 2/23/02
//
// Description
//  This is the attribute getter for the .xml attribute.
//
// Parameters
//  (none)
//
// Returns
//  A string with the XML of the Node calling this function.
//-----------------------------------------------------------------
function _Node_getXML() {

    //create a new XMLSerializer
    var objXMLSerializer = new XMLSerializer;

    //get the XML string
    var strXML = objXMLSerializer.serializeToString(this);

    //return the XML string
    return strXML;
}


//-----------------------------------------------------------------
// Function _Document_load()
//-----------------------------------------------------------------
// Author(s)
//  Nicholas C. Zakas (NCZ), 2/24/02
//
// Description
//  This function replaces the native load() method to allow for
//  readyState changes.
//
// Parameters
//  strURL (String) - The XML file to load.
//
// Returns
//  (nothing)
//-----------------------------------------------------------------
function _Document_load(strURL) {

    //set the parseError to 0
    this.parseError = 0;

    //change the readyState
    changeReadyState(this, 1);

    //watch for errors
    try {
        //call the original load method
        this.__load__(strURL);

    } catch (objException) {

        //set the parseError attribute
        this.parseError = -9999999;

        //change the readystate
        changeReadyState(this, 4);

    } // End: try...catch
}

//-----------------------------------------------------------------
// Function _Document_onload()
//-----------------------------------------------------------------
// Author(s)
//  Nicholas C. Zakas (NCZ), 2/24/02
//
// Description
//  This function is the event handler for the load event.
//
// Parameters
//  (none)
//
// Returns
//  (nothing)
//-----------------------------------------------------------------
function _Document_onload() {

    //handle the onload event
    handleOnLoad(this);
}

//-----------------------------------------------------------------
// Function handleOnLoad()
//-----------------------------------------------------------------
// Author(s)
//  Nicholas C. Zakas (NCZ), 2/24/02
//
// Description
//  This function handles the load event on the Document object.
//
// Parameters
//  objDOMDocument (Document) - the DOM Document object that has been loaded.
//
// Returns
//  (nothing)
//-----------------------------------------------------------------
function handleOnLoad(objDOMDocument) {
    //check for a parsing error
    if (!objDOMDocument.documentElement || objDOMDocument.documentElement.tagName == "parsererror")
        objDOMDocument.parseError = -9999999;

    //change the readyState
    changeReadyState(objDOMDocument, 4);
}

//-----------------------------------------------------------------
// Function changeReadyState()
//-----------------------------------------------------------------
// Author(s)
//  Nicholas C. Zakas (NCZ), 2/24/02
//
// Description
//  This function changes the readyState of a Document to the desired
//  state and runs any event handler the user has assigned.
//
// Parameters
//  objDOMDocument (Document) - the DOM Document object that has been loaded.
//  iReadyState (int) - the readyState to set the DOM Document to.
//
// Returns
//  (nothing)
//-----------------------------------------------------------------
function changeReadyState(objDOMDocument, iReadyState) {

    //change the readyState
    objDOMDocument.readyState = iReadyState;

    //if there is an onreadystatechange event handler, run it
    if (objDOMDocument.onreadystatechange != null && typeof objDOMDocument.onreadystatechange == "function")
        objDOMDocument.onreadystatechange();
}

if( document.implementation.hasFeature("XPath", "3.0") && !window.opera )
{
	XMLDocument.prototype.selectNodes = function(cXPathString, xNode)
	{
		if( !xNode ) { xNode = this; }

		var oNSResolver = this.createNSResolver(this.documentElement)
		var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
		var aResult = [];
		for( var i = 0; i < aItems.snapshotLength; i++)
		{
			aResult[i] =  aItems.snapshotItem(i);
		}

		return aResult;
	}
	XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode)
	{
		if( !xNode ) { xNode = this; }

		var xItems = this.selectNodes(cXPathString, xNode);
		if( xItems.length > 0 )
		{
			return xItems[0];
		}
		else
		{
			return null;
		}
	}

	Element.prototype.selectNodes = function(cXPathString)
	{
		if(this.ownerDocument.selectNodes)
		{
			return this.ownerDocument.selectNodes(cXPathString, this);
		}
		else{throw "For XML Elements Only";}
	}

	Element.prototype.selectSingleNode = function(cXPathString)
	{
		if(this.ownerDocument.selectSingleNode)
		{
			return this.ownerDocument.selectSingleNode(cXPathString, this);
		}
		else{throw "For XML Elements Only";}
	}

}
