[286659] Implement "Quick Outline" for the XML editor
diff --git a/bundles/org.eclipse.jst.jsp.ui/plugin.xml b/bundles/org.eclipse.jst.jsp.ui/plugin.xml
index 54ccc98..3d36dcc 100644
--- a/bundles/org.eclipse.jst.jsp.ui/plugin.xml
+++ b/bundles/org.eclipse.jst.jsp.ui/plugin.xml
@@ -35,6 +35,9 @@
 		<contentOutlineConfiguration
 			class="org.eclipse.jst.jsp.ui.views.contentoutline.JSPContentOutlineConfiguration"
 			target="org.eclipse.jst.jsp.core.jspsource" />
+		<quickOutlineConfiguration
+			class="org.eclipse.wst.xml.ui.internal.quickoutline.XMLQuickOutlineConfiguration"
+			target="org.eclipse.jst.jsp.core.jspsource" />
 		<propertySheetConfiguration
 			class="org.eclipse.wst.xml.ui.views.properties.XMLPropertySheetConfiguration"
 			target="org.eclipse.jst.jsp.core.jspsource" />
diff --git a/bundles/org.eclipse.wst.css.ui/plugin.xml b/bundles/org.eclipse.wst.css.ui/plugin.xml
index 5687c12..959218d 100644
--- a/bundles/org.eclipse.wst.css.ui/plugin.xml
+++ b/bundles/org.eclipse.wst.css.ui/plugin.xml
@@ -19,6 +19,9 @@
 		<contentOutlineConfiguration
 			class="org.eclipse.wst.css.ui.views.contentoutline.CSSContentOutlineConfiguration"
 			target="org.eclipse.wst.css.core.csssource" />
+		<quickOutlineConfiguration
+			class="org.eclipse.wst.css.ui.views.contentoutline.CSSQuickOutlineConfiguration"
+			target="org.eclipse.wst.css.core.csssource" />
 		<sourceViewerConfiguration
 			class="org.eclipse.wst.css.ui.StructuredTextViewerConfigurationCSS"
 			target="org.eclipse.wst.css.core.csssource" />
diff --git a/bundles/org.eclipse.wst.css.ui/src/org/eclipse/wst/css/ui/views/contentoutline/CSSContentSelectionProvider.java b/bundles/org.eclipse.wst.css.ui/src/org/eclipse/wst/css/ui/views/contentoutline/CSSContentSelectionProvider.java
new file mode 100644
index 0000000..d7f0be7
--- /dev/null
+++ b/bundles/org.eclipse.wst.css.ui/src/org/eclipse/wst/css/ui/views/contentoutline/CSSContentSelectionProvider.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.css.ui.views.contentoutline;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSPrimitiveValue;
+import org.eclipse.wst.sse.ui.IContentSelectionProvider;
+
+class CSSContentSelectionProvider implements IContentSelectionProvider {
+
+	public ISelection getSelection(TreeViewer viewer, ISelection selection) {
+		ISelection filteredSelection = selection;
+		if (selection instanceof IStructuredSelection) {
+			Object[] filteredNodes = getFilteredNodes(((IStructuredSelection) selection).toArray());
+			filteredSelection = new StructuredSelection(filteredNodes);
+		}
+		return filteredSelection;
+	}
+
+	private Object[] getFilteredNodes(Object[] filteredNodes) {
+		for (int i = 0; i < filteredNodes.length; i++) {
+			filteredNodes[i] = getFilteredNode(filteredNodes[i]);
+		}
+		return filteredNodes;
+	}
+
+	private Object getFilteredNode(Object object) {
+		// If the selection is a primitive value, get the property that contains it */
+		if (object instanceof ICSSPrimitiveValue) {
+			ICSSPrimitiveValue value = (ICSSPrimitiveValue) object;
+			object = value.getParentNode();
+		}
+		return object;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.css.ui/src/org/eclipse/wst/css/ui/views/contentoutline/CSSQuickOutlineConfiguration.java b/bundles/org.eclipse.wst.css.ui/src/org/eclipse/wst/css/ui/views/contentoutline/CSSQuickOutlineConfiguration.java
new file mode 100644
index 0000000..d226166
--- /dev/null
+++ b/bundles/org.eclipse.wst.css.ui/src/org/eclipse/wst/css/ui/views/contentoutline/CSSQuickOutlineConfiguration.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.css.ui.views.contentoutline;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.wst.sse.ui.IContentSelectionProvider;
+import org.eclipse.wst.sse.ui.quickoutline.AbstractQuickOutlineConfiguration;
+
+public class CSSQuickOutlineConfiguration extends AbstractQuickOutlineConfiguration {
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.quickoutline.AbstractQuickOutlineConfiguration#getContentProvider()
+	 */
+	public ITreeContentProvider getContentProvider() {
+		return new JFaceNodeContentProviderCSS();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.quickoutline.AbstractQuickOutlineConfiguration#getContentSelectionProvider()
+	 */
+	public IContentSelectionProvider getContentSelectionProvider() {
+		return new CSSContentSelectionProvider();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.quickoutline.AbstractQuickOutlineConfiguration#getLabelProvider()
+	 */
+	public ILabelProvider getLabelProvider() {
+		return new JFaceNodeLabelProviderCSS();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/plugin.xml b/bundles/org.eclipse.wst.html.ui/plugin.xml
index 4411ce3..2f06c98 100644
--- a/bundles/org.eclipse.wst.html.ui/plugin.xml
+++ b/bundles/org.eclipse.wst.html.ui/plugin.xml
@@ -23,6 +23,9 @@
 		<contentOutlineConfiguration
 			class="org.eclipse.wst.html.ui.views.contentoutline.HTMLContentOutlineConfiguration"
 			target="org.eclipse.wst.html.core.htmlsource" />
+		<quickOutlineConfiguration
+			class="org.eclipse.wst.xml.ui.internal.quickoutline.XMLQuickOutlineConfiguration"
+			target="org.eclipse.wst.html.core.htmlsource"/>
 		<propertySheetConfiguration
 			class="org.eclipse.wst.xml.ui.views.properties.XMLPropertySheetConfiguration"
 			target="org.eclipse.wst.html.core.htmlsource" />
diff --git a/bundles/org.eclipse.wst.sse.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.sse.ui/META-INF/MANIFEST.MF
index ff12a04..a22d23b 100644
--- a/bundles/org.eclipse.wst.sse.ui/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.wst.sse.ui/META-INF/MANIFEST.MF
@@ -44,6 +44,7 @@
  org.eclipse.wst.sse.ui.internal.util;x-friends:="org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.ui",
  org.eclipse.wst.sse.ui.internal.view.events;x-friends:="org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.ui",
  org.eclipse.wst.sse.ui.preferences,
+ org.eclipse.wst.sse.ui.quickoutline,
  org.eclipse.wst.sse.ui.reconcile,
  org.eclipse.wst.sse.ui.typing,
  org.eclipse.wst.sse.ui.views.contentoutline,
diff --git a/bundles/org.eclipse.wst.sse.ui/plugin.properties b/bundles/org.eclipse.wst.sse.ui/plugin.properties
index c366dfb..8abacd0 100644
--- a/bundles/org.eclipse.wst.sse.ui/plugin.properties
+++ b/bundles/org.eclipse.wst.sse.ui/plugin.properties
@@ -56,6 +56,8 @@
 command.search.find.occurrences.name=Occurrences in File
 command.search.find.occurrences.description=Find occurrences of the selection in the file
 command.search.find.occurrences.mnemonic=O
+command.information.quick_outline.name=Quick Outline
+command.information.quick_outline.description=Show the quick outline for the editor input
 ActionDefinition.selectEnclosing.name=Select Enclosing Element
 ActionDefinition.selectEnclosing.description=Expand selection to include enclosing element
 ActionDefinition.selectNext.name=Select Next Element
diff --git a/bundles/org.eclipse.wst.sse.ui/plugin.xml b/bundles/org.eclipse.wst.sse.ui/plugin.xml
index a1578d0..991687e 100644
--- a/bundles/org.eclipse.wst.sse.ui/plugin.xml
+++ b/bundles/org.eclipse.wst.sse.ui/plugin.xml
@@ -195,6 +195,12 @@
 			categoryId="org.eclipse.ui.category.edit"
 			id="org.eclipse.wst.sse.ui.search.find.occurrences">
 		</command>
+		<command
+			name="%command.information.quick_outline.name"
+			description="%command.information.quick_outline.description"
+			categoryId="org.eclipse.ui.category.edit"
+			id="org.eclipse.wst.sse.ui.quick_outline">
+		</command>
 	</extension>
 	<!-- Keybinding scope for source editor -->
 	<extension point="org.eclipse.ui.contexts">
@@ -269,6 +275,12 @@
 			schemeId="org.eclipse.ui.defaultAcceleratorConfiguration">
 		</key>
 		<key
+			sequence="M1+O"
+			contextId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			commandId="org.eclipse.wst.sse.ui.quick_outline"
+			schemeId="org.eclipse.ui.defaultAcceleratorConfiguration">
+		</key>
+		<key
 			sequence="M1+M2+/"
 			contextId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
 			commandId="org.eclipse.wst.sse.ui.add.block.comment"
diff --git a/bundles/org.eclipse.wst.sse.ui/schema/editorconfiguration.exsd b/bundles/org.eclipse.wst.sse.ui/schema/editorconfiguration.exsd
index b059bd8..0f83484 100644
--- a/bundles/org.eclipse.wst.sse.ui/schema/editorconfiguration.exsd
+++ b/bundles/org.eclipse.wst.sse.ui/schema/editorconfiguration.exsd
@@ -2,15 +2,20 @@
 <!-- Schema file written by PDE -->
 <schema targetNamespace="org.eclipse.wst.sse.ui" xmlns="http://www.w3.org/2001/XMLSchema">
 <annotation>
-      <appinfo>
+      <appInfo>
          <meta.schema plugin="org.eclipse.wst.sse.ui" id="editorConfiguration" name="Editor Configuration"/>
-      </appinfo>
+      </appInfo>
       <documentation>
          The SSE StructuredTextEditor is intended to be as flexible as possible.  Much of its design centers around the notion of defining and redefining its behavior and appearance based on the content type of its input.  This extension point allows clients to provide an editor configuration to the StructuredTextEditor without having to subclass the editor.
       </documentation>
    </annotation>
 
    <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
       <complexType>
          <sequence>
             <element ref="sourceViewerConfiguration" minOccurs="0" maxOccurs="unbounded"/>
@@ -20,6 +25,7 @@
             <element ref="doubleClickStrategy" minOccurs="0" maxOccurs="unbounded"/>
             <element ref="provisionalConfiguration" minOccurs="0" maxOccurs="unbounded"/>
             <element ref="provisionalDefinition" minOccurs="0" maxOccurs="unbounded"/>
+            <element ref="quickOutlineConfiguration" minOccurs="0" maxOccurs="unbounded"/>
          </sequence>
          <attribute name="point" type="string" use="required">
             <annotation>
@@ -64,9 +70,9 @@
                <documentation>
                   Must subclass org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration
                </documentation>
-               <appinfo>
+               <appInfo>
                   <meta.attribute kind="java" basedOn="org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration:"/>
-               </appinfo>
+               </appInfo>
             </annotation>
          </attribute>
       </complexType>
@@ -91,9 +97,9 @@
                <documentation>
                   Must subclass org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration
                </documentation>
-               <appinfo>
+               <appInfo>
                   <meta.attribute kind="java" basedOn="org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration:"/>
-               </appinfo>
+               </appInfo>
             </annotation>
          </attribute>
       </complexType>
@@ -118,9 +124,9 @@
                <documentation>
                   Must subclass org.eclipse.wst.sse.ui.views.properties.PropertySheetConfiguration
                </documentation>
-               <appinfo>
+               <appInfo>
                   <meta.attribute kind="java" basedOn="org.eclipse.wst.sse.ui.views.properties.PropertySheetConfiguration:"/>
-               </appinfo>
+               </appInfo>
             </annotation>
          </attribute>
       </complexType>
@@ -147,9 +153,9 @@
                <documentation>
                   Must implement org.eclipse.jface.text.ITextHover
                </documentation>
-               <appinfo>
+               <appInfo>
                   <meta.attribute kind="java" basedOn=":org.eclipse.jface.text.ITextHover"/>
-               </appinfo>
+               </appInfo>
             </annotation>
          </attribute>
       </complexType>
@@ -176,9 +182,9 @@
                <documentation>
                   Must implement org.eclipse.jface.text.ITextDoubleClickStrategy
                </documentation>
-               <appinfo>
+               <appInfo>
                   <meta.attribute kind="java" basedOn=":org.eclipse.jface.text.ITextDoubleClickStrategy"/>
-               </appinfo>
+               </appInfo>
             </annotation>
          </attribute>
       </complexType>
@@ -211,9 +217,9 @@
                <documentation>
                   Implementation class for this type.
                </documentation>
-               <appinfo>
+               <appInfo>
                   <meta.attribute kind="java"/>
-               </appinfo>
+               </appInfo>
             </annotation>
          </attribute>
       </complexType>
@@ -251,19 +257,46 @@
       </complexType>
    </element>
 
+   <element name="quickOutlineConfiguration">
+      <annotation>
+         <documentation>
+            Defines the configuration to be used when displaying editor input in the Tree layout for an editor&apos;s Quick Outline.
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="target" type="string" use="required">
+            <annotation>
+               <documentation>
+                  A string defining when to use this extension, either an editor or content type id.  Multiple targets may be given as a comma delimited value.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The class that provides implementation of the quick outline configuration.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.sse.ui.AbstractQuickOutlineConfiguration:"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
    <annotation>
-      <appinfo>
+      <appInfo>
          <meta.section type="since"/>
-      </appinfo>
+      </appInfo>
       <documentation>
          1.0
       </documentation>
    </annotation>
 
    <annotation>
-      <appinfo>
+      <appInfo>
          <meta.section type="examples"/>
-      </appinfo>
+      </appInfo>
       <documentation>
          &lt;pre&gt;
    &lt;extension 
@@ -286,20 +319,19 @@
    </annotation>
 
    <annotation>
-      <appinfo>
+      <appInfo>
          <meta.section type="apiInfo"/>
-      </appinfo>
+      </appInfo>
       <documentation>
          see &lt;code&gt;org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration&lt;/code&gt;, &lt;code&gt;org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration&lt;/code&gt;, &lt;code&gt;org.eclipse.wst.sse.ui.views.properties.StructuredPropertySheetConfiguration&lt;/code&gt;.
       </documentation>
    </annotation>
 
 
-
    <annotation>
-      <appinfo>
+      <appInfo>
          <meta.section type="copyright"/>
-      </appinfo>
+      </appInfo>
       <documentation>
          Copyright (c) 2005, 2007 IBM Corporation 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 &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/IContentSelectionProvider.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/IContentSelectionProvider.java
new file mode 100644
index 0000000..84ab191
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/IContentSelectionProvider.java
@@ -0,0 +1,13 @@
+package org.eclipse.wst.sse.ui;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.TreeViewer;
+
+/**
+ * Allows contributors to redefine a selection when provided with the current
+ * selection.
+ * 
+ */
+public interface IContentSelectionProvider {
+	ISelection getSelection(TreeViewer viewer, ISelection selection);
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextEditor.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextEditor.java
index 502372a..c4b398b 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextEditor.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextEditor.java
@@ -50,6 +50,7 @@
 import org.eclipse.jface.action.Separator;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.AbstractInformationControlManager;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.DefaultInformationControl;
 import org.eclipse.jface.text.IBlockTextSelection;
@@ -70,6 +71,8 @@
 import org.eclipse.jface.text.TextSelection;
 import org.eclipse.jface.text.contentassist.ContentAssistant;
 import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.information.IInformationPresenter;
+import org.eclipse.jface.text.information.IInformationProvider;
 import org.eclipse.jface.text.information.InformationPresenter;
 import org.eclipse.jface.text.reconciler.IReconciler;
 import org.eclipse.jface.text.source.Annotation;
@@ -194,12 +197,16 @@
 import org.eclipse.wst.sse.ui.internal.provisional.extensions.ISourceEditingTextTools;
 import org.eclipse.wst.sse.ui.internal.provisional.extensions.breakpoint.NullSourceEditingTextTools;
 import org.eclipse.wst.sse.ui.internal.provisional.preferences.CommonEditorPreferenceNames;
+import org.eclipse.wst.sse.ui.internal.quickoutline.QuickOutlineHandler;
+import org.eclipse.wst.sse.ui.internal.quickoutline.QuickOutlinePopupDialog;
 import org.eclipse.wst.sse.ui.internal.reconcile.DocumentRegionProcessor;
 import org.eclipse.wst.sse.ui.internal.selection.SelectionHistory;
 import org.eclipse.wst.sse.ui.internal.style.SemanticHighlightingManager;
 import org.eclipse.wst.sse.ui.internal.text.DocumentRegionEdgeMatcher;
+import org.eclipse.wst.sse.ui.internal.text.SourceInfoProvider;
 import org.eclipse.wst.sse.ui.internal.util.Assert;
 import org.eclipse.wst.sse.ui.internal.util.EditorUtility;
+import org.eclipse.wst.sse.ui.quickoutline.AbstractQuickOutlineConfiguration;
 import org.eclipse.wst.sse.ui.reconcile.ISourceReconcilingListener;
 import org.eclipse.wst.sse.ui.typing.AbstractCharacterPairInserter;
 import org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration;
@@ -1036,6 +1043,8 @@
 	/** The information presenter. */
 	private InformationPresenter fInformationPresenter;
 	private boolean fUpdateMenuTextPending;
+	/** The quick outline handler */
+	private QuickOutlineHandler fOutlineHandler;
 
 	private boolean shouldClose = false;
 	private long startPerfTime;
@@ -1355,9 +1364,13 @@
 		computeAndSetDoubleClickAction();
 		
 		IHandler handler = new GotoMatchingBracketHandler();
-    IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class);
-    if (handlerService != null)
-      handlerService.activateHandler(ActionDefinitionIds.GOTO_MATCHING_BRACKET, handler);
+	    IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class);
+	    if (handlerService != null)
+	      handlerService.activateHandler(ActionDefinitionIds.GOTO_MATCHING_BRACKET, handler);
+	    if (handlerService != null) {
+	    	fOutlineHandler = new QuickOutlineHandler();
+	    	handlerService.activateHandler(ActionDefinitionIds.SHOW_OUTLINE, fOutlineHandler);
+	    }
 
 		fShowPropertiesAction = new ShowPropertiesAction(getEditorPart(), getSelectionProvider());
 		fFoldingGroup = new FoldingActionGroup(this, getSourceViewer());
@@ -1463,7 +1476,11 @@
 		fPartListener = new PartListener(this);
 		getSite().getWorkbenchWindow().getPartService().addPartListener(fPartListener);
 		installSemanticHighlighting();
-
+		IInformationPresenter presenter = configureOutlinePresenter(getSourceViewer(), getSourceViewerConfiguration());
+		if (presenter != null) {
+			presenter.install(getSourceViewer());
+			fOutlineHandler.configure(presenter);
+		}
 		installCharacterPairing();
 		ISourceViewer viewer = getSourceViewer();
 		if (viewer instanceof ITextViewerExtension)
@@ -1641,6 +1658,9 @@
 			fInformationPresenter = null;
 		}
 
+		if (fOutlineHandler != null) {
+			fOutlineHandler.dispose();
+		}
 		// dispose of selection history
 		if (fSelectionHistory != null) {
 			fSelectionHistory.dispose();
@@ -3518,4 +3538,45 @@
 			fSemanticManager = null;
 		}
 	}
+
+	private IInformationPresenter configureOutlinePresenter(ISourceViewer sourceViewer, SourceViewerConfiguration config) {
+		InformationPresenter presenter = null;
+
+		// Get the quick outline configuration
+		AbstractQuickOutlineConfiguration cfg = null;
+		ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
+		String[] ids = getConfigurationPoints();
+		for (int i = 0; cfg == null && i < ids.length; i++) {
+			cfg = (AbstractQuickOutlineConfiguration) builder.getConfiguration(ExtendedConfigurationBuilder.QUICKOUTLINECONFIGURATION, ids[i]);
+		}
+
+		if (cfg != null) {
+			presenter = new InformationPresenter(getOutlinePresenterControlCreator(cfg));
+			presenter.setDocumentPartitioning(config.getConfiguredDocumentPartitioning(sourceViewer));
+			presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
+			IInformationProvider provider = new SourceInfoProvider(this);
+			String[] contentTypes = config.getConfiguredContentTypes(sourceViewer);
+			for (int i = 0; i < contentTypes.length; i++) {
+				presenter.setInformationProvider(provider, contentTypes[i]);
+			}
+			presenter.setSizeConstraints(50, 20, true, false);
+		}
+		return presenter;
+	}
+
+	/**
+	 * Returns the outline presenter control creator. The creator is a 
+	 * factory creating outline presenter controls for the given source viewer. 
+	 *
+	 * @param sourceViewer the source viewer to be configured by this configuration
+	 * @return an information control creator
+	 */
+	private IInformationControlCreator getOutlinePresenterControlCreator(final AbstractQuickOutlineConfiguration config) {
+		return new IInformationControlCreator() {
+			public IInformationControl createInformationControl(Shell parent) {
+				int shellStyle = SWT.RESIZE;
+				return new QuickOutlinePopupDialog(parent, shellStyle, getInternalModel(), config);
+			}
+		};
+	}
 }
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/ExtendedConfigurationBuilder.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/ExtendedConfigurationBuilder.java
index 7aaa739..8ec6fa8 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/ExtendedConfigurationBuilder.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/ExtendedConfigurationBuilder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * Copyright (c) 2001, 2010 IBM Corporation 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
@@ -66,6 +66,11 @@
 	 * strategy
 	 */
 	public static final String DOUBLECLICKSTRATEGY = "doubleClickStrategy"; //$NON-NLS-1$
+	/**
+	 * Extension type to pass into getConfigurations to get quick outline
+	 * configuration
+	 */
+	public static final String QUICKOUTLINECONFIGURATION = "quickOutlineConfiguration"; //$NON-NLS-1$
 
 	private static final String ATT_CLASS = "class"; //$NON-NLS-1$
 	private static final String ATT_TARGET = "target"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/actions/ActionDefinitionIds.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/actions/ActionDefinitionIds.java
index a745d5c..ae26969 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/actions/ActionDefinitionIds.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/actions/ActionDefinitionIds.java
@@ -51,6 +51,7 @@
 	public final static String TOGGLE_COMMENT = "org.eclipse.wst.sse.ui.toggle.comment";//$NON-NLS-1$
 	public final static String TOGGLE_BREAKPOINTS = "org.eclipse.wst.sse.ui.breakpoints.toggle";//$NON-NLS-1$
 	public final static String UNCOMMENT = "org.eclipse.wst.sse.ui.uncomment";//$NON-NLS-1$
+	public final static String SHOW_OUTLINE = "org.eclipse.wst.sse.ui.quick_outline";//$NON-NLS-1$
 
 	// registered command IDs, so we pick up the declared key bindings
 	public static final String GOTO_MATCHING_BRACKET= "org.eclipse.wst.sse.ui.goto.matching.bracket"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/actions/StructuredTextEditorActionConstants.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/actions/StructuredTextEditorActionConstants.java
index c943cc1..286d8cc 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/actions/StructuredTextEditorActionConstants.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/actions/StructuredTextEditorActionConstants.java
@@ -33,6 +33,7 @@
 	public final static String ACTION_NAME_TOGGLE_COMMENT = "ToggleComment";//$NON-NLS-1$
 	public final static String ACTION_NAME_UNCOMMENT = "Uncomment";//$NON-NLS-1$
 	public final static String ACTION_NAME_GOTO_MATCHING_BRACKET = "GotoMatchingBracket";//$NON-NLS-1$
+	public final static String ACTION_NAME_SHOW_OUTLINE = "ShowQuickOutline"; //$NON-NLS-1$
 
 	/**
 	 * @deprecated use UNDERSCORE instead
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/quickoutline/QuickOutlineHandler.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/quickoutline/QuickOutlineHandler.java
new file mode 100644
index 0000000..1fa7e13
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/quickoutline/QuickOutlineHandler.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.quickoutline;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.text.information.IInformationPresenter;
+
+public class QuickOutlineHandler extends AbstractHandler {
+
+	IInformationPresenter fPresenter;
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+	 */
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		if (fPresenter != null)
+			fPresenter.showInformation();
+		return null;
+	}
+
+	public void configure(IInformationPresenter presenter) {
+		fPresenter = presenter;
+	}
+
+	public void dispose() {
+		super.dispose();
+		if (fPresenter != null) {
+			fPresenter.uninstall();
+			fPresenter = null;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/quickoutline/QuickOutlinePopupDialog.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/quickoutline/QuickOutlinePopupDialog.java
new file mode 100644
index 0000000..1420af0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/quickoutline/QuickOutlinePopupDialog.java
@@ -0,0 +1,393 @@
+package org.eclipse.wst.sse.ui.internal.quickoutline;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.PopupDialog;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlExtension;
+import org.eclipse.jface.text.IInformationControlExtension2;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.ui.IContentSelectionProvider;
+import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
+import org.eclipse.wst.sse.ui.quickoutline.AbstractQuickOutlineConfiguration;
+
+/**
+ * Popup dialog that contains the filtering input and the outline
+ * view of the editor's input.
+ * 
+ * <p>
+ * Based on {@link org.eclipse.jdt.internal.ui.text.AbstractInformationControl}
+ * </p>
+ * 
+ */
+public class QuickOutlinePopupDialog extends PopupDialog implements IInformationControl, IInformationControlExtension, IInformationControlExtension2, DisposeListener {
+
+	/** Section used for storing the dialog's size and position settings */
+	private static final String DIALOG_SECTION = "org.eclipse.wst.sse.ui.quick_outline"; //$NON-NLS-1$
+
+	/** Text field for entering filter patterns */
+	private Text fFilterText;
+
+	/** Tree for presenting the information outline */
+	private TreeViewer fTreeViewer;
+
+	/** The model to be outlined */
+	private IStructuredModel fModel;
+
+	private ILabelProvider fLabelProvider;
+	private ITreeContentProvider fContentProvider;
+
+	private IContentSelectionProvider fSelectionProvider;
+
+	private StringPatternFilter fFilter;
+	
+	public QuickOutlinePopupDialog(Shell parent, int shellStyle, IStructuredModel model, AbstractQuickOutlineConfiguration configuration) {
+		super(parent, shellStyle, true, true, true, true, true, null, null);
+		fContentProvider = configuration.getContentProvider();
+		fLabelProvider = configuration.getLabelProvider();
+		fSelectionProvider = configuration.getContentSelectionProvider();
+		fModel = model;
+		create();
+	}
+
+	protected Control createDialogArea(Composite parent) {
+		createTreeViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL);
+		addListeners(fTreeViewer.getTree());
+
+		installFilter();
+		return fTreeViewer.getControl();
+	}
+
+	protected Control createTitleControl(Composite parent) {
+		createFilterText(parent);
+
+		return fFilterText;
+	}
+
+	protected void createTreeViewer(Composite parent, int style) {
+		Tree tree = new Tree(parent, style);
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.heightHint = tree.getItemHeight() * 12;
+		tree.setLayoutData(gd);
+
+		fTreeViewer = new TreeViewer(tree);
+		fTreeViewer.setContentProvider(fContentProvider);
+		fTreeViewer.setLabelProvider(fLabelProvider);
+		fTreeViewer.setAutoExpandLevel(2);
+		fTreeViewer.setUseHashlookup(true);
+		fTreeViewer.setInput(fModel);
+	}
+
+	protected void createFilterText(Composite parent) {
+		fFilterText = new Text(parent, SWT.NONE);
+		Dialog.applyDialogFont(fFilterText);
+
+		GridData data= new GridData(GridData.FILL_HORIZONTAL);
+		data.horizontalAlignment= GridData.FILL;
+		data.verticalAlignment= GridData.CENTER;
+		fFilterText.setLayoutData(data);
+		fFilterText.addKeyListener(new KeyListener() {
+			public void keyPressed(KeyEvent e) {
+				if (e.keyCode == 0x0D) // return
+					gotoSelectedElement();
+				if (e.keyCode == SWT.ARROW_DOWN)
+					fTreeViewer.getTree().setFocus();
+				if (e.keyCode == SWT.ARROW_UP)
+					fTreeViewer.getTree().setFocus();
+				if (e.character == 0x1B) // ESC
+					dispose();
+			}
+			public void keyReleased(KeyEvent e) {
+				// do nothing
+			}
+		});
+	}
+
+	protected void installFilter() {
+		fFilter = new StringPatternFilter();
+		fTreeViewer.addFilter(fFilter);
+		fFilterText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				String text = ((Text) e.widget).getText();
+				int length = text.length();
+				if (length > 0 && text.charAt(length -1 ) != '*') {
+					text = text + '*';
+				}
+				fFilter.updatePattern(text);
+				stringMatcherUpdated();
+			}
+		});
+	}
+
+	/**
+	 * The string matcher has been modified. The default implementation
+	 * refreshes the view and selects the first matched element
+	 */
+	protected void stringMatcherUpdated() {
+		// refresh viewer to re-filter
+		fTreeViewer.getControl().setRedraw(false);
+		fTreeViewer.refresh();
+		fTreeViewer.expandAll();
+		if (fTreeViewer.getTree().getItemCount() > 0)
+			fTreeViewer.getTree().setSelection(fTreeViewer.getTree().getItem(0));
+		fTreeViewer.getControl().setRedraw(true);
+	}
+
+	protected IDialogSettings getDialogSettings() {
+		IDialogSettings settings= SSEUIPlugin.getDefault().getDialogSettings().getSection(DIALOG_SECTION);
+		if (settings == null)
+			settings = SSEUIPlugin.getDefault().getDialogSettings().addNewSection(DIALOG_SECTION);
+
+		return settings;
+	}
+
+	private void gotoSelectedElement() {
+		Object element = getSelectedElement();
+		dispose();
+		ITextEditor editor = getActiveTextEditor();
+		if (editor != null) {
+			editor.selectAndReveal(((IndexedRegion) element).getStartOffset(), ((IndexedRegion) element).getEndOffset() - ((IndexedRegion) element).getStartOffset());
+		}
+	}
+
+	private ITextEditor getActiveTextEditor() {
+		IWorkbench wb = PlatformUI.getWorkbench();
+		ITextEditor editor = null;
+		if (wb != null) {
+			IWorkbenchWindow ww = wb.getActiveWorkbenchWindow();
+			IWorkbenchPage page = ww.getActivePage();
+			if (page != null) {
+				IEditorPart part = page.getActiveEditor();
+				if (part instanceof ITextEditor)
+					editor = (ITextEditor) part;
+				else
+					editor = part != null ? (ITextEditor) part.getAdapter(ITextEditor.class) : null;
+			}
+		}
+		return editor;
+	}
+
+	private Object getSelectedElement() {
+		if (fTreeViewer == null)
+			return null;
+
+		return ((IStructuredSelection) fTreeViewer.getSelection()).getFirstElement();
+	}
+
+	private void addListeners(final Tree tree) {
+		tree.addKeyListener(new KeyListener() {
+			public void keyPressed(KeyEvent e)  {
+				if (e.character == 0x1B) // ESC
+					dispose();
+			}
+			public void keyReleased(KeyEvent e) {
+				// do nothing
+			}
+		});
+
+		tree.addSelectionListener(new SelectionListener() {
+			public void widgetSelected(SelectionEvent e) {
+				// do nothing
+			}
+			public void widgetDefaultSelected(SelectionEvent e) {
+				gotoSelectedElement();
+			}
+		});
+
+		/* Mouse hover */
+		tree.addMouseMoveListener(new MouseMoveListener()	 {
+			TreeItem fLastItem= null;
+			public void mouseMove(MouseEvent e) {
+				if (tree.equals(e.getSource())) {
+					Object o= tree.getItem(new Point(e.x, e.y));
+					if (o instanceof TreeItem) {
+						Rectangle clientArea = tree.getClientArea();
+						if (!o.equals(fLastItem)) {
+							fLastItem= (TreeItem)o;
+							tree.setSelection(new TreeItem[] { fLastItem });
+						} else if (e.y - clientArea.y < tree.getItemHeight() / 4) {
+							// Scroll up
+							Point p= tree.toDisplay(e.x, e.y);
+							Item item= fTreeViewer.scrollUp(p.x, p.y);
+							if (item instanceof TreeItem) {
+								fLastItem= (TreeItem)item;
+								tree.setSelection(new TreeItem[] { fLastItem });
+							}
+						} else if (clientArea.y + clientArea.height - e.y < tree.getItemHeight() / 4) {
+							// Scroll down
+							Point p= tree.toDisplay(e.x, e.y);
+							Item item= fTreeViewer.scrollDown(p.x, p.y);
+							if (item instanceof TreeItem) {
+								fLastItem= (TreeItem)item;
+								tree.setSelection(new TreeItem[] { fLastItem });
+							}
+						}
+					}
+				}
+			}
+		});
+
+		tree.addMouseListener(new MouseAdapter() {
+			public void mouseUp(MouseEvent e) {
+
+				if (tree.getSelectionCount() < 1)
+					return;
+
+				if (e.button != 1)
+					return;
+
+				if (tree.equals(e.getSource())) {
+					Object o= tree.getItem(new Point(e.x, e.y));
+					TreeItem selection= tree.getSelection()[0];
+					if (selection.equals(o))
+						gotoSelectedElement();
+				}
+			}
+		});
+	}
+	public void addDisposeListener(DisposeListener listener) {
+		getShell().addDisposeListener(listener);
+	}
+
+	public void addFocusListener(FocusListener listener) {
+		getShell().addFocusListener(listener);
+	}
+
+	public Point computeSizeHint() {
+		return getShell().getSize();
+	}
+
+	public void dispose() {
+		close();
+	}
+
+	public boolean isFocusControl() {
+		return getShell().getDisplay().getActiveShell() == getShell();
+	}
+
+	public void removeDisposeListener(DisposeListener listener) {
+		getShell().removeDisposeListener(listener);
+	}
+
+	public void removeFocusListener(FocusListener listener) {
+		getShell().removeFocusListener(listener);
+	}
+
+	public void setBackgroundColor(Color background) {
+		applyBackgroundColor(background, getContents());
+	}
+
+	public void setFocus() {
+		getShell().forceFocus();
+		fFilterText.setFocus();
+	}
+
+	public void setForegroundColor(Color foreground) {
+		applyForegroundColor(foreground, getContents());
+	}
+
+	public void setInformation(String information) {
+		// nothing to do
+	}
+
+	public void setLocation(Point location) {
+		/*
+		 * If the location is persisted, it gets managed by PopupDialog - fine. Otherwise, the location is
+		 * computed in Window#getInitialLocation, which will center it in the parent shell / main
+		 * monitor, which is wrong for two reasons:
+		 * - we want to center over the editor / subject control, not the parent shell
+		 * - the center is computed via the initalSize, which may be also wrong since the size may
+		 *   have been updated since via min/max sizing of AbstractInformationControlManager.
+		 * In that case, override the location with the one computed by the manager. Note that
+		 * the call to constrainShellSize in PopupDialog.open will still ensure that the shell is
+		 * entirely visible.
+		 */
+		if (!getPersistLocation() || getDialogSettings() == null)
+			getShell().setLocation(location);
+	}
+
+	public void setSize(int width, int height) {
+		getShell().setSize(width, height);
+	}
+
+	public void setSizeConstraints(int maxWidth, int maxHeight) {
+	}
+
+	public void setVisible(boolean visible) {
+		if (visible) {
+			open();
+		} else {
+			saveDialogBounds(getShell());
+			getShell().setVisible(false);
+		}
+	}
+
+	public boolean hasContents() {
+		return fTreeViewer != null && fTreeViewer.getInput() != null;
+	}
+
+	public void setInput(Object input) {
+		if (!(input instanceof ISelection)) {
+			fTreeViewer.setSelection(new StructuredSelection(input));
+		}
+		else {
+			if (fSelectionProvider != null) {
+				ISelection selection = fSelectionProvider.getSelection(fTreeViewer, (ISelection) input);
+				fTreeViewer.setSelection(selection);
+			}
+			else {
+				fTreeViewer.setSelection((ISelection) input);
+			}
+		}
+	}
+
+	public void widgetDisposed(DisposeEvent e) {
+		fTreeViewer = null;
+		fFilterText = null;
+		fModel = null;
+	}
+
+	protected void fillDialogMenu(IMenuManager dialogMenu) {
+		// Add custom actions
+		super.fillDialogMenu(dialogMenu);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/quickoutline/StringPatternFilter.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/quickoutline/StringPatternFilter.java
new file mode 100644
index 0000000..cc0a1d6
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/quickoutline/StringPatternFilter.java
@@ -0,0 +1,504 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.quickoutline;
+
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.osgi.util.TextProcessor;
+
+/**
+ * Default Viewer Filter to be used by the {@link QuickOutlinePopupDialog}
+ * <p>
+ * Based on {@link org.eclipse.jdt.internal.ui.text.AbstractInformationControl.NamePatternFilter}
+ * </p>
+ */
+public class StringPatternFilter extends ViewerFilter {
+
+	private StringMatcher fStringMatcher;
+
+	/*
+	 * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+	 */
+	public boolean select(Viewer viewer, Object parentElement, Object element) {
+		StringMatcher matcher = fStringMatcher;
+		if (matcher == null || !(viewer instanceof TreeViewer))
+			return true;
+		TreeViewer treeViewer = (TreeViewer) viewer;
+
+		String matchName = ((ILabelProvider) treeViewer.getLabelProvider()).getText(element);
+		matchName = TextProcessor.deprocess(matchName);
+		if (matchName != null && matcher.match(matchName))
+			return true;
+
+		return hasUnfilteredChild(treeViewer, element);
+	}
+
+	private boolean hasUnfilteredChild(TreeViewer viewer, Object element) {
+		Object[] children=  ((ITreeContentProvider) viewer.getContentProvider()).getChildren(element);
+		for (int i= 0; i < children.length; i++)
+			if (select(viewer, element, children[i]))
+				return true;
+		return false;
+	}
+
+	public void updatePattern(String pattern) {
+		if (pattern.length() == 0) {
+			fStringMatcher = null;
+		}
+		else {
+			fStringMatcher = new StringMatcher(pattern, pattern.toLowerCase().equals(pattern), false);
+		}
+		
+	}
+
+	/**
+	 * String matcher based on {@link org.eclipse.ui.internal.misc.StringMatcher}
+	 */
+	static class StringMatcher {
+		protected String fPattern;
+
+	    protected int fLength; // pattern length
+
+	    protected boolean fIgnoreWildCards;
+
+	    protected boolean fIgnoreCase;
+
+	    protected boolean fHasLeadingStar;
+
+	    protected boolean fHasTrailingStar;
+
+	    protected String fSegments[]; //the given pattern is split into * separated segments
+
+	    /* boundary value beyond which we don't need to search in the text */
+	    protected int fBound = 0;
+
+	    protected static final char fSingleWildCard = '\u0000';
+
+	    public static class Position {
+	        int start; //inclusive
+
+	        int end; //exclusive
+
+	        public Position(int start, int end) {
+	            this.start = start;
+	            this.end = end;
+	        }
+
+	        public int getStart() {
+	            return start;
+	        }
+
+	        public int getEnd() {
+	            return end;
+	        }
+	    }
+
+	    /**
+	     * StringMatcher constructor takes in a String object that is a simple 
+	     * pattern which may contain '*' for 0 and many characters and
+	     * '?' for exactly one character.  
+	     *
+	     * Literal '*' and '?' characters must be escaped in the pattern 
+	     * e.g., "\*" means literal "*", etc.
+	     *
+	     * Escaping any other character (including the escape character itself), 
+	     * just results in that character in the pattern.
+	     * e.g., "\a" means "a" and "\\" means "\"
+	     *
+	     * If invoking the StringMatcher with string literals in Java, don't forget
+	     * escape characters are represented by "\\".
+	     *
+	     * @param pattern the pattern to match text against
+	     * @param ignoreCase if true, case is ignored
+	     * @param ignoreWildCards if true, wild cards and their escape sequences are ignored
+	     * 		  (everything is taken literally).
+	     */
+	    public StringMatcher(String pattern, boolean ignoreCase,
+	            boolean ignoreWildCards) {
+	        if (pattern == null) {
+				throw new IllegalArgumentException();
+			}
+	        fIgnoreCase = ignoreCase;
+	        fIgnoreWildCards = ignoreWildCards;
+	        fPattern = pattern;
+	        fLength = pattern.length();
+
+	        if (fIgnoreWildCards) {
+	            parseNoWildCards();
+	        } else {
+	            parseWildCards();
+	        }
+	    }
+
+	    /**
+	     * Find the first occurrence of the pattern between <code>start</code)(inclusive) 
+	     * and <code>end</code>(exclusive).  
+	     * @param text the String object to search in 
+	     * @param start the starting index of the search range, inclusive
+	     * @param end the ending index of the search range, exclusive
+	     * @return an <code>StringMatcher.Position</code> object that keeps the starting 
+	     * (inclusive) and ending positions (exclusive) of the first occurrence of the 
+	     * pattern in the specified range of the text; return null if not found or subtext
+	     * is empty (start==end). A pair of zeros is returned if pattern is empty string
+	     * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc"
+	     * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned
+	     */
+	    public StringMatcher.Position find(String text, int start, int end) {
+	        if (text == null) {
+				throw new IllegalArgumentException();
+			}
+
+	        int tlen = text.length();
+	        if (start < 0) {
+				start = 0;
+			}
+	        if (end > tlen) {
+				end = tlen;
+			}
+	        if (end < 0 || start >= end) {
+				return null;
+			}
+	        if (fLength == 0) {
+				return new Position(start, start);
+			}
+	        if (fIgnoreWildCards) {
+	            int x = posIn(text, start, end);
+	            if (x < 0) {
+					return null;
+				}
+	            return new Position(x, x + fLength);
+	        }
+
+	        int segCount = fSegments.length;
+	        if (segCount == 0) {
+				return new Position(start, end);
+			}
+
+	        int curPos = start;
+	        int matchStart = -1;
+	        int i;
+	        for (i = 0; i < segCount && curPos < end; ++i) {
+	            String current = fSegments[i];
+	            int nextMatch = regExpPosIn(text, curPos, end, current);
+	            if (nextMatch < 0) {
+					return null;
+				}
+	            if (i == 0) {
+					matchStart = nextMatch;
+				}
+	            curPos = nextMatch + current.length();
+	        }
+	        if (i < segCount) {
+				return null;
+			}
+	        return new Position(matchStart, curPos);
+	    }
+
+	    /**
+	     * match the given <code>text</code> with the pattern 
+	     * @return true if matched otherwise false
+	     * @param text a String object 
+	     */
+	    public boolean match(String text) {
+	    	if(text == null) {
+				return false;
+			}
+	        return match(text, 0, text.length());
+	    }
+
+	    /**
+	     * Given the starting (inclusive) and the ending (exclusive) positions in the   
+	     * <code>text</code>, determine if the given substring matches with aPattern  
+	     * @return true if the specified portion of the text matches the pattern
+	     * @param text a String object that contains the substring to match 
+	     * @param start marks the starting position (inclusive) of the substring
+	     * @param end marks the ending index (exclusive) of the substring 
+	     */
+	    public boolean match(String text, int start, int end) {
+	        if (null == text) {
+				throw new IllegalArgumentException();
+			}
+
+	        if (start > end) {
+				return false;
+			}
+
+	        if (fIgnoreWildCards) {
+				return (end - start == fLength)
+	                    && fPattern.regionMatches(fIgnoreCase, 0, text, start,
+	                            fLength);
+			}
+	        int segCount = fSegments.length;
+	        if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar)) {
+				return true;
+			}
+	        if (start == end) {
+				return fLength == 0;
+			}
+	        if (fLength == 0) {
+				return start == end;
+			}
+
+	        int tlen = text.length();
+	        if (start < 0) {
+				start = 0;
+			}
+	        if (end > tlen) {
+				end = tlen;
+			}
+
+	        int tCurPos = start;
+	        int bound = end - fBound;
+	        if (bound < 0) {
+				return false;
+			}
+	        int i = 0;
+	        String current = fSegments[i];
+	        int segLength = current.length();
+
+	        /* process first segment */
+	        if (!fHasLeadingStar) {
+	            if (!regExpRegionMatches(text, start, current, 0, segLength)) {
+	                return false;
+	            } else {
+	                ++i;
+	                tCurPos = tCurPos + segLength;
+	            }
+	        }
+	        if ((fSegments.length == 1) && (!fHasLeadingStar)
+	                && (!fHasTrailingStar)) {
+	            // only one segment to match, no wildcards specified
+	            return tCurPos == end;
+	        }
+	        /* process middle segments */
+	        while (i < segCount) {
+	            current = fSegments[i];
+	            int currentMatch;
+	            int k = current.indexOf(fSingleWildCard);
+	            if (k < 0) {
+	                currentMatch = textPosIn(text, tCurPos, end, current);
+	                if (currentMatch < 0) {
+						return false;
+					}
+	            } else {
+	                currentMatch = regExpPosIn(text, tCurPos, end, current);
+	                if (currentMatch < 0) {
+						return false;
+					}
+	            }
+	            tCurPos = currentMatch + current.length();
+	            i++;
+	        }
+
+	        /* process final segment */
+	        if (!fHasTrailingStar && tCurPos != end) {
+	            int clen = current.length();
+	            return regExpRegionMatches(text, end - clen, current, 0, clen);
+	        }
+	        return i == segCount;
+	    }
+
+	    /**
+	     * This method parses the given pattern into segments seperated by wildcard '*' characters.
+	     * Since wildcards are not being used in this case, the pattern consists of a single segment.
+	     */
+	    private void parseNoWildCards() {
+	        fSegments = new String[1];
+	        fSegments[0] = fPattern;
+	        fBound = fLength;
+	    }
+
+	    /**
+	     * Parses the given pattern into segments seperated by wildcard '*' characters.
+	     * @param p, a String object that is a simple regular expression with '*' and/or '?'
+	     */
+	    private void parseWildCards() {
+	        if (fPattern.startsWith("*")) { //$NON-NLS-1$
+				fHasLeadingStar = true;
+			}
+	        if (fPattern.endsWith("*")) {//$NON-NLS-1$
+	            /* make sure it's not an escaped wildcard */
+	            if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') {
+	                fHasTrailingStar = true;
+	            }
+	        }
+
+	        Vector temp = new Vector();
+
+	        int pos = 0;
+	        StringBuffer buf = new StringBuffer();
+	        while (pos < fLength) {
+	            char c = fPattern.charAt(pos++);
+	            switch (c) {
+	            case '\\':
+	                if (pos >= fLength) {
+	                    buf.append(c);
+	                } else {
+	                    char next = fPattern.charAt(pos++);
+	                    /* if it's an escape sequence */
+	                    if (next == '*' || next == '?' || next == '\\') {
+	                        buf.append(next);
+	                    } else {
+	                        /* not an escape sequence, just insert literally */
+	                        buf.append(c);
+	                        buf.append(next);
+	                    }
+	                }
+	                break;
+	            case '*':
+	                if (buf.length() > 0) {
+	                    /* new segment */
+	                    temp.addElement(buf.toString());
+	                    fBound += buf.length();
+	                    buf.setLength(0);
+	                }
+	                break;
+	            case '?':
+	                /* append special character representing single match wildcard */
+	                buf.append(fSingleWildCard);
+	                break;
+	            default:
+	                buf.append(c);
+	            }
+	        }
+
+	        /* add last buffer to segment list */
+	        if (buf.length() > 0) {
+	            temp.addElement(buf.toString());
+	            fBound += buf.length();
+	        }
+
+	        fSegments = new String[temp.size()];
+	        temp.copyInto(fSegments);
+	    }
+
+	    /** 
+	     * @param text a string which contains no wildcard
+	     * @param start the starting index in the text for search, inclusive
+	     * @param end the stopping point of search, exclusive
+	     * @return the starting index in the text of the pattern , or -1 if not found 
+	     */
+	    protected int posIn(String text, int start, int end) {//no wild card in pattern
+	        int max = end - fLength;
+
+	        if (!fIgnoreCase) {
+	            int i = text.indexOf(fPattern, start);
+	            if (i == -1 || i > max) {
+					return -1;
+				}
+	            return i;
+	        }
+
+	        for (int i = start; i <= max; ++i) {
+	            if (text.regionMatches(true, i, fPattern, 0, fLength)) {
+					return i;
+				}
+	        }
+
+	        return -1;
+	    }
+
+	    /** 
+	     * @param text a simple regular expression that may only contain '?'(s)
+	     * @param start the starting index in the text for search, inclusive
+	     * @param end the stopping point of search, exclusive
+	     * @param p a simple regular expression that may contains '?'
+	     * @return the starting index in the text of the pattern , or -1 if not found 
+	     */
+	    protected int regExpPosIn(String text, int start, int end, String p) {
+	        int plen = p.length();
+
+	        int max = end - plen;
+	        for (int i = start; i <= max; ++i) {
+	            if (regExpRegionMatches(text, i, p, 0, plen)) {
+					return i;
+				}
+	        }
+	        return -1;
+	    }
+
+	    /**
+	     * 
+	     * @return boolean
+	     * @param text a String to match
+	     * @param start int that indicates the starting index of match, inclusive
+	     * @param end</code> int that indicates the ending index of match, exclusive
+	     * @param p String,  String, a simple regular expression that may contain '?'
+	     * @param ignoreCase boolean indicating wether code>p</code> is case sensitive
+	     */
+	    protected boolean regExpRegionMatches(String text, int tStart, String p,
+	            int pStart, int plen) {
+	        while (plen-- > 0) {
+	            char tchar = text.charAt(tStart++);
+	            char pchar = p.charAt(pStart++);
+
+	            /* process wild cards */
+	            if (!fIgnoreWildCards) {
+	                /* skip single wild cards */
+	                if (pchar == fSingleWildCard) {
+	                    continue;
+	                }
+	            }
+	            if (pchar == tchar) {
+					continue;
+				}
+	            if (fIgnoreCase) {
+	                if (Character.toUpperCase(tchar) == Character
+	                        .toUpperCase(pchar)) {
+						continue;
+					}
+	                // comparing after converting to upper case doesn't handle all cases;
+	                // also compare after converting to lower case
+	                if (Character.toLowerCase(tchar) == Character
+	                        .toLowerCase(pchar)) {
+						continue;
+					}
+	            }
+	            return false;
+	        }
+	        return true;
+	    }
+
+	    /** 
+	     * @param text the string to match
+	     * @param start the starting index in the text for search, inclusive
+	     * @param end the stopping point of search, exclusive
+	     * @param p a pattern string that has no wildcard
+	     * @return the starting index in the text of the pattern , or -1 if not found 
+	     */
+	    protected int textPosIn(String text, int start, int end, String p) {
+
+	        int plen = p.length();
+	        int max = end - plen;
+
+	        if (!fIgnoreCase) {
+	            int i = text.indexOf(p, start);
+	            if (i == -1 || i > max) {
+					return -1;
+				}
+	            return i;
+	        }
+
+	        for (int i = start; i <= max; ++i) {
+	            if (text.regionMatches(true, i, p, 0, plen)) {
+					return i;
+				}
+	        }
+
+	        return -1;
+	    }
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/text/SourceInfoProvider.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/text/SourceInfoProvider.java
new file mode 100644
index 0000000..a905445
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/text/SourceInfoProvider.java
@@ -0,0 +1,42 @@
+package org.eclipse.wst.sse.ui.internal.text;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.IInformationProviderExtension;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+
+public class SourceInfoProvider implements IInformationProvider, IInformationProviderExtension  {
+
+	private StructuredTextEditor fEditor;
+
+	public SourceInfoProvider(StructuredTextEditor editor) {
+		fEditor = editor;
+	}
+	public String getInformation(ITextViewer textViewer, IRegion subject) {
+		return getInformation2(textViewer, subject).toString();
+	}
+
+	public IRegion getSubject(ITextViewer textViewer, int offset) {
+		if (textViewer != null && fEditor != null) {
+			IRegion region= WordFinder.findWord(textViewer.getDocument(), offset);
+			if (region != null)
+				return region;
+			else
+				return new Region(offset, 0);
+		}
+		return null;
+	}
+
+	public Object getInformation2(ITextViewer textViewer, IRegion subject) {
+		if (fEditor == null)
+			return null;
+
+		Object selection = fEditor.getSelectionProvider().getSelection();
+		if (selection == null)
+			selection = new Object();
+		return selection;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/text/WordFinder.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/text/WordFinder.java
new file mode 100644
index 0000000..4e708c5
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/text/WordFinder.java
@@ -0,0 +1,53 @@
+package org.eclipse.wst.sse.ui.internal.text;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+
+public class WordFinder {
+
+	/* Copied from org.eclipse.jdt.internal.ui.text.JavaWordFinder */
+	public static IRegion findWord(IDocument document, int offset) {
+
+		int start= -2;
+		int end= -1;
+
+		try {
+			int pos= offset;
+			char c;
+
+			while (pos >= 0) {
+				c= document.getChar(pos);
+				if (!Character.isJavaIdentifierPart(c))
+					break;
+				--pos;
+			}
+			start= pos;
+
+			pos= offset;
+			int length= document.getLength();
+
+			while (pos < length) {
+				c= document.getChar(pos);
+				if (!Character.isJavaIdentifierPart(c))
+					break;
+				++pos;
+			}
+			end= pos;
+
+		} catch (BadLocationException x) {
+		}
+
+		if (start >= -1 && end > -1) {
+			if (start == offset && end == offset)
+				return new Region(offset, 0);
+			else if (start == offset)
+				return new Region(start, end - start);
+			else
+				return new Region(start + 1, end - start - 1);
+		}
+
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/quickoutline/AbstractQuickOutlineConfiguration.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/quickoutline/AbstractQuickOutlineConfiguration.java
new file mode 100644
index 0000000..33ff2d8
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/quickoutline/AbstractQuickOutlineConfiguration.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.quickoutline;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.wst.sse.ui.IContentSelectionProvider;
+
+/**
+ * Base class that provides configuration for a quick outline.
+ *
+ */
+public abstract class AbstractQuickOutlineConfiguration {
+
+	/**
+	 * Provides the label provider to be used by the quick outline
+	 * 
+	 * @return an <code>ILabelProvider</code> to be used by the quick outline
+	 */
+	public abstract ILabelProvider getLabelProvider();
+
+	/**
+	 * Provides the content provider to be used by the quick outline
+	 * 
+	 * @return a <code>ITreeContentProvider</code> to be used when providing the content of the quick outline
+	 */
+	public abstract ITreeContentProvider getContentProvider();
+
+	/**
+	 * Provides the content selection provider to be used by the quick outline. This allows
+	 * for adjusting the selection to be displayed in the outline based on the editor's selection
+	 * 
+	 * @return an <code>IContentSelectionProvider</code> used by the quick outline. By default, returns
+	 * null indicating that the selection in the editor translates to the selection in the outline.
+	 */
+	public IContentSelectionProvider getContentSelectionProvider() {
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.xml.ui/META-INF/MANIFEST.MF
index 6f04052..a66c86f 100644
--- a/bundles/org.eclipse.wst.xml.ui/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.wst.xml.ui/META-INF/MANIFEST.MF
@@ -26,6 +26,7 @@
  org.eclipse.wst.xml.ui.internal.projection;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
  org.eclipse.wst.xml.ui.internal.properties;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
  org.eclipse.wst.xml.ui.internal.provisional;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.quickoutline,
  org.eclipse.wst.xml.ui.internal.registry;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
  org.eclipse.wst.xml.ui.internal.search;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
  org.eclipse.wst.xml.ui.internal.selection;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
diff --git a/bundles/org.eclipse.wst.xml.ui/plugin.xml b/bundles/org.eclipse.wst.xml.ui/plugin.xml
index c6dc1da..8dd2f18 100644
--- a/bundles/org.eclipse.wst.xml.ui/plugin.xml
+++ b/bundles/org.eclipse.wst.xml.ui/plugin.xml
@@ -39,6 +39,9 @@
 		<contentOutlineConfiguration
 			class="org.eclipse.wst.xml.ui.views.contentoutline.XMLContentOutlineConfiguration"
 			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<quickOutlineConfiguration
+			class="org.eclipse.wst.xml.ui.internal.quickoutline.XMLQuickOutlineConfiguration"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
 		<propertySheetConfiguration
 			class="org.eclipse.wst.xml.ui.views.properties.XMLPropertySheetConfiguration"
 			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLContentSelectionProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLContentSelectionProvider.java
new file mode 100644
index 0000000..a3c9c75
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLContentSelectionProvider.java
@@ -0,0 +1,46 @@
+package org.eclipse.wst.xml.ui.internal.quickoutline;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.wst.sse.ui.IContentSelectionProvider;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+public class XMLContentSelectionProvider implements IContentSelectionProvider {
+
+	public ISelection getSelection(TreeViewer viewer, ISelection selection) {
+		ISelection filteredSelection = selection;
+		if (selection instanceof IStructuredSelection) {
+			Object[] filteredNodes = getFilteredNodes(((IStructuredSelection) selection).toArray());
+			filteredSelection = new StructuredSelection(filteredNodes);
+		}
+		return filteredSelection;
+	}
+
+	private Object[] getFilteredNodes(Object[] filteredNodes) {
+		for (int i = 0; i < filteredNodes.length; i++) {
+			filteredNodes[i] = getFilteredNode(filteredNodes[i]);
+		}
+		return filteredNodes;
+	}
+
+	private Object getFilteredNode(Object object) {
+		if (object instanceof Node) {
+			Node node = (Node) object;
+			short nodeType = node.getNodeType();
+			// replace attribute node in selection with its parent
+			if (nodeType == Node.ATTRIBUTE_NODE) {
+				node = ((Attr) node).getOwnerElement();
+			}
+			// anything else not visible, replace with parent node
+			else if (nodeType == Node.TEXT_NODE) {
+				node = node.getParentNode();
+			}
+			return node;
+		}
+		return object;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLQuickOutlineConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLQuickOutlineConfiguration.java
new file mode 100644
index 0000000..16d21a1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLQuickOutlineConfiguration.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.quickoutline;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.wst.sse.ui.IContentSelectionProvider;
+import org.eclipse.wst.sse.ui.quickoutline.AbstractQuickOutlineConfiguration;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeContentProvider;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider;
+
+public class XMLQuickOutlineConfiguration extends AbstractQuickOutlineConfiguration {
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.IOutlineContentManager#getContentProvider()
+	 */
+	public ITreeContentProvider getContentProvider() {
+		return new JFaceNodeContentProvider();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.IOutlineContentManager#getContentSelectionProvider()
+	 */
+	public IContentSelectionProvider getContentSelectionProvider() {
+		return new XMLContentSelectionProvider();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.IOutlineContentManager#getLabelProvider()
+	 */
+	public ILabelProvider getLabelProvider() {
+		return new JFaceNodeLabelProvider();
+	}
+
+}