function clsXMLLib(libraryWindow)
{
    var libraries = libraryWindow;
    
    if(libraries == null)
    {
        libraries = top;
    }

    using("helperLib", libraries);
    this.serverTransformXML         = serverTransformXML;
    this.serverTransformXMLAsync    = serverTransformXMLAsync;
	this.transformXML               = transformXML;
	this.getNodeText                = getNodeText;
	this.getNodeXML                 = getNodeXML;
	this.setNodeText                = setNodeText;
	this.setNodeXML                 = setNodeXML;
	
	this.getNodeNextSibling         = getNodeNextSibling;
	this.getNodeFirstChild          = getNodeFirstChild;
	this.getNodePreviousSibling     = getNodePreviousSibling;

	this.loadXml = _loadXml;
	
	this.loadXSL                    = _loadSyncXSL;
	
	var objXMLDocTemplate ,objXSLDocTemplate 
	var m_sXSLTemplateProgId = "Msxml2.XSLTemplate.6.0"
	

    prepareXmlDomParser()

	this.objXMLDocTemplate = objXMLDocTemplate;
	this.objXSLDocTemplate = objXSLDocTemplate;

	function _loadXml(path, tagVariant, cb) {
	    var cache;
	    try { cache = top.context.cache } catch (e) { }


	    var xmlDoc = cache[tagVariant];
	    if (xmlDoc != null) return cb(xmlDoc, tagVariant);

	    xmlDoc = wflib.XMLLib.objXMLDocTemplate.cloneNode(true);
	    xmlDoc.async = true;
	    if (navigator.userAgent.indexOf("MSIE") < 0) {
	        xmlDoc.addEventListener("load", _ffcb, false);
	    } else {
	        xmlDoc.onreadystatechange = _cb
	    }
	    xmlDoc.load(path);

	    if (tagVariant != null) {
	        try {
	            cache[tagVariant] = xmlDoc;
	        } catch (e) { }
	    }

	    function _ffcb() {
            
	        try { cb(xmlDoc, tagVariant) } catch (e) { }
	    }
	    
        function _cb() {
	        if (xmlDoc.readyState != 4) return;
            
	        try { cb(xmlDoc, tagVariant) } catch (e) { }
	    }
	}
    

    function prepareXmlDomParser()
    {
        var objXmlDom;
        
        if(navigator.userAgent.indexOf("MSIE") < 0) 
        {
            objXmlDom = document.implementation.createDocument("","", null);
            
            objXSLDocTemplate = objXmlDom;
        }
        else //IE
        {
            //var xmlVersions         = ["MSXML2.DomDocument.6.0",                "MSXML2.DomDocument.3.0",               "MSXML2.DomDocument.4.0",               "MSXML2.DomDocument.5.0",               "MSXML2.DomDocument",               "Microsoft.XMLDom"]
            var xmlVersions         = ["MSXML2.DomDocument.6.0"]
            var xslVersions         = ["Msxml2.FreeThreadedDOMDocument.6.0",    "Msxml2.FreeThreadedDOMDocument.3.0",   "Msxml2.FreeThreadedDOMDocument.4.0",   "Msxml2.FreeThreadedDOMDocument.5.0",   "Msxml2.FreeThreadedDOMDocument",   "Microsoft.FreeThreadedDOMDocument"]
            var xslTemplateVersions = ["MSXML2.XSLTemplate.6.0",                "MSXML2.XSLTemplate.3.0",               "MSXML2.XSLTemplate.4.0",               "MSXML2.XSLTemplate.5.0",               "MSXML2.XSLTemplate",               "Microsoft.XSLTemplate"]
            for(var i = 0; i < xmlVersions.length; i++)
            {
                try
                {
                    objXmlDom            = new ActiveXObject(xmlVersions[i]);
                    objXSLDocTemplate    = new ActiveXObject(xslVersions[i])
                    m_sXSLTemplateProgId = xslTemplateVersions[i]
                    break;
                }
                catch(e){}
            }
        }
        
        objXMLDocTemplate = objXmlDom;
    }

	function setNodeText(vXML,sElementName,sValue)
	{
		try{
		var objXML 
		if (typeof(vXML)=="string")
		{
			objXML = objXMLDocTemplate.cloneNode(true)
			objXML.loadXML (vXML)
		}
		else
			objXML= vXML;	
				
		var objElement = objXML.selectSingleNode(sElementName)
		if(objElement==null)
			objElement = objXML.appendChild(objXML.ownerDocument.createElement(sElementName))
		objElement.text = sValue
		if (typeof(vXML)=="string")
			return objXML.xml
		else
			return objXML	
		}catch(e){}
	}
	
	function setNodeXML(vXML, sElementName, ValueXml, append)
	{
		try
		{
		    var objXML 
		    if (typeof(vXML) == "string")
		    {
			    objXML = objXMLDocTemplate.cloneNode(true);
			    objXML.loadXML(vXML);
		    }
		    else
		    {
			    objXML = vXML;	
            }
				
		    var xmlToInsert = objXML.ownerDocument.cloneNode(true)
		    xmlToInsert.loadXML("<root>" + ValueXml + "</root>")
		    
		    var element = objXML.selectSingleNode(sElementName)
		    
		    if(element != null)
		    {
		        //if the mode is not append this has to be treated like a replace operation.
		        if(append != true)
		        {
		            //delete all children of the exisiting element
		            var elementChildren = element.childNodes;
		            
		            for(var i = 0;i < elementChildren.length; i++)
		            {
		                element.removeChild(elementChildren[i])
		            }
                }
		    }
		    else
		    {
		        element = objXML.appendChild(objXML.ownerDocument.createElement(sElementName))
		    }
		    
		    element.appendChild(xmlToInsert.selectSingleNode("/root").childNodes[0].cloneNode(true))
		
		    //if a string has been passed then return a string.    
		    if (typeof(vXML) == "string")
		    {
			    return objXML.xml
            }
		    else
		    {
			    return objXML	
            }
		}
		catch(e){}
	}
	
	function _loadSyncXSL(sPath,sCacheName,bContent)
	{
		var objXSL 
		try{objXSL = libraries.context.cache[sCacheName]}catch(e){}
		
		
		if(objXSL == null)
		{
		    if (!(navigator.userAgent.indexOf("MSIE") < 0)) 
		    {
			    objXSL = objXSLDocTemplate.cloneNode(true)
			    objXSL.async = false
			    try{
			    objXSL.setProperty("AllowXsltScript", true);
			    objXSL.setProperty("AllowDocumentFunction", true);
			    }catch(e){}
            }
            else
            {
			    objXSL = objXMLDocTemplate.cloneNode(true)
			    objXSL.async = false
            }
            
            if(bContent == true || sPath.length > 100)
            {
	            objXSL.loadXML(sPath);
            }
            else
            {
	            objXSL.load(sPath);
            }
            
		}
		


	    if(sCacheName != null)	
	    {
	        
		    libraries.context.cache[sCacheName] = objXSL
        }
		return objXSL
	}

    function getNodeFirstChild(xmlNode)
    {
        try {
            var n = xmlNode.childNodes[0];
            while (n != null && n.nodeType == 3) {
                n = n.nextSibling;
            }
            return n;
        }
        catch (e) { return null }
    }

	function getNodeNextSibling(xmlNode)
	{
	    try
	    {
	        var n = xmlNode.nextSibling;
	        while(n != null && n.nodeType == 3)
	        {
	            n = n.nextSibling;
	        }
            return n;
        }
        catch(e){return null}
	}

	function getNodePreviousSibling(xmlNode)
	{
	    try
	    {
            var n = xmlNode.previousSibling;
            while(n != null && n.nodeType == 3)
            {
                n = n.previousSibling;
            }
            return n;
        }
        catch(e){return null}
	}
	
	function getNodeText(vXML,sNodeName)
	{
		try
		{
		    var objXML,objTemp 
		    if (typeof(vXML)=="string")
		    {
			    objXML = objXMLDocTemplate.cloneNode(true)
			    objXML.loadXML (vXML)
		    }
		    else
		    {
    			objXML= vXML;
		    }
		
            
		    objTemp = objXML.selectSingleNode(sNodeName)
		    if (objTemp == null)
		    {
    			return "";
		    }
		    else
		    {
		        if(objTemp.text == undefined)
		        {
		            return objTemp.value;
		        }
			    return objTemp.text;
    		}
		}
		catch(e)
		{
		    return "";
        }
	}

	function getNodeXML(vXML,sNodeName)
	{
		try{
		var objXML,objTemp 
		if (typeof(vXML)=="string")
		{
			objXML = objXMLDocTemplate.cloneNode(true)
			objXML.loadXML (vXML)
		}
		else
			objXML= vXML;
		
		objTemp = objXML.selectSingleNode(sNodeName)
		if (objTemp == null)
		{
			return "";
		}
		else
		{
			return objTemp.xml
		}
		}catch(e){}
	}

    function serverTransformXMLAsync(functionPointer,xmlData,bDesignerTransform,sDesignerTransformXSLFile)
    {
        var result
        if(bDesignerTransform == true)
        {
            xmlData = "<![CDATA[<document><record><path>" + libraries.helperLib.wsfMapPath("$application/participant/xml/tree.xml") + "</path><xsl>" + sDesignerTransformXSLFile + "</xsl></record></document>]]>";
        }

        result = libraries.helperLib.processSoapRequestAsync(top,requestComplete, libraries.helperLib.wsfMapPath("/webservices/wf.object/utilityprocessor.asmx") ,"wf.object","XmlTransform", "sXML", xmlData)      
        
        function requestComplete(result)
        {
            var sReturnValue = "";
            if(result != null)
            {
                sReturnValue = libraries.XMLLib.getNodeText(result,"//XmlTransformResult")
            }
            
            try{functionPointer(sReturnValue)}catch(e){}
        }
    }
    
    function serverTransformXML(xmlData,bDesignerTransform,sDesignerTransformXSLFile)
    {
        var result;
        
        if(bDesignerTransform == true)
        {
            xmlData = "<![CDATA[<document><record><path>" + libraries.helperLib.wsfMapPath("$applicationid/participant/xml/tree.xml") + "</path><xsl>" + sDesignerTransformXSLFile + "</xsl></record></document>]]>";
        }
                    
        result = libraries.helperLib.processSoapRequest(top, libraries.helperLib.wsfMapPath("/webservices/wf.object/utilityprocessor.asmx"),"wf.object","XmlTransform", "sXML", xmlData);
        
        if(result != null)
        {
            return libraries.XMLLib.getNodeText(result,"//XmlTransformResult");
        }
        else
        {
            return "";
        }
    }

    function getXSLTProcessor(xsl)
    {
        var objXSLT, processor;
        if(navigator.userAgent.indexOf("MSIE") < 0) 
        {
            processor = new XSLTProcessor();
            processor.importStylesheet(xsl);
            
        }
        else
        {
            try
		    {
		        objXSLT = new ActiveXObject(m_sXSLTemplateProgId);
		        objXSLT.stylesheet = xsl;
		        processor = objXSLT.createProcessor()
		    }
		    catch(e)
		    {
		        alert("error in xmllib.getXSLTProcessor:" +  e.description);
            }
        }
        return processor;
    }

	function transformXML(xmlData,sXSLFileName)
	{
		var objXSLT, objXSL, objXML, objProc, sOutput


		//first load the xsl
		if (typeof(sXSLFileName)=="string")
		{
		    objXSL = _loadSyncXSL(sXSLFileName, null, false);
		}
		else
		{
			objXSL = sXSLFileName	
        }
        
        
        //load the xml to be transformed
        objXML = objXMLDocTemplate.cloneNode(true)
		objXML.async = false;
		objXML.loadXML(xmlData)
        
        
        //create a processor
        objProc = getXSLTProcessor(objXSL, objXML)
		
		//add parameters and transform
		if(navigator.userAgent.indexOf("MSIE") < 0) 
		{
    		if (arguments.length > 2)
    		{
			    for(var i=2;i<arguments.length;i++)
			    {
				    objProc.setParameter(null, "param" + (i-1),arguments[i]);
			    }
			}
		    var newDocument = objProc.transformToDocument(objXML);
		    
            sOutput = newDocument.xml;
            
            if(objXSL.xml.indexOf('method="text"') > 0 && newDocument.documentElement.textContent)
            {
                //this is for safari
                sOutput = newDocument.documentElement.textContent;
            }
            
            if(sOutput.indexOf("transformiix:result") >= 0)
            {
                var transformiix = getNodeXML(sOutput, "//transformiix:result/*[name() != 'transformiix:result']");
                
                if(transformiix.length == 0)
                {
                    transformiix = getNodeText(sOutput, "//transformiix:result");
                }
                sOutput = transformiix;
            }
		}
		else
		{
		    objProc.input = objXML
    		if (arguments.length > 2)
    		{
			    for(var i=2;i<arguments.length;i++)
			    {
				    objProc.addParameter("param" + (i-1),arguments[i]);
			    }
			}
		    objProc.transform();		
		    sOutput = objProc.output
		}
		
		return(sOutput);
	}



 
}
