jQuery.transform = 
{
	queryStack: [],
	
	abort: function ( )
	{
		jQuery.each ( jQuery.transform.queryStack, function ( i, val )
		{
			val.abort ( );
		} );
	},
	
	execute: function ( xml, xsl, callback, onBeforeStart )
	{
		/**
		 * Check Params:
		 */
			if ( typeof onBeforeStart == 'function' ) onBeforeStart ( );
		 
			switch ( typeof xml )
			{
				case 'string':
					xml = { doc: null, url: xml, params: {}, method: 'get' };
					break;
					
				case 'object':
					xml = jQuery.extend ( { doc: null, url: '', params: {}, method: 'get' }, xml );				
					break;
			}
		 
			switch ( typeof xsl )
			{
				case 'string':
					xsl = { doc: null, url: xsl, params: {}, method: 'get' };
					break;
					
				case 'object':
					xsl = jQuery.extend ( { doc: null, url: '', params: {}, method: 'get' }, xsl );
					break;
			}
		
		/**
		 * fill xml:
		 */
			if ( xml.doc == null )
			{
				jQuery.transform.queryStack.push ( ( xml.method == 'get' ? $.get : $.post ) ( xml.url, xml.params, function ( response, status ) 
				{
					xml.doc = response;
					xml.status = status;
						
					if ( status == 'success' ) jQuery.transform.execute ( xml, xsl, callback );
					else callback ( null, 'xml error', xml, xsl );
				
				}, 'xml' ) );
			}			
	
		/**
		 * fill xsl:
		 */
			else if ( xsl.doc == null )
			{
				jQuery.transform.queryStack.push ( ( xsl.method == 'get' ? $.get : $.post ) ( xsl.url, xsl.params, function ( response, status ) 
				{
					xsl.doc = response;
					xsl.status = status;
						
					if ( status == 'success' ) jQuery.transform.execute ( xml, xsl, callback );
					else callback ( null, 'xsl error', xml, xsl );
				
				}, 'xml' ) );
			}
	
		/**
		 * transform:
		 */
			else
			{
				var resultString = '';
			
				if ( window.ActiveXObject )
				{
					resultString = xml.doc.transformNode ( xsl.doc );				
				}
				else if ( document.implementation && document.implementation.createDocument )
				{
					xsltProcessor = new XSLTProcessor ( );
					xsltProcessor.importStylesheet ( xsl.doc );
		
					var tmp = document.createElement ( 'DIV' );
						tmp.appendChild ( xsltProcessor.transformToFragment ( xml.doc, document ) );	
				
					resultString = tmp.innerHTML;
				}
				
				callback ( resultString, 'success', xml, xsl );
			}
			
		/**
		 * jQuery - plugin requirement
		 */
			return this;
	}
};

jQuery.fn.xslt = function ( xml, xsl, onComplete, onBeforeStart )
{
	var self = this;

	return this.each ( function ( )
	{
		jQuery.transform.execute ( xml, xsl, function ( resultString, status )
		{
			if ( status == 'success' )
			{
				$(self).fadeOut(function()
				{					
					$(self).html ( resultString );
					$(self).fadeIn ( 'slow', onComplete );					
				})
			}	
				
		}, onBeforeStart );
	} );
};