﻿//===================================================================
// XSLT Transformation class.
//===================================================================
function XSLTransform()
{
	var THIS = this;
	
	//==================================================
	// Dispose.
	//==================================================
	this.Dispose = function Dispose()
	{
		for(Element in THIS)
		{
			if (typeof(THIS[Element]) != 'function')
			{
				THIS[Element] = null;
				delete THIS[Element];
			}
		}
		
		delete THIS;
		return;
	}
	
	//===============================================================
	// Transform the XML.
	//===============================================================
	this.Transform = function Transform(Container, XSLT, XML, CallBack, AllowContentUpdate)
	{
		try
		{
			// Check the XML.
			if (XML == '')
			{
				alert('Transform(): The XML document is empty.');
				return;
			}

			var strReturnValue = '';
			var intPath = XSLT.toString().indexOf('.xslt') + 5;
			var strPath = XSLT.toString().substring(0, intPath);
			var aXSLT = new Array();
			var strXSLT = '';
			var objXSLTDoc = null;
			
			if (XSLT.toString().indexOf('.xslt?') != -1)
				THIS.aParameters = XSLT.toString().substring((XSLT.toString().indexOf('.xslt') + 6)).split('&');

			THIS.Container = Container;
			THIS.CallBack = CallBack;
			THIS.AllowContentUpdate = ((AllowContentUpdate == undefined) ? true : AllowContentUpdate);
			
			// Check if the browser.
			if (window.ActiveXObject)
			{
				// Internet explorer.
				var objXSLT = new ActiveXObject('Msxml2.XSLTemplate.3.0');
				var objXSLDoc = new ActiveXObject('Msxml2.FreeThreadedDOMDocument.3.0');
				var objXSLProcessor;
				
				objXSLDoc.async = false;
				objXSLDoc.load('http://' + window.location.hostname + strPath);
				
				if (objXSLDoc.parseError.errorCode != 0)
				{
					var objError = objXSLDoc.parseError;
					alert('An error has occured whilst parsing the XLST document: -\n\n ' + objError.reason + '\n ' + 'http://' + window.location.hostname + strPath);
				}
				else
				{
					objXSLT.stylesheet = objXSLDoc;
					var objXMLDoc = new ActiveXObject('Msxml2.DOMDocument.3.0');
					objXMLDoc.async = false;
					
					//objXMLDoc.loadXML(XML.replace('&', '&amp;'));
					objXMLDoc.loadXML(XML.replace(/&/gi, '&amp;'));
					
					if (objXMLDoc.parseError.errorCode != 0)
					{
						var objError = objXMLDoc.parseError;
						alert('An error has occured whilst parsing the XML document: -\n\n' + objError.reason);
					}
					else
					{
						objXSLProcessor = objXSLT.createProcessor();
						objXSLProcessor.input = objXMLDoc;
						
						if (THIS.aParameters != undefined)
						{
							for (var intCounter = 0; intCounter < THIS.aParameters.length; intCounter++)
							{
								var aParameter = THIS.aParameters[intCounter].toString().split('=');
								objXSLProcessor.addParameter(aParameter[0], unescape(aParameter[1]));
							}
						}

						objXSLProcessor.transform();
						
						// Check if the container is still available.
						if (THIS.Container)
						{
							if (THIS.AllowContentUpdate)
								THIS.Container.innerHTML = objXSLProcessor.output;
						}
						
						// Check if the callback is still available.
						if (THIS.CallBack)
							THIS.CallBack();
					}
				}
				
				// Dispose of objects.
				THIS.Dispose();
			}
			else
			{
				// Firefox, Safari etc...
				if (document.implementation && document.implementation.createDocument)
				{
					var blnBuildXSLT = (window.navigator.userAgent.indexOf('Safari') > -1);
					var objParser = new DOMParser();
					THIS.objXMLDoc = document.implementation.createDocument('', '', null);
					THIS.objXMLDoc.async = false;
					THIS.objXMLDoc = objParser.parseFromString(XML, "text/xml");
					
					blnBuildXSLT = true;
					
					// Check if the XSLT has to be constructed using the server.
					if (blnBuildXSLT)
					{	
						var objXSLTProcessor = new XSLTProcessor();
						THIS.objXSLTProcessor = document.implementation.createDocument('', '', null);

						var objXMLHTTP = new XMLHttpRequest();
						objXMLHTTP.open('GET', 'http://' + window.location.hostname + '/Xslt/ReadXSLT.aspx?xslt=' + strPath, false);
						objXMLHTTP.send(null);
						objXSLTDoc = objXMLHTTP.responseXML.documentElement;
						objXSLTProcessor.importStylesheet(objXSLTDoc);

						if (THIS.aParameters != undefined)
						{
							for (var intCounter = 0; intCounter < THIS.aParameters.length; intCounter++)
							{
								var aParameter = THIS.aParameters[intCounter].toString().split('=');
								objXSLTProcessor.setParameter(null, aParameter[0], unescape(aParameter[1]));
							}
						}
						
						// Check if the container is still available.
						if (THIS.Container)
						{
							if (THIS.AllowContentUpdate)
							{
								THIS.Container.innerHTML = '';
								
								try
								{
									THIS.Container.appendChild(objXSLTProcessor.transformToFragment(THIS.objXMLDoc, document));
								}
								catch(e)
								{
									THIS.Container.innerHTML = '<strong>Transformation Error</strong><br/>' + e.message;
								}
							}
						}
						
						// Check if the callback is still available.
						if (THIS.CallBack)
							THIS.CallBack();

						// Dispose of objects.
						THIS.Dispose();
					}
					else
					{
						THIS.objXSLT = document.implementation.createDocument('', '', null);
						THIS.objXSLT.addEventListener("load", THIS.objXSLT_OnLoad, false);
						THIS.objXSLT.load('http://' + window.location.hostname + strPath);
					}
				}
			}
		}
		catch(e)
		{
			try
			{
				// Check if the container is still available.
				if (THIS.Container)
				{
					THIS.Container.innerHTML = '<p>An error has occured whilst transforming the document \'' + XSLT + '\': -<p/><br/>'
												+ '<p>Message: ' + e.message + '</p><br/>'
												+ '<p>' + THIS.ToString(objXSLTDoc) + '</p>';
				}

				THIS.CallBack();
			}
			catch(e)
			{
				alert('Transform(): The following error has occured:\n\n' + e.message);
			}
		}
		return;
	}
	
	//===============================================================
	// XSLT document onload event handler.
	//===============================================================
	this.objXSLT_OnLoad = function objXSLT_OnLoad()
	{
		try
		{
			var objXSLTProcessor = new XSLTProcessor();
			objXSLTProcessor.importStylesheet(THIS.objXSLT);

			if (THIS.aParameters != undefined)
			{
				for (var intCounter = 0; intCounter < THIS.aParameters.length; intCounter++)
				{
					var aParameter = THIS.aParameters[intCounter].toString().split('=');
					objXSLTProcessor.setParameter(null, aParameter[0], unescape(aParameter[1]));
				}
			}
			
			// Check if the container is still available.
			if (THIS.Container)
			{
				if (THIS.AllowContentUpdate)
				{
					THIS.Container.innerHTML = '';
					THIS.Container.appendChild(objXSLTProcessor.transformToFragment(THIS.objXMLDoc, document));
				}
			}
			
			// Check if the callback is still available.
			if (THIS.CallBack)
				THIS.CallBack();
		}
		catch(e)
		{
			//alert('An error has occured whilst transforming the document: -\n\n' + e.message);
		}

		// Dispose of objects.
		THIS.Dispose();
		return;
	}
	
	//==============================================
	// Create the XML DOM document.
	//==============================================
	this.CreateDOMDocument = function CreateDOMDocument(XML)
	{
		// IE.
		if (window.ActiveXObject)
		{
			var objXMLDoc = new ActiveXObject('Microsoft.XMLDOM');
		}
		else
		{
			//Firefox, Mozilla, Opera, etc.
			var objXMLDoc = document.implementation.createDocument('', '',null);
		}
		
		objXMLDoc.async = false;
		
		// Check the browser.
		if (window.ActiveXObject)
		{
			objXMLDoc.loadXML(XML);
		}
		else
		{
			objParser = new DOMParser();
			objXMLDoc = objParser.parseFromString(XML, "text/xml");
		}
		return objXMLDoc;
	}

	//==========================================
	// Return a String representation of the given document
	//==========================================
	this.ToString = function ToString(docXML)
	{
		if (docXML == null)
			return 'The XML document is empty.';

		if (docXML.xml)
			return docXML.xml;
		else
		{
			try
			{
				return new XMLSerializer().serializeToString(docXML);
			}
			catch (exc) { return 'Unable to get XML' }
		}
	}
	
	return;
}
