function TransformXMLIntoElement(XMLPath, XPath, XSLPath, XSLParams, Element){
	Element.innerHTML += transformxml(XMLPath, XPath, XSLPath, XSLParams);
}

// An XPath Evaluator for Firefox
// From http://kb.mozillazine.org/XPath :
// Evaluate an XPath expression aExpression against a given DOM node
// or Document object (aNode), returning the results as an array
// thanks wanderingstan at morethanwarm dot mail dot com for the
// initial work.
function evaluateXPath(aNode, aExpr) {
  var xpe = new XPathEvaluator();
  var nsResolver = xpe.createNSResolver(aNode.ownerDocument == null ?
    aNode.documentElement : aNode.ownerDocument.documentElement);
  var result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null);
  var found = [];
  var res;
  while (res = result.iterateNext())
    found.push(res);
  return found;
}

//transformxml (delegates to transformxml_ff or transformxml_ie, based on
//available objects):
//	Transforms the XML at XMLPath with the XSL script at XSLPath, selecting
//	a SINGLE node with XPath and using parameters XSLParams.
//	(May very well be capable of operating on multiple nodes; I haven't
//	worked that in yet.)
//	Returns a string, because the IE variant uses the XMLDOM, whose
//	transform method returns a string.
function transformxml(XMLPath, XPath, XSLPath, XSLParams){
	var retVal;
	
	//funcAddParam:  A conditionally-defined function.  (Defined in the _ff
	//and _ie branches.)
	//Pre:	arg1 is the name of a parameter within the XSLT script, or
	//	blank; blank implies a no-op.
	//	If working with an XSLTProcessor, the object 'processor' must
	//	be defined as an XSLTProcessor.
	//	If working with an ActiveX XMLDOM, the object 'xsl' must be
	//	defined as an XMLDOM.
	//Post:	Specifies a parameter-value pair to an XSL-Transform script.
	//	Does this by modifying DOM with ActiveX, or calling the
	//	setParameter method with an XSLTProcessor.
	var funcAddParam;
	
	if(document.implementation && document.implementation.createDocument && typeof(XSLTProcessor) != 'undefined'){
		retVal = transformxml_ff(XMLPath, XPath, XSLPath, XSLParams);
	} else if(typeof ActiveXObject != 'undefined'){
		retVal = transformxml_ie(XMLPath, XPath, XSLPath, XSLParams);
	} else {
		retVal = "<span class='error'>Sorry, but your browser does not support a scripting component that this page requires (XSL Transformations).  To see this page as intended, please use either Internet Explorer 5.5+ or Firefox 1.0+.<br/>Internet Explorer is included with Windows installations.<br/>Firefox can be downloaded for free here:<br/><a href='http://www.getfirefox.com/'><img src='../images/getfirefox_88x31.png' alt='Get Firefox' style='border:none;' /></a></span>";
	}
	
	return retVal;
}

function transformxml_ff(XMLPath, XPath, XSLPath, XSLParams){
	var retVal = "";
	var bContinueTransform = true;
	XPath = (XPath=="") ? "/" : XPath;	//Ensure the XPath goes to a node
	
	//Load data
	var dataXML = document.implementation.createDocument("", "", null);
	dataXML.async=false;
	bContinueTransform = bContinueTransform && dataXML.load(XMLPath);
	if(!bContinueTransform){
		retval += "<p>Error in file " + XMLPath + "</p>";//:  " + xml.parseError.errorCode + "<br/>" + xml.parseError.reason + "</p>";
	}

	//Load stylesheet
	var dataXSL = document.implementation.createDocument("", "", null);
	dataXSL.async=false;
	bContinueTransform = true;	//Temporary, for error-handling purposes; delete line when error handler is found for Firefox.
	bContinueTransform = bContinueTransform && dataXSL.load(XSLPath);
	if(!bContinueTransform){
		retval += "<p>Error in file " + XSLPath + "</p>";//:  " + xml.parseError.errorCode + "<br/>" + xml.parseError.reason + "</p>";
	}

	var processor = new XSLTProcessor();
	
	//Define parameter-setter
	var funcAddParam = function(param, val){
		if(param != ""){
			processor.setParameter(null, param, val);
		}
	}
	
	if(bContinueTransform){
		processor.importStylesheet(dataXSL);
		
		//Transform parameters
		var aryParams = XSLParams.split("~");
		var aryPar, xslp;
		for(var i=0; i<aryParams.length; i++){
			aryPar = aryParams[i].split("=");
			
			funcAddParam(aryPar[0], aryPar[1]);
		}
		
		//Process
		//This renders the XML in a string, with no extraneous namespace declarations
		var ownerDocument = processor.transformToDocument(evaluateXPath(dataXML,XPath)[0]);
		var serializer = new XMLSerializer();
		retVal += serializer.serializeToString(ownerDocument);
	}
	return retVal;
}

function transformxml_ie(XMLPath, XPath, XSLPath, XSLParams){
	var retval="";
	var bContinueTransform = true;
	XPath = (XPath=="") ? "/" : XPath;	//Ensure the XPath goes to a node
	
	//Load data
	var xml = new ActiveXObject("Microsoft.XMLDOM");
	xml.async = false;
	bContinueTransform = bContinueTransform && xml.load(XMLPath);
	if(xml.parseError.errorCode != 0){
		retval += "<p>Error in file " + XMLPath + ":  " + xml.parseError.errorCode + "<br/>" + xml.parseError.reason + "</p>";
	}

	//Load stylesheet
	var xsl = new ActiveXObject("Microsoft.XMLDOM");
	xsl.async = false;
	bContinueTransform = bContinueTransform && xsl.load(XSLPath);
	if(xsl.parseError.errorCode != 0){
		retval += "<p>Error in file " + XSLPath + ":  " + xsl.parseError.errorCode + "<br/>" + xsl.parseError.reason + "</p>";
	}
	
	//Define parameter-setter
	var funcAddParam = function(param, val){
		var xslp;
		if(param != ""){
			xslp = xsl.selectSingleNode("//xsl:param[@name='" + TrimString(aryPar[0]) + "']");
			if(xslp){
				xslp.text = TrimString(aryPar[1]);
			} else {
				retval += "<p>Warning:  There is no parameter '" + aryPar[0] + "' in " + XSLPath + ".</p>"
			}
		}
	}
	
	if(bContinueTransform){
		//Transform parameters
		var aryParams = XSLParams.split("~");
		var aryPar, xslp;
		for(var i=0; i<aryParams.length; i++){
			aryPar = aryParams[i].split("=");
			
			funcAddParam(aryPar[0], aryPar[1]);
		}
		
		//Process
		retval += xml.selectSingleNode(XPath).transformNode(xsl);
	}
	return retval;
}


