/**
 * Helper function to get the active X xml parser to use
 * for the xml http object.
 * @return the prifix for the XmlHttp active x object to use.
 */
function getXmlHttpPrefix()
{
  if (getXmlHttpPrefix.prefix)
  {
    return getXmlHttpPrefix.prefix;
  }

  var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
  var activeXObj;
  for (var i = 0; i < prefixes.length; i++)
  {
    try
    {
      // try to create the objects
      activeXObj = new ActiveXObject(prefixes[i] + ".XmlHttp");
      return getXmlHttpPrefix.prefix = prefixes[i];
    }
    catch (ex)
    {
    }
  }

  throw new Error("Could not find an installed XML parser");
}

/**
 * The XML Http helper object.
 * This xml object allows you to post an xml data
 * to a server without leaving the current page.
 */
function XmlHttp()
{
}
XmlHttp.READY_STATE_UNINITIALIZED = 0;
XmlHttp.READY_STATE_LOADING = 1;
XmlHttp.READY_STATE_LOADED = 2;
XmlHttp.READY_STATE_INTERACTIVE = 3;
XmlHttp.READY_STATE_COMPLETED = 4;

/**
 * A create function for the XMLHttp object.
 */
XmlHttp.create = function ()
  {
    try
    {
      if (window.XMLHttpRequest)
      {
        var req = new XMLHttpRequest();

        // some versions of Moz do not support the readyState property
        // and the onreadystate event so we patch it!
        if (req.readyState == null)
        {
          req.readyState = 1;
          req.addEventListener("load", function ()
            {
              req.readyState = 4;
              if (typeof req.onreadystatechange == "function")
              {
                req.onreadystatechange();
              }
            },
            false);
        }

        return req;
      }
      if (window.ActiveXObject)
      {
        return new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp");
      }
    }
    catch (ex)
    {
    }
    // fell through
    throw new Error("Your browser does not support XmlHttp objects");
  }

function getDomDocumentPrefix() 
{
  if (getDomDocumentPrefix.prefix)
  {
    return getDomDocumentPrefix.prefix;
  }
  
  var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
  var activeXObj;
  for (var i = 0; i < prefixes.length; i++) 
  {
    try 
    {
      // try to create the objects
      activeXObj = new ActiveXObject(prefixes[i] + ".DomDocument");
      return getDomDocumentPrefix.prefix = prefixes[i];
    }
    catch (ex) 
    {
    };
  }
  
  throw new Error("Could not find an installed XML parser");
}

// XmlDocument factory
function XmlDocument() {}

XmlDocument.create = function () {
  try {
    // DOM2
    if (document.implementation && document.implementation.createDocument) {
      var doc = document.implementation.createDocument("", "", null);
      
      // some versions of Moz do not support the readyState property
      // and the onreadystate event so we patch it!
      if (doc.readyState == null) 
      {
        doc.readyState = 1;
        doc.addEventListener("load", function () 
        {
          doc.readyState = 4;
          if (typeof doc.onreadystatechange == "function")
            doc.onreadystatechange();
        }, false);
      }
      
      return doc;
    }
    if (window.ActiveXObject)
      return new ActiveXObject(getDomDocumentPrefix() + ".DomDocument");
  }
  catch (ex) 
  {
  }
  throw new Error("Your browser does not support XmlDocument objects");
};



// Create the loadXML method and xml getter for Mozilla
if (window.DOMParser && window.XMLSerializer &&
  window.Node && Node.prototype && Node.prototype.__defineGetter__)
{

  // XMLDocument did not extend the Document interface in some versions
  // of Mozilla. Extend both!
  //XMLDocument.prototype.loadXML =
  Document.prototype.loadXML = function (s)
    {

      // parse the string to a new doc
      var doc2 = (new DOMParser()).parseFromString(s, "text/xml");

      // remove all initial children
      while (this.hasChildNodes())
      {
        this.removeChild(this.lastChild);
      }
      // insert and import nodes
      for (var i = 0; i < doc2.childNodes.length; i++)
      {
        this.appendChild(this.importNode(doc2.childNodes[i], true));
      }
    }


  /**
   * xml getter
   *
   * This serializes the DOM tree to an XML String
   *
   * Usage: var sXml = oNode.xml
   *
   */
  Document.prototype.__defineGetter__("xml", function ()
  {
    return (new XMLSerializer()).serializeToString(this);
  });
}

/**
 * This function loads the XML document from the specified URL and, when
 * it is fully loaded, passes that document and the URL to the specified
 * handler function. This function works with any XML document.
 */
function xmlLoader(uri, handler, errorHandler)
{

  var xmlHttp = XmlHttp.create();

  // The following two lines are to force the browse not to return
  // a cached copy of the requested xml
  var timestamp = new Date();
  var uniqueURI = uri+(uri.indexOf("?") > 0 ? "&" : "?")+"timestamp="+timestamp.getTime();

  var args = new Array();
  for(var i = 3; i < arguments.length; i++)
  {
    args[args.length] = arguments[i];
  }

  xmlHttp.open("GET", uniqueURI, true);
  {
    xmlHttp.onreadystatechange = function () 
    {
      if (xmlHttp.readyState == 4)
      {
      	if(errorHandler && xmlHttp.status != 200){
      		errorHandler(xmlHttp, args);
      		return;
      	}
       	if (xmlHttp.responseText && xmlHttp.responseText.indexOf("<forceTop") > -1)
		{
			document.location = uniqueURI;
			return;
		}
		try{
	        handler(xmlHttp, args);
	    }catch(error){}
      }
    }
  }
  xmlHttp.send(null);
}

function alertHandler(xmlHttp)
{
  alert("Response Text: " + xmlHttp.responseText);
}

/**
 * Handler to replace the content of a specified element with
 * the content retrieved from a uri.  This handler should be passed into
 * loadXML 
 * @param xmlHttp the xml document to use as the content of the 
 *        specified element Id.
 * @param elementId the id of the element whose inner html should be replaced.
 */
function replaceElementContentHandler(xmlHttp, contentElementId)
{
  try
  {
    document.getElementById(contentElementId).innerHTML = xmlHttp.responseText;
  }
  catch (exc)
  {
    alert("An error occurred <br/>" +
      "Message: " + exc.message + "<br/>" +
      "File: " + exc.fileName + "<br/>" +
      "Line: " + exc.lineNumber + "<br/>" +
      "Name: " + exc.name);
  }
}

/**
 * Function to get a string representation of an attribute. 
 * Uses classes from xmlutil.css for formatting.
 * @param attribute the attribute node to get the string repesentation of.
 * @return the string representation of the specified attribute node.
 */
function xmlAttributeToString(attribute) 
{
  return " <span class='attribname'>" + attribute.nodeName + 
    "</span><span class='attribvalue'>=\"" + attribute.nodeValue + 
    "\"</span>";
}

/**
 * Function to get the string representation of an object.
 * @obj the object to get the string representation for.
 * @return the string representation of the object passed in.
 */
function inspect(obj) 
{
  var objToString = "";
  for (var k in obj)
  {
    objToString += "obj." + k + " = " + obj[k] + "\n";
  }
  return objToString;
}

/**
 * Function to get the a displayable version of the
 * specified xml node.
 * This function produces elements with classes defined
 * in xmlutil.css.
 * @param the node to get the displayable version of.
 * @indent the number of spaces to indent the children.
 */
function xmlNodeToString(node, indent) 
{
  if (node == null)
  {
    return "";
  }
  
  var str = "";
  
  switch (node.nodeType) 
  {
    case 1: // Element
      str += "<div class='element'>&lt;<span class='elementname'>" + 
        node.nodeName + "</span>";
      
      var attrs = node.attributes;
      for (var i = 0; i < attrs.length; i++)
      {
        str += xmlAttributeToString(attrs[i]);
      }
      
      if (!node.hasChildNodes())
      {
        return str + "/&gt;</div>";
      }
      
      str += "&gt;<br />";
      
      var cs = node.childNodes;
      for (var i = 0; i < cs.length; i++)
      {
        str += xmlNodeToString(cs[i], indent + 3);
      }
      
      str += "&lt;/<span class='elementname'>" + node.nodeName + 
        "</span>&gt;</div>";
      break;
  
    case 9: // Document
      var cs = node.childNodes;
      for (var i = 0; i < cs.length; i++)
      {
        str += xmlNodeToString(cs[i], indent);
      }
      break;
  
    case 3: // Text
      if (!/^\s*$/.test(node.nodeValue))
      {
        str += "<span class='text'>" + node.nodeValue + "</span><br />";
      }
      break;
  
    case 7: // ProcessInstruction
      str += "&lt;?" + node.nodeName;
    
      var attrs = node.attributes;
      for (var i = 0; i < attrs.length; i++)
      {
        str += xmlNodeToString(attrs[i]);
      }
      
      str+= "?&gt;<br />"
      break;
  
    case 4: // CDATA
      str = "<div class='cdata'>&lt;![CDATA[<span class='cdata-content'>" + 
        node.nodeValue + "</span>]" + "]></div>";
      break;
      
    case 8: // Comment
      str = "<div class='comment'>&lt;!--<span class='comment-content'>" + 
        node.nodeValue + "</span>--></div>";
      break;
    
    case 10:
        str = "<div class='doctype'>&lt;!DOCTYPE " + node.name;
        if (node.publicId) 
        {
          str += " PUBLIC \"" + node.publicId + "\"";
          if (node.systemId) 
          {
            str += " \"" + node.systemId + "\"";
          }
        }
        else if (node.systemId) 
        {
          str += " SYSTEM \"" + node.systemId + "\"";
        }
        str += "&gt;</div>";        
        break;
    
    default:
      inspect(node);
  }
  
  return str;
}

/**
 * function to html encode an xml string.
 * @param xml the xml string that should be encoded to make viewable
 *        on an html page.
 */
function encodeXMLforHTML(xml)
{
  return xml.replace(/\&/g, "&amp;").replace(/\</g, "&lt;").replace(/\>/g, "&gt;").replace(/\t/g, "&nbsp;&nbsp;&nbsp;").replace(/\n/g, "<br />");
}


function getSimpleElementValue(node)
{
	var childNodes = node.childNodes;
	var value = '';

	if (childNodes)
	{
		var child;
		for (var i = 0; i < childNodes.length; i++)
		{
			child = childNodes[i];
			if (child.nodeType == 3)
			{
				value = child.nodeValue;
			}
		}
	}

	return value;
}























