/*****************************************************************************
**
**  created by : declercq Carl
**
**
**  purpose : all basic xml manipuation with javascript
**
**
**
****************************************************************************/
function ImportXML(name)
{
   var xmlDoc=null;

   //if IE load the xml (better function)
   if(!window.opera && window.ActiveXObject && document.all)
   {
      xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
      xmlDoc.async = false;
      xmlDoc.load(name);
      if (xmlDoc.parseError.errorCode != 0) 
      {
         var myErr = xmlDoc.parseError;
         alert("You have error " + myErr.reason);
      }      
      return xmlDoc;
   }
   
   xmlDoc = new XMLHttpRequest();
   //XMLHttpRequest not supported by the browser
   if(!xmlDoc)
      return false;
   
   xmlDoc.open("GET", name, false);
   xmlDoc.send(null);
   return xmlDoc.responseXML;
}

/*****************************************************************************/

//Find First element of the xmltree
//param : xml file
function GetRootElement(xmlDoc)
{
   return xmlDoc.documentElement;
}

/*****************************************************************************/

//Find Last element of the xmltree
//param : xml file
function GetLastElement(xmlDoc)
{
   element = xmlDoc.root;
   while(element.childNodes.length > 0)
   {
      element = element.lastChild;
   }
   return element;
}

/*****************************************************************************/

//get the next element in the tree
//param1 : current element 
//param2 : fl_done set on 0 (set at 1 if childs already be done)
function NextNode(node,nodetype,fl_done)
{
   if(!node)
      return node;
   var org_node = node;
   //get first child
   if(node.childNodes && node.childNodes.length > 0 && !fl_done)
   {
      node = node.firstChild;
      if(nodetype)
      {
         while(node.nodeType  != nodetype)
         {
            node = node.nextSibling;
            if(node==null) break;
         }

         if(!node)
         {
            node = NextNode(org_node,nodetype,1);
         }
      }
      return node;
   }
   else
   {
      var parent = node.parentNode;
      //no parent any more (eof)
      if(!parent)
      {
         return (parent);
      }
      
      //get the nextSibling child
      if(node != parent.lastChild)
      {
         node = node.nextSibling;
         if(nodetype)
         {
            while(node.nodeType  != nodetype)
            {
               node = node.nextSibling;
               if(node==null) break;
            }
         }
         return node;
      }
      //get next node of parent (childs are always be done)
      else
      {
         return NextElement(parent,1);
      }
   }
}

function NextElement(node,fl_done)
{
   if(!node)
      return node;
   
   //get first child
   if(node.childNodes && node.childNodes.length > 0 && !fl_done)
   {
      return node.firstChild;
   }
   else
   {
      var parent = node.parentNode;
      //no parent any more (eof)
      if(!parent)
      {
         return (parent);
      }
      //get the nextSibling child
      if(node!=parent.lastChild)
      {
         return (node.nextSibling);
      }
      //get next node of parent (childs are always be done)
      else
      {
         return NextElement(parent,1);
      }
   }
}
/*****************************************************************************/

//get the previous element in the tree
//param : curent element
function PrevElement(element)
{
   //EOF
   if(!element || !element.parentNode)
      return NULL;
   parent=element.parentNode;
   if(element != parent.firstChild)
   {
      //get the prev element
      element = element.prevSibling;
      while(element.childNodes.length > 0)
      {
         element = element.lastChild;
      }
      return element;
   }
   else
      return parent;
}

/*****************************************************************************/

//select nodes with a XPath expression
//return a NodeList!!
/*function SelectNodes(xmlDoc,expression)
{
   if(document.all)
      return xmlDoc.documentElement.selectNodes(expression);
   else
      return xmlDoc.evaluate(expression, xmlDoc, null, 0, null);
      
}*/

/*****************************************************************************/
if(typeof(XMLDocument)!="function")
{
    function XMLDocument()
    {
       this._typeName = "XMLDocument";
       //variable for the created DOM Document
       this.DOMDocumnt = null;
       //determine if this is a standards-compliant browser like Mozilla
       if (document.implementation && document.implementation.createDocument) 
       {
          //create the DOM Document the standards way
          this.DOMDocumnt = document.implementation.createDocument("","", null);
       } 
       else 
       if (!window.opera && window.ActiveXObject && document.all) 
       {
          //create the DOM Document the IE way
          this.DOMDocumnt = new ActiveXObject("Microsoft.XMLDOM");
          return this.DOMDocumnt;
       }
       //return the object
    }
}
if ((navigator.product == "Gecko") && !( /Opera/.test(navigator.userAgent))) 
{
   Element.prototype.__defineGetter__("text", function (){ return (new XMLSerializer()).serializeToString(this).replace(/<[^>]+>/g,"").replace(/\&amp;/g, "&").replace(/\&lt;/g, "<").replace(/&gt;/g, ">"); } );
   Document.prototype.__defineGetter__("text", function (){   return (new XMLSerializer()).serializeToString(this).replace(/<[^>]+>/g,"").replace(/\&amp;/g, "&").replace(/\&lt;/g, "<").replace(/&gt;/g, ">"); } );
   XMLDocument.prototype.__defineGetter__("text", function (){  return (new XMLSerializer()).serializeToString(this.DOMDocumnt).replace(/<[^>]+>/g,"").replace(/\&amp;/g, "&").replace(/\&lt;/g, "<").replace(/&gt;/g, ">"); } );

   Element.prototype.__defineGetter__("xml", function (){ return (new XMLSerializer()).serializeToString(this); } );
   Document.prototype.__defineGetter__("xml", function (){   return (new XMLSerializer()).serializeToString(this);  } );
   XMLDocument.prototype.__defineGetter__("xml", function (){  return (new XMLSerializer()).serializeToString(this.DOMDocumnt); } );


   XMLDocument.prototype.loadXML = function(str) 
   {
      this.DOMDocumnt = (new DOMParser()).parseFromString(str, "text/xml");
   }

   XMLDocument.prototype.selectSingleNode = function(sXPath)
   {
      var xPathResult = this.DOMDocumnt.evaluate(sXPath, this.DOMDocumnt,
            this.DOMDocumnt.createNSResolver(this.DOMDocumnt.documentElement), 9, null);
      if (xPathResult.singleNodeValue) 
      {
         return xPathResult.singleNodeValue;
      }

      return (new DOMParser()).parseFromString("<empty/>","text/xml").documentElement;
   }

   Element.prototype.selectSingleNode = function(sXPath)
   {
      var xmlDoc = (new DOMParser()).parseFromString("<root>" + this.xml+ "</root>", 'text/xml');
      var xPathResult = xmlDoc.evaluate(sXPath, xmlDoc,xmlDoc.createNSResolver(xmlDoc.documentElement), 9, null);

      if (xPathResult.singleNodeValue) 
      {
         return xPathResult.singleNodeValue;
      }
      return (new DOMParser()).parseFromString("<empty/>","text/xml").documentElement;
   }

   XMLDocument.prototype.selectNodes = function(sXPath)
   {
      var xPathResult = this.DOMDocumnt.evaluate(sXPath, this.DOMDocumnt,this.DOMDocumnt.createNSResolver(this.DOMDocumnt.documentElement),XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
      var nodeArray = new Array();
      var node;
      if (xPathResult)
      {
         node = xPathResult.iterateNext();
         while(node)
         {
            nodeArray[nodeArray.length] = node;
            node = xPathResult.iterateNext();
         }
      }

      return nodeArray;
   }

   Element.prototype.selectNodes = function(sXPath)
   {
      var xmlDoc = (new DOMParser()).parseFromString(this.xml, 'text/xml');
      var xPathResult = xmlDoc.evaluate(sXPath, xmlDoc,xmlDoc.createNSResolver(xmlDoc.documentElement),XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
      var nodeArray = new Array();
      var node;
      if (xPathResult)
      {
         node = xPathResult.iterateNext()
            var cnt = 0;
         while(node)
         {
            nodeArray[cnt] = node;
            node = xPathResult.iterateNext();
            cnt++;
         } 
         return nodeArray;
      }
      return nodeArray;
   }

   Element.prototype.replaceNode = function(newElement)
   {
      var eParent = this.parentNode;
      eParent.replaceChild(newElement,this);
   }
}

if(/Opera/.test(navigator.userAgent))
{
   //add in the extra parts that were needed
   window.selectSingleNode = function (d,v,c){v+="[1]";var nl=selectNodes(d,v,c);if(nl.length>0)return nl[0];else return null;}
   Document.prototype.selectSingleNode = function(v){return selectSingleNode(this,v,null);}
   Element.prototype.selectSingleNode = function(v){var scope=this.ownerDocument;if(scope.selectSingleNode)return selectSingleNode(scope,v,this);else return null;}

   //fix for Opera's mistaken handling of innerText (entities are preserved)
   String.prototype.removeEntities = function () {
      var oDiv = document.createElement('div'), oStr = this.toString();
      oDiv.innerHTML = '&gt;';
      if( oDiv.innerText != '>' ) {
         //broken innerText, fix it
         oDiv.innerHTML = oStr;
         oStr = '';
         for( var i = 0; oDiv.childNodes[i]; i++ ) {
            oStr += oDiv.childNodes[i].nodeValue;
         }
      }
      delete oDiv;
      return oStr;
   };

   //emulate XPath
   window.selectNodes = function (d,v,c){
      var elName = v.replace(/[^\w].*$/,'');
      elName = d.getElementsByTagName(elName);
      var attrToMatch = v.replace(/^.*@/,'').replace(/\s*=.*$/,'');
      var valToMatch = v.replace(/^[^']*'/,'').replace(/'.*$/,'');
      for(var i=0;elName[i];i++){if(elName[i].getAttribute(attrToMatch)==valToMatch){return [elName[i]];}}
      return [];
   }

   Document.selectNodes = function(v){ return selectNodes(this,v,null); }
   Element.prototype.selectNodes = function(v){ return selectNodes(this.ownerDocument,v,this); }
}



