Index: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/TransformingReceptionist.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/TransformingReceptionist.java	(revision 33631)
+++ main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/TransformingReceptionist.java	(revision 33632)
@@ -49,6 +49,6 @@
 public class TransformingReceptionist extends Receptionist
 {
-	protected static final int CONFIG_PASS = 1;
-	protected static final int TEXT_PASS = 2;
+  protected static final String CONFIG_FORMAT_FILE = "config_format.xsl"; //int CONFIG_PASS = 1;
+  protected static final String TEXT_FORMAT_FILE = "text_fragment_format.xsl"; //int TEXT_PASS = 2;
 
 	static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.TransformingReceptionist.class.getName());
@@ -57,4 +57,6 @@
 	static final String preprocess_xsl_filename = GlobalProperties.getGSDL3Home() + File.separatorChar + "interfaces" + File.separatorChar + "core" + File.separatorChar + "transform" + File.separatorChar + "preProcess.xsl";
 
+  static final String gslib_filename = "gslib.xsl";
+  
 	/** the list of xslt to use for actions */
 	protected HashMap<String, String> xslt_map = null;
@@ -610,100 +612,20 @@
 
 	/**
-	 * transform the page using xslt we need to get any format element out of
-	 * the page and add it to the xslt before transforming
+	 * transform the page using xslt.
+	 * we need to get any format element out of the page and add it to the xslt before transforming
 	 */
-        protected Node transformPage(Element page,String currentInterface,String output)
+        protected Node transformPage(Element page_xml, String currentInterface, String output)
 	{
 		_debug = false;
 
-		Element request = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
+		Element request = (Element) GSXML.getChildByTagName(page_xml, GSXML.PAGE_REQUEST_ELEM);
 
 		//logger.info("Current output mode is: " + output + ", current interface name is: " + currentInterface);
 		
-		// DocType defaults in case the skin doesn't have an "xsl:output" element
-		String qualifiedName = "html";
-		String publicID = "-//W3C//DTD HTML 4.01 Transitional//EN";
-		String systemID = "http://www.w3.org/TR/html4/loose.dtd";
-
-		// We need to create an empty document with a predefined DocType,
-		// that will then be used for the transformation by the DOMResult
-		Document docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
-
 		if (output.equals("xsltclient"))
 		{
-		        String baseURL = request.getAttribute(GSXML.BASE_URL);
-				
-			// If you're just getting the client-side transform page, why bother with the rest of this?
-			Element html = docWithDoctype.createElement("html");
-			Element img = docWithDoctype.createElement("img");
-			img.setAttribute("src", "loading.gif"); // Make it dynamic
-			img.setAttribute("alt", "Please wait...");
-			Text title_text = docWithDoctype.createTextNode("Please wait..."); // Make this language dependent
-			Element head = docWithDoctype.createElement("head");
-
-			// e.g., <base href="http://localhost:8383/greenstone3/" /><!-- [if lte IE 6]></base><![endif] -->
-			Element base = docWithDoctype.createElement("base");
-			base.setAttribute("href",baseURL);
-			Comment opt_end_base = docWithDoctype.createComment("[if lte IE 6]></base><![endif]");
-			
-			Element title = docWithDoctype.createElement("title");
-			title.appendChild(title_text);
-
-			Element body = docWithDoctype.createElement("body");
-
-			Element jquery_script = docWithDoctype.createElement("script");
-			jquery_script.setAttribute("src", "jquery-1.10-min.js");
-			jquery_script.setAttribute("type", "text/javascript");
-			Comment jquery_comment = docWithDoctype.createComment("jQuery");
-			jquery_script.appendChild(jquery_comment);
-
-			Element saxonce_script = docWithDoctype.createElement("script");
-			saxonce_script.setAttribute("src", "Saxonce/Saxonce.nocache.js");
-			saxonce_script.setAttribute("type", "text/javascript");
-			Comment saxonce_comment = docWithDoctype.createComment("SaxonCE");
-			saxonce_script.appendChild(saxonce_comment);
-
-			Element xsltutil_script = docWithDoctype.createElement("script");
-			xsltutil_script.setAttribute("src", "xslt-util.js");
-			xsltutil_script.setAttribute("type", "text/javascript");
-			Comment xsltutil_comment = docWithDoctype.createComment("JavaScript version of XSLTUtil.java");
-			xsltutil_script.appendChild(xsltutil_comment);
-
-			Element script = docWithDoctype.createElement("script");
-			Comment script_comment = docWithDoctype.createComment("Filler for browser");
-			script.setAttribute("src", "client-side-xslt.js");
-			script.setAttribute("type", "text/javascript");
-			script.appendChild(script_comment);
-			
-			Element pagevar = docWithDoctype.createElement("script");
-			Element style = docWithDoctype.createElement("style");
-			style.setAttribute("type", "text/css");
-			Text style_text = docWithDoctype.createTextNode("body { text-align: center; padding: 50px; font: 14pt Arial, sans-serif; font-weight: bold; }");
-			pagevar.setAttribute("type", "text/javascript");
-			Text page_var_text = docWithDoctype.createTextNode("var placeholder = true;");
-
-			html.appendChild(head);
-			head.appendChild(base); head.appendChild(opt_end_base);
-			head.appendChild(title);
-			head.appendChild(style);
-			style.appendChild(style_text);
-			html.appendChild(body);
-			head.appendChild(pagevar);
-			head.appendChild(jquery_script);
-			head.appendChild(saxonce_script);
-			head.appendChild(xsltutil_script);
-			head.appendChild(script);
-			pagevar.appendChild(page_var_text);
-
-			body.appendChild(img);
-			docWithDoctype.appendChild(html);
-
-			return (Node) docWithDoctype;
-		}
-
-		// Passing in the pretty string here means it needs to be generated even when not debugging; so use custom function to return blank when debug is off
-		//logger.debug("page before transforming:");
-		//logger.debug(this.converter.getPrettyStringLogger(page, logger));
-
+		  return generateXSLTClientOutput(request);
+		}
+		
 		String action = request.getAttribute(GSXML.ACTION_ATT);
 		String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
@@ -713,58 +635,36 @@
 		// for now, if output=xml, we don't transform the page, we just return 
 		// the page xml
-		Document theXML = null;
+		Document page_with_xslt_params_doc = null;
 
 		if (output.equals("xml") || (output.equals("json")) || output.equals("clientside"))
 		{
-			// Append some bits and pieces first...
-			theXML = converter.newDOM();
+			// Append the xsltparams to the page
+		        page_with_xslt_params_doc = converter.newDOM();
 			// Import into new document first!
-			Node newPage = theXML.importNode(page, true);
-			theXML.appendChild(newPage);
-			Element root = theXML.createElement("xsltparams");
-			newPage.appendChild(root);
-
-			Element libname = theXML.createElement("param");
-			libname.setAttribute("name", "library_name");
-			Text libnametext = theXML.createTextNode((String) config_params.get(GSConstants.LIBRARY_NAME));
-			libname.appendChild(libnametext);
-
-			Element intname = theXML.createElement("param");
-			intname.setAttribute("name", "interface_name");
-			Text intnametext = theXML.createTextNode((String) config_params.get(GSConstants.INTERFACE_NAME));
-			intname.appendChild(intnametext);
-
-			Element siteName = theXML.createElement("param");
-			siteName.setAttribute("name", "site_name");
-			Text siteNameText = theXML.createTextNode((String) config_params.get(GSConstants.SITE_NAME));
-			siteName.appendChild(siteNameText);
-
-			Element clientSideXSLTName = theXML.createElement("param");
-			clientSideXSLTName.setAttribute("name", "use_client_side_xslt");
+			Node page_with_xslt_params = page_with_xslt_params_doc.importNode(page_xml, true);
+			page_with_xslt_params_doc.appendChild(page_with_xslt_params);
+			Element xslt_params = page_with_xslt_params_doc.createElement("xsltparams");
+			page_with_xslt_params.appendChild(xslt_params);
+
+			GSXML.addParameter2ToList(xslt_params, "library_name", (String) config_params.get(GSConstants.LIBRARY_NAME));
+			GSXML.addParameter2ToList(xslt_params, "interface_name", (String) config_params.get(GSConstants.INTERFACE_NAME));
+			GSXML.addParameter2ToList(xslt_params, "site_name", (String) config_params.get(GSConstants.SITE_NAME));
 			Boolean useClientXSLT = (Boolean) config_params.get(GSConstants.USE_CLIENT_SIDE_XSLT);
-			Text clientSideXSLTNameText = theXML.createTextNode(useClientXSLT.toString());
-			clientSideXSLTName.appendChild(clientSideXSLTNameText);
+			GSXML.addParameter2ToList(xslt_params, "use_client_side_xslt", useClientXSLT.toString());
+			GSXML.addParameter2ToList(xslt_params, "filepath", GlobalProperties.getGSDL3Home());
 			
-			Element filepath = theXML.createElement("param");
-			filepath.setAttribute("name", "filepath");
-			Text filepathtext = theXML.createTextNode(GlobalProperties.getGSDL3Home());
-			filepath.appendChild(filepathtext);
-
-			root.appendChild(libname);
-			root.appendChild(intname);
-			root.appendChild(siteName);
-			root.appendChild(clientSideXSLTName);
-			root.appendChild(filepath);
-
 			if ((output.equals("xml")) || output.equals("json"))
 			{
-				// in the case of "json", calling method responsible for converting to JSON-string
-				return theXML.getDocumentElement();
-			}
+			  // Just return the page XML
+			  // in the case of "json", calling method responsible for converting to JSON-string
+			  return page_with_xslt_params_doc.getDocumentElement();
+			}
+			// in the case of client side, later on we'll use this doc with xslt params added,
+			// along with the xsl.
 		}
 
 		Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
 		String collection = "";
-		String inlineTemplate = "";
+		String inline_template = "";
 		if (cgi_param_list != null)
 		{
@@ -777,5 +677,5 @@
 			}
 
-			inlineTemplate = (String) params.get(GSParams.INLINE_TEMPLATE);
+			inline_template = (String) params.get(GSParams.INLINE_TEMPLATE);
 			String debug_p = (String) params.get(GSParams.DEBUG);
 			if (debug_p != null && (debug_p.equals("on") || debug_p.equals("1") || debug_p.equals("true")))
@@ -812,46 +712,54 @@
 		config_params.put("collName", collection);
 
-		Document style_doc = getXSLTDocument(action, subaction, collection);
-		if (style_doc == null)
-		{
-		  // this getParseErrorMessage may have originally worked, but now it doesn't.
-		  // //String errorPage = this.converter.getParseErrorMessage();
-		  // 	if (errorPage != null)
-		  // 	{
-		  // 	  return XMLTransformer.constructErrorXHTMLPage("Cannot parse the xslt file\n");// + errorPage);
-		  // 	}
-			return page;
-		}
-
+		// find the appropriate stylesheet (based on action/subaction) - eg a=p&sa=home will be home.xsl
+		// This mapping is defined in interfaceConfig.xsl
+		// All versions of the stylesheet (base interface, interface, site, collection) are
+		// merged together into one document
+		Document page_xsl = getXSLTDocument(action, subaction, collection);
+		String page_xsl_filename = getXSLTFilename(action, subaction); // for debug purposes
+		if (page_xsl == null)
+		{
+		  logger.error("Couldn't find and/or load the stylesheet ("+page_xsl_filename+") for a="+action+", sa="+subaction+", in collection "+collection);
+		  return XMLTransformer.constructErrorXHTMLPage("Couldn't find and/or load the stylesheet \""+page_xsl_filename+"\" for a="+action+", sa="+subaction+", in collection "+collection);
+		}
+
+		if (output.equals("xsl1")) {
+		  // if we just output the page_xsl directly then there may be unescaped & in the javascript,
+		  // and the page won't display properly
+		  return converter.getDOM(getStringFromDocument(page_xsl));
+		}
+
+		
 		// put the page into a document - this is necessary for xslt to get
 		// the paths right if you have paths relative to the document root
 		// eg /page.
-		Document doc = XMLConverter.newDOM();
-		doc.appendChild(doc.importNode(page, true));
-		Element page_response = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
+		Document page_xml_doc = XMLConverter.newDOM();
+		page_xml_doc.appendChild(page_xml_doc.importNode(page_xml, true));
+		Element page_response = (Element) GSXML.getChildByTagName(page_xml, GSXML.PAGE_RESPONSE_ELEM);
 		Element format_elem = (Element) GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM);
 
-		NodeList pageElems = doc.getElementsByTagName("page");
-		if (pageElems.getLength() > 0)
-		{
-			Element pageElem = (Element) pageElems.item(0);
-			String langAtt = pageElem.getAttribute(GSXML.LANG_ATT);
-
-			if (langAtt != null && langAtt.length() > 0)
-			{
-				config_params.put("lang", langAtt);
-			}
-		}
-
-		if (output.equals("formatelem"))
+		if (output.equals("format"))
 		{
 			return format_elem;
 		}
+
+		// do we have language attribute for page?
+		String lang_att = page_xml.getAttribute(GSXML.LANG_ATT);
+		if (lang_att != null && lang_att.length() > 0)
+		  {
+		    config_params.put("lang", lang_att);
+		  }
+		
 		if (format_elem != null)
 		{
-			//page_response.removeChild(format_elem);
-			logger.debug("format elem=" + this.converter.getPrettyStringLogger(format_elem, logger));
-			// need to transform the format info
-			String configStylesheet_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, "config_format.xsl");
+		  //page_response.removeChild(format_elem);
+		  
+		  // need to transform the format info
+		  // run config_format.xsl over the format_elem. We need to do this now to turn
+		  // eg gsf:template into xsl:template so that the merging works properly.
+		  // xsl:templates will get merged
+		  // into the main stylesheet, but gsf:templates won't.
+		  
+			String configStylesheet_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, CONFIG_FORMAT_FILE);
 			Document configStylesheet_doc = this.converter.getDOM(new File(configStylesheet_file));
 
@@ -881,5 +789,5 @@
 					new_format = (Element) result;
 				}
-				logger.debug("new format elem=" + this.converter.getPrettyStringLogger(new_format, logger));
+				
 				if (output.equals("newformat"))
 				{
@@ -887,39 +795,86 @@
 				}
 
-				// add extracted GSF statements in to the main stylesheet
+				// add the extracted format statements in to the main stylesheet
 				if (_debug)
 				{
 					String siteHome = GSFile.siteHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME));
-					GSXSLT.mergeStylesheetsDebug(style_doc, new_format, true, true, "OTHER1", GSFile.collectionConfigFile(siteHome, collection));
+					GSXSLT.mergeStylesheetsDebug(page_xsl, new_format, true, true, "OTHER1", GSFile.collectionConfigFile(siteHome, collection));
 				}
 				else
 				{
-					GSXSLT.mergeStylesheets(style_doc, new_format, true);
-				}
-				//System.out.println("added extracted GSF statements into the main stylesheet") ;
-
-				// add extracted GSF statements in to the debug test stylesheet
-				//GSXSLT.mergeStylesheets(oldStyle_doc, new_format);
+				  GSXSLT.mergeStylesheets(page_xsl, new_format, true);
+				}
+
 			}
 			else
 			{
-				logger.error(" couldn't parse the config_format stylesheet, adding the format info as is");
-				GSXSLT.mergeStylesheets(style_doc, format_elem, true);
-				//GSXSLT.mergeStylesheets(oldStyle_doc, format_elem);
-			}
-			logger.debug("the converted stylesheet is:");
-			logger.debug(this.converter.getPrettyStringLogger(style_doc.getDocumentElement(), logger));
-		}
-
-		//for debug purposes only
-		Document oldStyle_doc = style_doc;
-		Document preprocessingXsl;
+			  // Is this a fatal error, or are there situations where we could carry on here...
+			  logger.error(" Couldn't parse the "+CONFIG_FORMAT_FILE+" stylesheet");
+			  return XMLTransformer.constructErrorXHTMLPage("Couldn't find and/or load the stylesheet \""+CONFIG_FORMAT_FILE);
+			  //GSXSLT.mergeStylesheets(page_xsl, format_elem, true);
+			}
+		}
+
+		if (output.equals("xsl2")) {
+		  return converter.getDOM(getStringFromDocument(page_xsl));
+		}
+
+		if (inline_template != null)
+		{
+			try
+			{
+				Document inline_template_doc = this.converter.getDOM("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xsl:stylesheet version=\"1.0\" "+GSXML.ALL_NAMESPACES_ATTS +  ">" + inline_template + "</xsl:stylesheet>", "UTF-8");
+
+				if (_debug)
+				{
+					GSXSLT.mergeStylesheetsDebug(page_xsl, inline_template_doc.getDocumentElement(), true, true, "OTHER2", "INLINE");
+				}
+				else
+				{
+				  //GSXSLT.mergeStylesheets(skinAndLibraryDoc, inlineTemplateDoc.getDocumentElement(), true);
+				  GSXSLT.mergeStylesheets(page_xsl, inline_template_doc.getDocumentElement(), true);
+				}
+			}
+			catch (Exception ex)
+			{
+				ex.printStackTrace();
+			}
+		}
+
+		if (output.equals("xsl3")) {
+		  return converter.getDOM(getStringFromDocument(page_xsl));
+		}
+
+		// once we are here, have got the main page xsl loaded up. Have added in any format statements from the source xml, and added in any inline template which came through cgi params.
+		
+		// next we load in the import and include files. - these, too, go through the inheritance cascade (base interface, interface, site, collection) before being added into the main document
+		
+		if (_debug)
+		{
+		  GSXSLT.inlineImportAndIncludeFilesDebug(page_xsl, null, _debug, page_xsl_filename, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
+		}
+		else
+		{
+		  GSXSLT.inlineImportAndIncludeFiles(page_xsl, null, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
+		
+		}
+
+		if (output.equals("xsl4")) {
+		  return converter.getDOM(getStringFromDocument(page_xsl));
+		}
+  
+  // The next steg is to process the page_xsl +  gslib.xsl by preProcess.xsl to expand all the
+  // gslib elements
+
+                Document preprocessingXsl;
 		try
 		{
+		  // interfaces/core/transform/preProcess.xsl
+		  // this takes skinandLibraryXsl, copies skinXSL, merges elements of libraryXsl into it, and replaces gslib elements
 			preprocessingXsl = getDoc(preprocess_xsl_filename);
 			String errMsg = ((XMLConverter.ParseErrorHandler) parser.getErrorHandler()).getErrorMessage();
 			if (errMsg != null)
 			{
-				return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt file: " + preprocess_xsl_filename + "\n" + errMsg);
+				return XMLTransformer.constructErrorXHTMLPage("error loading core/transform/preProcess xslt file: " + preprocess_xsl_filename + "\n" + errMsg);
 			}
 		}
@@ -932,11 +887,12 @@
 			e.printStackTrace();
 			System.out.println("error loading preprocess xslt");
-			return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt\n" + e.getMessage());
-		}
-
+			return XMLTransformer.constructErrorXHTMLPage("Error loading interfaces/core/transform/preProcess xslt\n" + e.getMessage());
+		}
+
+		// gslib.xsl
 		Document libraryXsl = null;
 		try
 		{
-			libraryXsl = GSXSLT.mergedXSLTDocumentCascade("gslib.xsl", (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, _debug);
+			libraryXsl = GSXSLT.mergedXSLTDocumentCascade(gslib_filename, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, _debug);
 		}
 		catch (Exception e)
@@ -947,4 +903,10 @@
 		}
 
+  if (output.equals("preprocess")) {
+    return converter.getDOM(getStringFromDocument(preprocessingXsl));
+  }
+  if (output.equals("gslib")) {
+    return converter.getDOM(getStringFromDocument(libraryXsl));
+  }
 		//   Combine the skin file and library variables/templates into one document. 
 		//   Please note: We dont just use xsl:import because the preprocessing stage  
@@ -954,181 +916,78 @@
 		Document skinAndLibraryDoc = converter.newDOM();
 
-		// Applying the preprocessing XSLT - in its own block {} to allow use of non-unique variable names
-		{
-
-			skinAndLibraryXsl = converter.newDOM();
-			Element root = skinAndLibraryXsl.createElement("skinAndLibraryXsl");
-			skinAndLibraryXsl.appendChild(root);
-
-			Element s = skinAndLibraryXsl.createElement("skinXsl");
-			s.appendChild(skinAndLibraryXsl.importNode(style_doc.getDocumentElement(), true));
-			root.appendChild(s);
-
-			Element l = skinAndLibraryXsl.createElement("libraryXsl");
-			if (libraryXsl != null)
-			{
-				Element libraryXsl_el = libraryXsl.getDocumentElement();
-				l.appendChild(skinAndLibraryXsl.importNode(libraryXsl_el, true));
-			}
-			root.appendChild(l);
-
-			//System.out.println("Skin and Library XSL are now together") ;
-
-			//System.out.println("Pre-processing the skin file...") ;
-
-			//pre-process the skin style sheet
-			//In other words, apply the preProcess.xsl to 'skinAndLibraryXsl' in order to
-			//expand all GS-Lib statements into complete XSL statements and also to create
-			//a valid xsl style sheet document.
-
-			XMLTransformer preProcessor = new XMLTransformer();
-			// Perform the transformation, by passing in:
-			// preprocess-stylesheet, source-xsl (skinAndLibraryXsl), and the node that should 
-			// be in the result (skinAndLibraryDoc)
-			preProcessor.transform_withResultNode(preprocessingXsl, skinAndLibraryXsl, skinAndLibraryDoc);
-			//System.out.println("GS-Lib statements are now expanded") ;
-		}
-
-		// there is a thing called a URIResolver which you can set for a
-		// transformer or transformer factory. may be able to use this
-		// instead of this absoluteIncludepaths hack
-
-		//GSXSLT.absoluteIncludePaths(skinAndLibraryDoc, GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
-
-		//Same but for the debug version when we want the do the transformation like we use to do
-		//without any gslib elements.
-		GSXSLT.absoluteIncludePaths(oldStyle_doc, GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
-
-		//Send different stages of the skin xslt to the browser for debug purposes only
-		//using &o=skindoc or &o=skinandlib etc...
-		if (output.equals("skindoc"))
-		{
-			return converter.getDOM(getStringFromDocument(style_doc));
-		}
-		if (output.equals("skinandlib"))
-		{
-			return converter.getDOM(getStringFromDocument(skinAndLibraryXsl));
-		}
-		if (output.equals("skinandlibdoc"))
-		{
-
-			Node skinAndLib = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
-			return skinAndLib;			
-		}
-		if (output.equals("oldskindoc"))
-		{
-			return converter.getDOM(getStringFromDocument(oldStyle_doc));
-		}
-
-		// We now no longer create a document with doctype before the transformation
-		// We let the XMLTransformer do the work of first working out the doctype from any 
-		// that may be set in the (merged) stylesheets and then setting the doctype when transforming
-
-		/*
-		// Try to get the system and public ID from the current skin xsl document
-		// otherwise keep the default values.
-		Element root = skinAndLibraryDoc.getDocumentElement();
-		NodeList nodes = root.getElementsByTagName("xsl:output");
-		// If there is at least one "xsl:output" command in the final xsl then...
-		if (nodes.getLength() != 0)
-		{
-			// There should be only one element called xsl:output, 
-			// but if this is not the case get the last one
-			Element xsl_output = (Element) nodes.item(nodes.getLength() - 1);
-			if (xsl_output != null)
-			{
-				// Qualified name will always be html even for xhtml pages
-				//String attrValue = xsl_output.getAttribute("method");
-				//qualifiedName = attrValue.equals("") ? qualifiedName : attrValue;
-
-				String attrValue = xsl_output.getAttribute("doctype-system");
-				systemID = attrValue.equals("") ? systemID : attrValue;
-
-				attrValue = xsl_output.getAttribute("doctype-public");
-				publicID = attrValue.equals("") ? publicID : attrValue;
-			}
-		}
-
-		//System.out.println(converter.getPrettyString(docWithDoctype));
-		//System.out.println("Doctype vals: " + qualifiedName + " " + publicID + " " + systemID) ;
-
-		docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
-		*/
-
-		//System.out.println("Generate final HTML from current skin") ;
-		//Transformation of the XML message from the receptionist to HTML with doctype
-
-		if (inlineTemplate != null)
-		{
-			try
-			{
-				Document inlineTemplateDoc = this.converter.getDOM("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xsl:stylesheet version=\"1.0\" "+GSXML.ALL_NAMESPACES_ATTS +  ">" + inlineTemplate + "</xsl:stylesheet>", "UTF-8");
-
-				if (_debug)
-				{
-					GSXSLT.mergeStylesheetsDebug(skinAndLibraryDoc, inlineTemplateDoc.getDocumentElement(), true, true, "OTHER2", "INLINE");
-				}
-				else
-				{
-					GSXSLT.mergeStylesheets(skinAndLibraryDoc, inlineTemplateDoc.getDocumentElement(), true);
-				}
-			}
-			catch (Exception ex)
-			{
-				ex.printStackTrace();
-			}
-		}
-
-		if (_debug)
-		{
-			GSXSLT.inlineImportAndIncludeFilesDebug(skinAndLibraryDoc, null, _debug, this.getGSLibXSLFilename(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
-		}
-		else
-		{
-			GSXSLT.inlineImportAndIncludeFiles(skinAndLibraryDoc, null, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
-		}
-		skinAndLibraryDoc = (Document) performFormatPass(collection, skinAndLibraryDoc, doc, new UserContext(request), TEXT_PASS);
-		skinAndLibraryDoc = (Document) performFormatPass(collection, skinAndLibraryDoc, doc, new UserContext(request), CONFIG_PASS);
-
-		if (output.equals("xmlfinal"))
-		{
-			return doc;
-		}
-
-		if (output.equals("skinandlibdocfinal") || output.equals("clientside"))
-		{
-			if (output.equals("skinandlibdocfinal"))
-			{
-			        Node skinAndLibFinal = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
-				return skinAndLibFinal;
-			}
-			else
-			{
-			        // Go through and 'fix up' any 'util:...' or 'java:...' attributes the skinAndLibraryDoc has
-			        String lang = (String)config_params.get("lang");
-			        resolveExtendedNamespaceAttributesXSLT(skinAndLibraryDoc,currentInterface,lang); // test= and select= attributes
-				resolveExtendedNamespaceAttributesXML(skinAndLibraryDoc,currentInterface,lang);  // href= and src= attributes
-				Node skinAndLibFinal = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
-				
-				// Send XML and skinandlibdoc down the line together
-				Document finalDoc = converter.newDOM();
-				Node finalDocSkin = finalDoc.importNode(skinAndLibraryDoc.getDocumentElement(), true);
-				Node finalDocXML = finalDoc.importNode(theXML.getDocumentElement(), true);
-				Element root = finalDoc.createElement("skinlibfinalPlusXML");
-				root.appendChild(finalDocSkin);
-				root.appendChild(finalDocXML);
-				finalDoc.appendChild(root);
-				return (Node) finalDoc.getDocumentElement();
-			}
-
-
-
-			
-		}
-
+                // add in all gslib.xsl's include and import files
+		// debug?? use debug method?? or does it not make sense here??
+		GSXSLT.inlineImportAndIncludeFiles(libraryXsl, null, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
+
+		// now, we transform all the gslib elements
+		{
+		  
+
+		  skinAndLibraryXsl = converter.newDOM();
+		  Element root = skinAndLibraryXsl.createElement("skinAndLibraryXsl");
+		  skinAndLibraryXsl.appendChild(root);
+		  
+		  Element s = skinAndLibraryXsl.createElement("skinXsl");
+		  s.appendChild(skinAndLibraryXsl.importNode(page_xsl.getDocumentElement(), true));
+		  root.appendChild(s);
+		  
+		  Element l = skinAndLibraryXsl.createElement("libraryXsl");
+		  if (libraryXsl != null)
+		    {
+		      Element libraryXsl_el = libraryXsl.getDocumentElement();
+		      l.appendChild(skinAndLibraryXsl.importNode(libraryXsl_el, true));
+		    }
+		  root.appendChild(l);
+
+		  XMLTransformer preProcessor = new XMLTransformer();
+		  preProcessor.transform_withResultNode(preprocessingXsl, skinAndLibraryXsl, skinAndLibraryDoc);
+
+		}
+		if (output.equals("xsl5")) {
+		  return converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
+		}
+
+		skinAndLibraryDoc = (Document) transformGSFElements(collection, skinAndLibraryDoc, TEXT_FORMAT_FILE); 
+		  
+		skinAndLibraryDoc = (Document) transformGSFElements(collection, skinAndLibraryDoc, CONFIG_FORMAT_FILE); 
+		}
+		
+
+		if (output.equals("xsl6") || output.equals("skinandlibdocfinal")
+		{
+		  return converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
+		}
+		
+		if (output.equals("clientside"))
+		{
+			        
+		  // Go through and 'fix up' any 'util:...' or 'java:...' attributes the skinAndLibraryDoc has
+		  String lang = (String)config_params.get("lang");
+		  resolveExtendedNamespaceAttributesXSLT(skinAndLibraryDoc,currentInterface,lang); // test= and select= attributes
+		  resolveExtendedNamespaceAttributesXML(skinAndLibraryDoc,currentInterface,lang);  // href= and src= attributes
+		  Node skinAndLibFinal = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
+		  
+		  // Send XML and skinandlibdoc down the line together
+		  Document finalDoc = converter.newDOM();
+		  Node finalDocSkin = finalDoc.importNode(skinAndLibraryDoc.getDocumentElement(), true);
+		  Node finalDocXML = finalDoc.importNode(page_with_xslt_params_doc.getDocumentElement(), true);
+		  Element root = finalDoc.createElement("skinlibfinalPlusXML");
+		  root.appendChild(finalDocSkin);
+		  root.appendChild(finalDocXML);
+		  finalDoc.appendChild(root);
+		  return (Node) finalDoc.getDocumentElement();
+		}
+		
+		logger.debug("final xml is ");
+		logger.debug(XMLConverter.getPrettyString(page_xml_doc));
+
+		logger.debug("final xsl is");
+		logger.debug(XMLConverter.getPrettyString(skinAndLibraryDoc));
+		
 		// The transformer will now work out the resulting doctype from any set in the (merged) stylesheets and
 		// will set this in the output document it creates. So don't pass in any docWithDocType to the transformer
-		//Node finalResult = this.transformer.transform(skinAndLibraryDoc, doc, config_params, docWithDoctype);
-		Node finalResult = this.transformer.transform(skinAndLibraryDoc, doc, config_params);
+
+  // Here, we finally transform the page xml source with the complete xsl file
+  Node finalResult = this.transformer.transform(skinAndLibraryDoc, page_xml_doc, config_params);
 
 		if (_debug)
@@ -1139,32 +998,101 @@
 		return finalResult;
 
-		// The line below will do the transformation like we use to do before having Skin++ implemented,
-		// it will not contain any GS-Lib statements expanded, and the result will not contain any doctype.
-
-		//return (Element)this.transformer.transform(style_doc, doc, config_params);  
-		//return null; // For now - change later
-	}
-
-	protected Node performFormatPass(String collection, Document skinAndLibraryDoc, Document doc, UserContext userContext, int pass)
-	{
-		String formatFile;
-		if (pass == CONFIG_PASS)
-		{
-			formatFile = "config_format.xsl";
-		}
-		else
-		{
-			formatFile = "text_fragment_format.xsl";
-		}
-
-		String configStylesheet_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, formatFile);
-		Document configStylesheet_doc = this.converter.getDOM(new File(configStylesheet_file));
-
-		if (configStylesheet_doc != null)
-		{
-			return this.transformer.transform(configStylesheet_doc, skinAndLibraryDoc, config_params);
-		}
-		return skinAndLibraryDoc;
-	}
+	}
+
+  protected Node generateXSLTClientOutput(Element request) {
+
+    // DocType defaults in case the skin doesn't have an "xsl:output" element
+    String qualifiedName = "html";
+    String publicID = "-//W3C//DTD HTML 4.01 Transitional//EN";
+    String systemID = "http://www.w3.org/TR/html4/loose.dtd";
+
+    // We need to create an empty document with a predefined DocType,
+    // that will then be used for the transformation by the DOMResult
+    Document docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
+    String baseURL = request.getAttribute(GSXML.BASE_URL);
+				
+    // If you're just getting the client-side transform page, why bother with the rest of this?
+    Element html = docWithDoctype.createElement("html");
+    Element img = docWithDoctype.createElement("img");
+    img.setAttribute("src", "loading.gif"); // Make it dynamic
+    img.setAttribute("alt", "Please wait...");
+    Text title_text = docWithDoctype.createTextNode("Please wait..."); // Make this language dependent
+    Element head = docWithDoctype.createElement("head");
+
+    // e.g., <base href="http://localhost:8383/greenstone3/" /><!-- [if lte IE 6]></base><![endif] -->
+    Element base = docWithDoctype.createElement("base");
+    base.setAttribute("href",baseURL);
+    Comment opt_end_base = docWithDoctype.createComment("[if lte IE 6]></base><![endif]");
+			
+    Element title = docWithDoctype.createElement("title");
+    title.appendChild(title_text);
+
+    Element body = docWithDoctype.createElement("body");
+
+    Element jquery_script = docWithDoctype.createElement("script");
+    jquery_script.setAttribute("src", "jquery-1.10-min.js");
+    jquery_script.setAttribute("type", "text/javascript");
+    Comment jquery_comment = docWithDoctype.createComment("jQuery");
+    jquery_script.appendChild(jquery_comment);
+
+    Element saxonce_script = docWithDoctype.createElement("script");
+    saxonce_script.setAttribute("src", "Saxonce/Saxonce.nocache.js");
+    saxonce_script.setAttribute("type", "text/javascript");
+    Comment saxonce_comment = docWithDoctype.createComment("SaxonCE");
+    saxonce_script.appendChild(saxonce_comment);
+
+    Element xsltutil_script = docWithDoctype.createElement("script");
+    xsltutil_script.setAttribute("src", "xslt-util.js");
+    xsltutil_script.setAttribute("type", "text/javascript");
+    Comment xsltutil_comment = docWithDoctype.createComment("JavaScript version of XSLTUtil.java");
+    xsltutil_script.appendChild(xsltutil_comment);
+
+    Element script = docWithDoctype.createElement("script");
+    Comment script_comment = docWithDoctype.createComment("Filler for browser");
+    script.setAttribute("src", "client-side-xslt.js");
+    script.setAttribute("type", "text/javascript");
+    script.appendChild(script_comment);
+			
+    Element pagevar = docWithDoctype.createElement("script");
+    Element style = docWithDoctype.createElement("style");
+    style.setAttribute("type", "text/css");
+    Text style_text = docWithDoctype.createTextNode("body { text-align: center; padding: 50px; font: 14pt Arial, sans-serif; font-weight: bold; }");
+    pagevar.setAttribute("type", "text/javascript");
+    Text page_var_text = docWithDoctype.createTextNode("var placeholder = true;");
+
+    html.appendChild(head);
+    head.appendChild(base); head.appendChild(opt_end_base);
+    head.appendChild(title);
+    head.appendChild(style);
+    style.appendChild(style_text);
+    html.appendChild(body);
+    head.appendChild(pagevar);
+    head.appendChild(jquery_script);
+    head.appendChild(saxonce_script);
+    head.appendChild(xsltutil_script);
+    head.appendChild(script);
+    pagevar.appendChild(page_var_text);
+
+    body.appendChild(img);
+    docWithDoctype.appendChild(html);
+
+    return (Node) docWithDoctype;
+
+  }
+
+  // transform the xsl with xsl to replace all gsf elements. We do this in 2 stages -
+  // first do just a text pass, that way we can have gsf elements in the text content 
+  protected Node transformGSFElements(String collection, Document skinAndLibraryDoc, String formatFile) {
+
+    String configStylesheet_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, formatFile);
+    Document configStylesheet_doc = this.converter.getDOM(new File(configStylesheet_file));
+    
+    if (configStylesheet_doc != null)
+      {
+	return this.transformer.transform(configStylesheet_doc, skinAndLibraryDoc, config_params);
+      }
+    return skinAndLibraryDoc;
+    
+  }    
 
 	// method to convert Document to a proper XML string for debug purposes only
@@ -1205,32 +1133,40 @@
 	}
 
+  protected String getXSLTFilename(String action, String subaction) {
+    String name = null;
+    if (!subaction.equals(""))
+      {
+	String key = action + ":" + subaction;
+	name = this.xslt_map.get(key);
+      }
+    // try the action by itself
+    if (name == null)
+      {
+	name = this.xslt_map.get(action);
+      }
+    if (name == null)
+      {
+	// so we can reandomly create any named page
+	if (action.equals("p") && !subaction.equals(""))
+	  {
+	    // TODO: pages/ won't work for interface other than default!!
+	    name = "pages/" + subaction + ".xsl";
+	  }
+	
+      }
+    return name;
+  }
+
+  
 	protected Document getXSLTDocument(String action, String subaction, String collection)
 	{
-		String name = null;
-		if (!subaction.equals(""))
-		{
-			String key = action + ":" + subaction;
-			name = this.xslt_map.get(key);
-		}
-		// try the action by itself
-		if (name == null)
-		{
-			name = this.xslt_map.get(action);
-		}
-		if (name == null)
-		{
-			// so we can reandomly create any named page
-			if (action.equals("p") && !subaction.equals(""))
-			{
-				// TODO: pages/ won't work for interface other than default!!
-				name = "pages/" + subaction + ".xsl";
-			}
-
-		}
-		
+	  String name = getXSLTFilename(action, subaction);
 		Document finalDoc = null;
 		if(name != null)
 		{
-			finalDoc = GSXSLT.mergedXSLTDocumentCascade(name, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, _debug);
+		  // this finds all the stylesheets named "name" and merges them together, in the order of
+		  // base interface, current interface, site, collection - the latter overriding the former.
+		  // templates with the same name will replace earlier versions
+		  finalDoc = GSXSLT.mergedXSLTDocumentCascade(name, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, _debug);
 		}
 		return finalDoc;
