/*
  Java Script file: xml.js
       Description: This JS file contains JavaScript functions that offer
                    the functionality of accessing XML data embedded in
                    a HTML document

  Modification History

  Date         By   Version   Description
  Oct 13 2008  GL   v1.0      Created this JS as part of the effort to develop
                              a web application for CP to enter sales opportunity

*/

  /*
    Function: XMLDoc
     Purpose: Constructor for the XMLDoc class
  */
  function XMLDoc(xmlText){
    var browser;
    
    this.xmlText = xmlText;
    this.Document = null;
    this.root = null;
    this.Status = "";
    this.Content = "";
    this.ItemID = "0";
    this.Initialize = InitializeXML;
    this.GetBrowserType = XMLGetBrowserType;
    this.LoadXML = LoadXML;
    this.Initialize();
    browser = XMLGetBrowserType();
    this.browser = browser;

  } // End of XMLDoc constructor

  function GetXMLFromText(xmlText){
    var xmlDoc;
    var error;
    var browser;
    var parser;

    xmlDoc = null;
    error = "[GetXMLFromText] Fail to create an XML document object. ";
    if (xmlText != null){
      try{
        browser = XMLGetBrowserType();
        if (browser == "Internet Explorer"){
          xmlDoc = new ActiveXObject("MSXML2.DOMDocument");
          xmlDoc.async="false";
          xmlDoc.loadXML(xmlText);
        }
        else {
          parser = new DOMParser();
          xmlDoc=parser.parseFromString(xmlText,"text/xml");
        }
      }
      catch (exp){
        error = "Unable to load the given text into a XML document object. " +
                 exp;
        throw (error);
      }
    } // Verify that the parameter is defined
    return xmlDoc;
  } // End of GetXMLFromText
  
  function XMLGetBrowserType(){
    var browser;
    browser = navigator.userAgent.toLowerCase();
    if (browser.indexOf("opera") != -1) return 'Opera';
    if (browser.indexOf("staroffice") != -1) return 'Star Office';
    if (browser.indexOf("webtv") != -1) return 'WebTV';
    if (browser.indexOf("beonex") != -1) return 'Beonex';
    if (browser.indexOf("chimera") != -1) return 'Chimera';
    if (browser.indexOf("netpositive") != -1) return 'NetPositive';
    if (browser.indexOf("phoenix") != -1) return 'Phoenix';
    if (browser.indexOf("firefox") != -1) return 'Firefox';
    if (browser.indexOf("safari") != -1) return 'Safari';
    if (browser.indexOf("skipstone") != -1) return 'SkipStone';
    if (browser.indexOf("msie") != -1) return 'Internet Explorer';
    if (browser.indexOf("netscape") != -1) return 'Netscape';
    if (browser.indexOf("mozilla/5.0") != -1) return 'Mozilla';
    if (browser.indexOf('\/') != -1) {
    if (browser.substr(0,browser.indexOf('\/')) != 'mozilla') {
    return navigator.userAgent.substr(0,browser.indexOf('\/'));}
    else return 'Netscape';} else if (browser.indexOf(' ') != -1)
    return navigator.userAgent.substr(0,browser.indexOf(' '));
    else return navigator.userAgent;
  } // End of XMLGetBrowserType


  /*
    Function: XMLElement
     Purpose: Constructor for the XMLElement class
  */
  function XMLElement(name){
    var xmlDoc;
    var xmlText;
    var xpath;
    var browser;
    var error;

    xmlDoc = null;
    error = "[XMLElement] Fail to create a XMLElement object. ";
    if (name != null){
      xmlText = "<" + name + "/>";
      xmlDoc = GetXMLFromText(xmlText);
      this.xmlDoc = xmlDoc;
      this.name = name;
      this.SelectSingleNode = SelectSingleNode;
      this.SelectNodes = SelectNodes;
      xpath = "/" + name;
      browser = XMLGetBrowserType();
      this.browser = browser;
      this.element = xmlDoc.documentElement;
      this.AppendChild = AppendChild;
      this.GetAttribute = GetXMLAttributeValue;
    } // Check if the paremeter is defined
  } // End of XMLElement
  
  

  /*
    Function: AppendChild
     Purpose: Appends a child XML element to an element in the
              given XML document
  */
  function AppendChild(childName, xpath, attributeXMLText){
    var xmlAttributeDoc;
    var attributeList;
    var itemCount;
    var itemIndex;
    var elementl
    var elementName;
    var attributeName;
    var attributeValue;
    var error;
    var childXML;
    var browser;

    error = "[AppendChild] Fail to append a child element. ";
    if (childName != null && xpath!= null && attributeXMLText != null){
      if (this.xmlDoc != null) {
        try{
          xmlAttributeDoc = GetXMLFromText(attributeXMLText);
          attributeList = this.SelectNodes(xmlAttributeDoc.documentElement,xpath);
          if (attributeList != null){
            itemCount = attributeList.length;
            if (itemCount > 0){
              childXML = this.xmlDoc.createElement(childName);
              browser = XMLGetBrowserType();
              
              for (itemIndex=0; itemIndex < itemCount; itemIndex++){
                elementName = attributeList[itemIndex].getAttribute("elementName");
                attributeName = attributeList[itemIndex].getAttribute("name");
                attributeValue = attributeList[itemIndex].getAttribute("value");
                element = this.xmlDoc.createElement(elementName);
                
                element.setAttribute("name", attributeName);
                element.setAttribute("value", attributeValue);
                childXML.appendChild(element);
              } // Loop
              this.element.appendChild(childXML);
            }
            else{
              error += "Unable to gather any attribute node using the XPath expression, " + xpath;
              throw (error);
            }
          }
          else{
            error += "Unable to gather the list of attribute nodes using the XPath expresion, " + xpath;
            throw(error);
          }
        }
        catch (exp){
          error += exp;
          throw(error);
        }
       } // Verify that the XML document property has been initialized
      } // Check if the parameters are defined
    } // End of AppendChild
  
  function SelectSingleNode(element, xpath){
    var browser;
    var node;
    var xpathEval;
    var result;
    var doc;
    
    node = null;
    browser = this.browser;
    if (browser == "Internet Explorer"){
      node = element.selectSingleNode(xpath);
    }
    else {
      doc = element;
      if (element.documentOwner){
        doc = element.documentOwner;
      }
      xpathEval = new XPathEvaluator();
      result = xpathEval.evaluate(xpath, doc, null, 
                                  XPathResult.FIRST_ORDERED_NODE_TYPE, null);    
  	  
      if (result != null) {
        node = result.singleNodeValue;
      } // Check if the XPath query returned any result
      
    } // Firefox browser
    return node;
  } // End of SelectSingleNode  

  function SelectNodes(element, xpath){
    var browser;
    var nodeList;
    var xpathEval;
    var nsResolver;
    var result;
    var node;
    var error;
    var doc;
    var itemIndex;
    var itemCount;
    
    nodeList = null;
    error = "[SelectNodes] Fail to gather a list of XML nodes. ";
    browser = this.browser;
    if (browser == "Internet Explorer"){
      nodeList = element.selectNodes(xpath);
    }
    else{
      if (document.implementation.hasFeature("XPath", "3.0")){
        try{
          xpathEval = new XPathEvaluator();
          doc = element;
          if (element.documentOwner){
            doc = element.documentOwner;
          }
          // nsResolver = doc.createNSResolver(doc.documentElement);
          result = xpathEval.evaluate(xpath, doc, null, 
                                      XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
      	  if (result != null){
      	    itemIndex = 0;
      	    nodeList = new Array;
      	    node = result.iterateNext();
      	    while (node){
      	      nodeList.push(node);
      	      itemIndex++;
      	      node = result.iterateNext();      	      
            } // Loop
          }
        }
        catch (exp){
          error += exp;
          alert(error);
        }
      }
    } // Firefox browser
    return nodeList;
  } // End of SelectNodes
  
  function GetXMLAttributeValue(element, attributeName){
    var value;
    
    value = "";
    if (this.browser == "Internet Explorer"){
      value = element.getAttribute(attributeName);
    }
    else{
      value = element.attributes[attributeName].value;
    }
    return value;
  } // End of GetXMLAttributeValue  

  function LoadXML(xmlText){
    var xmlDoc;
    var error;
    var browser;
    var parser;
    var isLoadSuccessful;

    xmlDoc = null;
    isLoadSuccessful = false;
    if (xmlText != null){
      try{
        browser = this.GetBrowserType();
        if (browser == "Internet Explorer"){
          xmlDoc = new ActiveXObject("MSXML2.DOMDocument");
          xmlDoc.async="false";
          xmlDoc.loadXML(xmlText);
          isLoadSuccessful = true;
        }
        else {
          parser = new DOMParser();
          xmlDoc=parser.parseFromString(xmlText,"text/xml");
          isLoadSuccessful = true;
        }
      }
      catch (exp){
        error += "Unable to load the given text into a XML document object. " +
                 exp;
        throw (error);
      }
    } // Verify that the parameter is defined
    this.Document = xmlDoc;
    return isLoadSuccessful;
  } // End of LoadXML

  
  function InitializeXML(){
    var error;

    error = "[Initialize] Fail to initialize the XMLDoc class. ";
    if (this.xmlText != null){
      if (this.LoadXML(this.xmlText)){
        try{
          this.root = this.Document.documentElement;

        }
        catch (exp){
          error += exp;
          throw (error);
        }
      }
    }
  } // End of Initialize function

