[405223] Processing and file name/type doesn't match output type from
XSL
diff --git a/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/XSLLaunchShortcut.java b/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/XSLLaunchShortcut.java
index a852d7a..cebf156 100644
--- a/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/XSLLaunchShortcut.java
+++ b/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/XSLLaunchShortcut.java
@@ -11,11 +11,12 @@
  *******************************************************************************/
 package org.eclipse.wst.xsl.internal.debug.ui;
 
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -393,10 +394,11 @@
 		ILaunchConfiguration config = null;
 		try {
 			ILaunchConfigurationType configType = getConfigurationType();
+			String lastSegment = xmlFile != null ? xmlFile.getName() :  xmlFilePath != null ? xmlFilePath.lastSegment() : "XSLTransformation"; //$NON-NLS-1$
 			ILaunchConfigurationWorkingCopy wc = configType.newInstance(null,
 					getLaunchManager()
 							.generateUniqueLaunchConfigurationNameFrom(
-									xmlFilePath.lastSegment()));
+									lastSegment));
 			if (xmlFile != null)
 				wc
 						.setAttribute(
@@ -424,6 +426,16 @@
 				pipeline.addTransformDef(new LaunchTransform(xslFilePath,
 						LaunchTransform.EXTERNAL_TYPE));
 			}
+			if (! pipeline.getTransformDefs().isEmpty()) {
+				LaunchTransform lastDef = pipeline.getTransformDefs().get(pipeline.getTransformDefs().size()-1);
+				String outputFormat = guessOutputMethod(lastDef);
+				if (outputFormat != null) {
+					wc
+					.setAttribute(
+							XSLLaunchConfigurationConstants.ATTR_DEFAULT_OUTPUT_METHOD,
+							outputFormat);
+				}
+			}			
 			wc.setAttribute(XSLLaunchConfigurationConstants.ATTR_PIPELINE,
 					pipeline.toXML());
 			if (xmlFile != null)
@@ -436,6 +448,25 @@
 		return config;
 	}
 
+	private String guessOutputMethod(LaunchTransform lastDef) {
+		try {
+			XslOutputMethodSniffer xofs = new XslOutputMethodSniffer();
+			xofs.parseContents(new InputSource(new FileInputStream(lastDef.getLocation().toFile())));
+			return xofs.getOutputMethod();
+		} catch (FileNotFoundException e) {
+			// It's OK
+		} catch (IOException e) {
+			// It's OK
+		} catch (ParserConfigurationException e) {
+			// It's OK
+		} catch (SAXException e) {
+			// It's OK
+		} catch (CoreException e) {
+			// It really is OK!
+		}
+		return null;
+	}
+
 	protected Shell getShell() {
 		return XSLDebugUIPlugin.getActiveWorkbenchShell();
 	}
diff --git a/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/XslOutputMethodSniffer.java b/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/XslOutputMethodSniffer.java
new file mode 100644
index 0000000..4fd4908
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/XslOutputMethodSniffer.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Jesper Steen Moller and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Jesper Steen Moller - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xsl.internal.debug.ui;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * @since 3.5
+ */
+public final class XslOutputMethodSniffer extends DefaultHandler {
+	private static final String XSL_NAMESPACE = "http://www.w3.org/1999/XSL/Transform"; //$NON-NLS-1$
+	private static final String OUTPUT_ELEMENT_NAME = "output"; //$NON-NLS-1$
+	private static final String METHOD_ATTR_NAME = "method"; //$NON-NLS-1$
+	
+	/**
+	 * An exception indicating that the parsing should stop. This is usually
+	 * triggered when the top-level element has been found.
+	 */
+	private class StopParsingException extends SAXException {
+		/**
+		 * All serializable objects should have a stable serialVersionUID
+		 */
+		private static final long serialVersionUID = 1L;
+
+		/**
+		 * Constructs an instance of <code>StopParsingException</code> with a
+		 * <code>null</code> detail message.
+		 */
+		public StopParsingException() {
+			super((String) null);
+		}
+	}
+
+	private String outputMethod = null;
+
+	public String getOutputMethod() {
+		return this.outputMethod;
+	}
+
+	/**
+	 * Creates a new SAX parser for use within this instance.
+	 * 
+	 * @return The newly created parser.
+	 * 
+	 * @throws ParserConfigurationException
+	 *             If a parser of the given configuration cannot be created.
+	 * @throws SAXException
+	 *             If something in general goes wrong when creating the parser.
+	 * @throws SAXNotRecognizedException
+	 *             If the <code>XMLReader</code> does not recognize the
+	 *             lexical handler configuration option.
+	 * @throws SAXNotSupportedException
+	 *             If the <code>XMLReader</code> does not support the lexical
+	 *             handler configuration option.
+	 */
+	private final SAXParser createParser(SAXParserFactory parserFactory) throws ParserConfigurationException, SAXException, SAXNotRecognizedException, SAXNotSupportedException {
+		// Initialize the parser.
+		final SAXParser parser = parserFactory.newSAXParser();
+		final XMLReader reader = parser.getXMLReader();
+		try {
+			//	be sure validation is "off" or the feature to ignore DTD's will not apply
+			reader.setFeature("http://xml.org/sax/features/validation", false); //$NON-NLS-1$
+			reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
+		} catch (SAXNotRecognizedException e) {
+			// not a big deal if the parser does not recognize the features
+		} catch (SAXNotSupportedException e) {
+			// not a big deal if the parser does not support the features
+		}
+		return parser;
+	}
+
+	public boolean parseContents(InputSource contents) throws IOException, ParserConfigurationException, SAXException {
+		// Parse the file into we have what we need (or an error occurs).
+	
+		try {
+			SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+			parserFactory.setValidating(false);
+			parserFactory.setNamespaceAware(true);
+			final SAXParser parser = createParser(parserFactory);
+			// to support external entities specified as relative URIs (see bug 63298)
+			contents.setSystemId("/"); //$NON-NLS-1$
+			parser.parse(contents, this);
+		} catch (StopParsingException e) {
+			// Abort the parsing normally. Fall through...
+		}
+		return true;
+	}
+
+	/*
+	 * Resolve external entity definitions to an empty string.  This is to speed
+	 * up processing of files with external DTDs.  Not resolving the contents 
+	 * of the DTD is ok, as only the System ID of the DTD declaration is used.
+	 * @see org.xml.sax.helpers.DefaultHandler#resolveEntity(java.lang.String, java.lang.String)
+	 */
+	public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
+		return new InputSource(new StringReader("")); //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
+	 *      java.lang.String, java.lang.String, org.xml.sax.Attributes)
+	 */
+	public final void startElement(final String uri, final String elementName, final String qualifiedName, final Attributes attributes) throws SAXException {
+		if (XSL_NAMESPACE.equals(uri) && OUTPUT_ELEMENT_NAME.equals(elementName)) {
+			this.outputMethod = attributes.getValue(METHOD_ATTR_NAME);
+			throw new StopParsingException();
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.xml.sax.ext.LexicalHandler#startEntity(java.lang.String)
+	 */
+	public final void startEntity(final String name) {
+		// Not interested.
+	}
+	
+	@Override
+	public void processingInstruction(String target, String data)
+			throws SAXException {
+	}
+
+//	public static void main(String[] args) throws IOException, ParserConfigurationException, SAXException {
+//		String xml = "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'><xsl:output method='fish'/><xsl:template name='nameib1'></xsl:template></xsl:stylesheet>"; //$NON-NLS-1$
+//		XslOutputFormatSniffer sniffer = new XslOutputFormatSniffer();
+//		sniffer.parseContents(new InputSource(new StringReader(xml)));
+//		System.out.println(sniffer.getOutputMethod());
+//	}
+}
diff --git a/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/tabs/main/XSLMainTab.java b/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/tabs/main/XSLMainTab.java
index a9db14f..98d5096 100644
--- a/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/tabs/main/XSLMainTab.java
+++ b/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/tabs/main/XSLMainTab.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007,2008 Chase Technology Ltd - http://www.chasetechnology.co.uk and others
+ * Copyright (c) 2007,2013 Chase Technology Ltd - http://www.chasetechnology.co.uk and others
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  * Contributors:
  *     Doug Satchwell (Chase Technology Ltd) - initial API and implementation
  *     David Carver - STAR - bug 223557 - Added Images contributed by Holger Voorman
+ *     Jesper S Moller - 405223 - Processing and file name/type doesn't match output type from XSL
  *******************************************************************************/
 package org.eclipse.wst.xsl.internal.debug.ui.tabs.main;
 
@@ -124,6 +125,14 @@
 			configuration.setAttribute(
 					XSLLaunchConfigurationConstants.ATTR_PIPELINE, pipeline
 							.toXML());
+			
+			String method = pipeline.getOutputProperties().getProperty("method", null); //$NON-NLS-1$
+
+			if (method != null) {
+				configuration.setAttribute(
+						XSLLaunchConfigurationConstants.ATTR_DEFAULT_OUTPUT_METHOD, 
+						method);
+			}
 		} catch (CoreException e) {
 			XSLDebugUIPlugin.log(e);
 		}
diff --git a/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/tabs/output/OutputFileBlock.java b/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/tabs/output/OutputFileBlock.java
index ff99b65..ee31db8 100644
--- a/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/tabs/output/OutputFileBlock.java
+++ b/bundles/org.eclipse.wst.xsl.debug.ui/src/org/eclipse/wst/xsl/internal/debug/ui/tabs/output/OutputFileBlock.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007 Chase Technology Ltd - http://www.chasetechnology.co.uk
+ * Copyright (c) 2007, 2013 Chase Technology Ltd - http://www.chasetechnology.co.uk
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     Doug Satchwell (Chase Technology Ltd) - initial API and implementation
+ *     Jesper S Moller - 405223 - Processing and file name/type doesn't match output type from XSL
  *******************************************************************************/
 package org.eclipse.wst.xsl.internal.debug.ui.tabs.output;
 
@@ -39,6 +40,7 @@
 	private String inputFilename;
 	private Text fileNameText;
 	private String defaultOutputFileName;
+	private String defaultOutputFileMethod;
 	private String outputFileName;
 
 	public OutputFileBlock() {
@@ -196,6 +198,10 @@
 
 	public void initializeFrom(ILaunchConfiguration configuration) {
 		try {
+			defaultOutputFileMethod = configuration.getAttribute(
+					XSLLaunchConfigurationConstants.ATTR_DEFAULT_OUTPUT_METHOD,
+					"xml"); //$NON-NLS-1$
+			
 			inputFilename = configuration.getAttribute(
 					XSLLaunchConfigurationConstants.ATTR_INPUT_FILE, ""); //$NON-NLS-1$
 			updateDefaultOutputFile();
@@ -284,7 +290,7 @@
 	private void updateDefaultOutputFile() {
 		try {
 			IPath path = XSLTRuntime
-					.defaultOutputFileForInputFile(inputFilename);
+					.defaultOutputFileForInputFile(inputFilename, defaultOutputFileMethod);
 			// determine whether this path exists in the workspace
 			IFile[] files = ResourcesPlugin.getWorkspace().getRoot()
 					.findFilesForLocation(path);
diff --git a/bundles/org.eclipse.wst.xsl.launching/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.xsl.launching/META-INF/MANIFEST.MF
index 6e18cea..82c18ea 100644
--- a/bundles/org.eclipse.wst.xsl.launching/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.wst.xsl.launching/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name.0
 Bundle-SymbolicName: org.eclipse.wst.xsl.launching;singleton:=true
-Bundle-Version: 1.0.200.qualifier
+Bundle-Version: 1.1.0.qualifier
 Bundle-Activator: org.eclipse.wst.xsl.internal.launching.LaunchingPlugin
 Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
  org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)",
diff --git a/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/XSLLaunchConfigurationConstants.java b/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/XSLLaunchConfigurationConstants.java
index 1c226a4..8cc3beb 100644
--- a/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/XSLLaunchConfigurationConstants.java
+++ b/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/XSLLaunchConfigurationConstants.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007 Chase Technology Ltd - http://www.chasetechnology.co.uk
+ * Copyright (c) 2007, 2013 Chase Technology Ltd - http://www.chasetechnology.co.uk
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     Doug Satchwell (Chase Technology Ltd) - initial API and implementation
+ *     Jesper S Moller - 405223 - Processing and file name/type doesn't match output type from XSL
  *******************************************************************************/
 package org.eclipse.wst.xsl.launching;
 
@@ -38,4 +39,11 @@
 	 * @since 1.0
 	 */
 	public static final String ATTR_WORKING_DIR = LaunchingPlugin.PLUGIN_ID + ".ATTR_WORKING_DIR"; //$NON-NLS-1$;
+	
+	/**
+	 * @since 1.1
+	 */
+	public static final String ATTR_DEFAULT_OUTPUT_METHOD = LaunchingPlugin.PLUGIN_ID + ".ATTR_DEFAULT_OUTPUT_METHOD"; //$NON-NLS-1$;
+	
+	
 }
diff --git a/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/XSLTRuntime.java b/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/XSLTRuntime.java
index 1164cbd..92bf426 100644
--- a/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/XSLTRuntime.java
+++ b/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/XSLTRuntime.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Chase Technology Ltd - http://www.chasetechnology.co.uk
+ * Copyright (c) 2007, 2013 Chase Technology Ltd - http://www.chasetechnology.co.uk
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  * Contributors:
  *     Doug Satchwell (Chase Technology Ltd) - initial API and implementation
  *     David Carver (Intalio) - clean up find bugs
+ *     Jesper S Moller - 405223 - Processing and file name/type doesn't match output type from XSL
  *******************************************************************************/
 package org.eclipse.wst.xsl.launching;
 
@@ -35,11 +36,27 @@
 	 */
 	public static IPath defaultOutputFileForInputFile(String inputFileExpression)
 			throws CoreException {
+		return defaultOutputFileForInputFile(inputFileExpression, "xml"); //$NON-NLS-1$
+	}
+
+	/**
+	 * Creates a default Output File for the given input file string.
+	 * 
+	 * @return Returns an IPath for the Output File.
+	 * @since 1.0
+	 */
+	public static IPath defaultOutputFileForInputFile(String inputFileExpression, String method)
+			throws CoreException {
 		String file = VariablesPlugin.getDefault().getStringVariableManager()
 				.performStringSubstitution(inputFileExpression);
 		IPath inputFilePath = new Path(file);
 		inputFilePath = inputFilePath.removeFileExtension();
-		inputFilePath = inputFilePath.addFileExtension("out.xml"); //$NON-NLS-1$
+		String extension = "xml"; //$NON-NLS-1$
+		if ("text".equals(method)) extension = "txt";  //$NON-NLS-1$//$NON-NLS-2$
+		else if ("html".equals(method)) extension = "html"; //$NON-NLS-1$ //$NON-NLS-2$
+		else if ("xhtml".equals(method)) extension = "xhtml"; //$NON-NLS-1$ //$NON-NLS-2$
+		
+		inputFilePath = inputFilePath.addFileExtension("out." + extension); //$NON-NLS-1$
 		return inputFilePath;
 	}
 
diff --git a/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/config/BaseLaunchHelper.java b/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/config/BaseLaunchHelper.java
index 8c2eb6e..73b9ab7 100644
--- a/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/config/BaseLaunchHelper.java
+++ b/bundles/org.eclipse.wst.xsl.launching/src/org/eclipse/wst/xsl/launching/config/BaseLaunchHelper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007 Chase Technology Ltd - http://www.chasetechnology.co.uk
+ * Copyright (c) 2007, 2013 Chase Technology Ltd - http://www.chasetechnology.co.uk
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     Doug Satchwell (Chase Technology Ltd) - initial API and implementation
+ *     Jesper S Moller - 405223 - Processing and file name/type doesn't match output type from XSL
  *******************************************************************************/
 package org.eclipse.wst.xsl.launching.config;
 
@@ -137,6 +138,10 @@
 	public static File hydrateOutputFile(ILaunchConfiguration configuration)
 			throws CoreException {
 		IPath outputFile = null;
+		
+		String method = configuration.getAttribute(
+				XSLLaunchConfigurationConstants.ATTR_DEFAULT_OUTPUT_METHOD, "xml"); //$NON-NLS-1$
+
 		boolean useDefaultOutputFile = configuration.getAttribute(
 				XSLLaunchConfigurationConstants.ATTR_USE_DEFAULT_OUTPUT_FILE,
 				true);
@@ -153,7 +158,7 @@
 			outputFile = XSLTRuntime
 					.defaultOutputFileForInputFile(configuration.getAttribute(
 							XSLLaunchConfigurationConstants.ATTR_INPUT_FILE,
-							(String) null));
+							(String) null), method);
 		}
 		return outputFile.toFile();
 	}