﻿/// ==========================================================================
/// Clase Xml
/// ==========================================================================
function Xml()
{

  // Variables privadas
  var isExplorer = (typeof window.ActiveXObject != 'undefined');
  var isMozilla  = (typeof document.implementation != "undefined") && (typeof document.implementation.createDocument != "undefined");
  
  this.xmlDocument = null;
  
  ///--------------------------------------------------------------------------
  /// Crea un objeto Documento XML
  ///--------------------------------------------------------------------------
  this.createXmlDocument = function( asFreeThreaded, callbackFunction )
  {
  
    var objXML = null;

    // Soporte nativo
    if ( document.implementation && document.implementation.createDocument )
	  {
			objXML = document.implementation.createDocument("","",null);
	  }
	  // Soporte ActiveX
  	else if ( window.ActiveXObject )
		{
			
			var arrActiveX = null;
			
			if ( asFreeThreaded )
			{
				// Array de todos los DOM posibles, de mas nuevo a mas viejo		
				arrActiveX = ["MSXML4.FreeThreadedDOMDocument", 
											"MSXML3.FreeThreadedDOMDocument",
											"MSXML2.FreeThreadedDOMDocument", 
											"MSXML.FreeThreadedDOMDocument"];
			}
			else
			{
				// Array de todos los DOM posibles, de mas nuevo a mas viejo		
				arrActiveX = ["MSXML4.DOMDocument", 
											"MSXML3.DOMDocument",
											"MSXML2.DOMDocument", 
											"MSXML.DOMDocument",
											"Microsoft.XmlDom"];
			}
			
			var blnFound   = false;

			// Iteramos a traves de cada cadena para determinar cual usar
			for ( var intIndex = 0; (intIndex < arrActiveX.length) && !blnFound; intIndex++ ) 
			{
				try 
				{
					objXML = new ActiveXObject(arrActiveX[intIndex]);
					blnFound = true;
				} 
				catch ( e ) {}
			}
			
      if ( !blnFound )
        throw "MSXML no se ha encontrado en este ordenador.";
		}
      
    // Si hay funcion de callback, de manera asincronica
    if ( callbackFunction != null && callbackFunction != "" )
    {      
		  objXML.async = true;
			objXML.onreadystatechange = callbackFunction;
		}
		// Si no, de manera sincronica
		else
		  objXML.async = false;
		  
    this.xmlDocument = objXML;		  
  }
  
  ///--------------------------------------------------------------------------
  /// Carga un archivo XML e indica que funcion llamar tras la carga
  ///--------------------------------------------------------------------------
  this.loadXmlFile = function( strXmlFile, asFreeThreaded, callbackFunction )
  {

    this.createXmlDocument(asFreeThreaded,callbackFunction);

    // En Mozilla hay que llamar directamente a la funcion, pues
    // no soporta modo asincronico. Si es modo sincronico tambien le
    // afectara esta medida
		if ( isMozilla || callbackFunction == null || callbackFunction == "" )
		{
      this.xmlDocument.readyState = 4;
		  this.xmlDocument.addEventListener("load",callbackFunction,false);
		}

		this.xmlDocument.load(strXmlFile);
		
		return this.xmlDocument;
  }
  
  ///--------------------------------------------------------------------------
  /// Carga una cadena XML e indica que funcion llamar tras la carga
  ///--------------------------------------------------------------------------
  this.loadXml = function( strXml, asFreeThreaded, callbackFunction )
  {

    this.createXmlDocument(asFreeThreaded,callbackFunction);

		// Explorer
		if ( isExplorer ) 
			this.xmlDocument.loadXML(strXml);
		// Mozilla
		else
		{
			var objDOMParser = new DOMParser();
			this.xmlDocument = objDOMParser.parseFromString(strXml,"text/xml");
              // En Mozilla hay que llamar directamente a la funcion, pues
              // no soporta modo asincronico
              if ( callbackFunction != null && callbackFunction != "" )
              {
                this.xmlDocument.readyState = 4;
	  		        callbackFunction();
	  	        }
		}

		return this.xmlDocument;
  }
  
  ///--------------------------------------------------------------------------
  /// Informa de si el objeto ya ha recibido todos los datos de manera segura
  ///--------------------------------------------------------------------------
  this.isReady = function()
  {

    return (this.xmlDocument.readyState == 4);
  }
  
  ///--------------------------------------------------------------------------
  /// Transforma este objeto Xml con el objeto Xsl indicado, y deja el resultado
  /// en el objeto informado
  ///--------------------------------------------------------------------------
  this.transform = function( objXsl, objDest )
  {

	  var strHtml = "";

	  // Explorer
	  if ( isExplorer )
	  {
		  strHtml = this.xmlDocument.transformNode(objXsl.xmlDocument);
		  objDest.innerHTML = strHtml;
	  }
	  // Mozilla
	  else
	  {
		  var objProcessor = new XSLTProcessor();
		  objProcessor.importStylesheet(objXsl.xmlDocument);
		  var ownerDocument = document.implementation.createDocument("","",null);
		  var objHtmlFragment = objProcessor.transformToFragment(this.xmlDocument,ownerDocument);
		  objDest.innerHTML = "";
		  objDest.appendChild(objHtmlFragment);
	  }
  }
  
  ///--------------------------------------------------------------------------
  /// Transforma este objeto Xml con el objeto Xsl indicado, y deja el resultado
  /// en el objeto informado, realizando todo a traves de un procesador XSLT
  /// al cual se le pueden pasar parametros para la XSL
  ///--------------------------------------------------------------------------
  this.transformWithProcessor = function( objXsl, objDest, parameters )
  {
  
	  // Explorer
	  if ( isExplorer )
	  {

	    var objXSLT = null;

			// Array de todos los DOM posibles, de mas nuevo a mas viejo		
			var arrActiveX = ["MSXML4.XSLTemplate", 
												"MSXML3.XSLTemplate",
												"MSXML2.XSLTemplate", 
												"MSXML.XSLTemplate"];
	                      
			var blnFound   = false;

			// Iteramos a traves de cada cadena para determinar cual usar
			for ( var intIndex = 0; (intIndex < arrActiveX.length) && !blnFound; intIndex++ ) 
			{
				try 
				{
					objXSLT = new ActiveXObject(arrActiveX[intIndex]);
					blnFound = true;
				} 
				catch ( e ) {}
			}

			if ( !blnFound )
				throw "MSXML no se ha encontrado en este ordenador.";

			objXSLT.stylesheet  = objXsl.xmlDocument;
			var objProcessor    = objXSLT.createProcessor();
			objProcessor.input  = this.xmlDocument;
		
			if ((parameters != null) && (parameters.length > 0))
				for ( var intIndex = 0; intIndex < parameters.length; intIndex++ )
					objProcessor.addParameter(parameters[intIndex][0],parameters[intIndex][1]);
				
			objProcessor.transform();
			objDest.innerHTML = objProcessor.output;
	  }
	  // Mozilla
	  else
	  {
		  var objProcessor = new XSLTProcessor();
		  objProcessor.importStylesheet(objXsl.xmlDocument);
		  var ownerDocument = document.implementation.createDocument("","",null);

			if ((parameters != null) && (parameters.length > 0))
				for ( var intIndex = 0; intIndex < parameters.length; intIndex++ )
					objProcessor.setParameter(null,parameters[intIndex][0],parameters[intIndex][1]);
		  
		  var objHtmlFragment = objProcessor.transformToFragment(this.xmlDocument,ownerDocument);
		  objDest.innerHTML = "";
		  objDest.appendChild(objHtmlFragment);
		}
  }
  
  //-----------------------------------------------------------------
  //-----------------------------------------------------------------
  this.selectSingleNodeText = function (xmlDoc, elementPath) 
  {
        if(window.ActiveXObject) 
        {
            return xmlDoc.selectSingleNode(elementPath).text; 
        }
        else
        {

        var xpe = new XPathEvaluator(); 
         
        var nsResolver = xpe.createNSResolver( xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement);

        var results = xpe.evaluate(elementPath,xmlDoc,nsResolver,XPathResult.ANY_TYPE, null).iterateNext().textContent;
        
        return results; 
        }
  }
  
   //-----------------------------------------------------------------
  //-----------------------------------------------------------------
  this.selectNodes = function (xmlDoc, elementPath) 
  {
        if(window.ActiveXObject) 
        {
            return xmlDoc.selectNodes(elementPath); 
        }
        else
        {

            var xpe = new XPathEvaluator(); 
             
            var nsResolver = xpe.createNSResolver( xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement);

            var results = xpe.evaluate(elementPath,xmlDoc,nsResolver,XPathResult.ANY_TYPE, null);
            var aNodes = new Array();
            
            
            if (results != null)
            {
                var oElement = results.iterateNext();
                while(oElement) 
                {
                    aNodes.push(oElement);
                    oElement = results.iterateNext();
                }
            }
            return aNodes;
        }
  }

}




