Part of fix for Jira issue XALANJ-2447.

The handling of exclude-result-prefixes for an xsl:stylesheet had the complete
set of excluded prefixes accumulated on the xsl:stylesheet for the main
stylesheet module.  However, the scope of the attribute is supposed to consist
only of elements that are direct descendants of an element that has the
attribute, and does not extend to imported or included stylesheets.  The same
is true of namespaces excluded because they have been declared as extension
element prefixes.

Fixed this by maintaining a stack of excluded prefixes that's pushed on entry
to the Stylesheet.parseOwnChildren method and popped on exit from the same.
The push operation clears the current set of excluded prefixes and the pop
operation restores the set of excluded prefixes that were in effect for the
importing or including stylesheet.

Reviewed by Christine Li (jycli () ca ! ibm ! com)


git-svn-id: https://svn.apache.org/repos/asf/xalan/java/trunk@669373 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/org/apache/xalan/xsltc/compiler/Stylesheet.java b/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
index b8e3dd5..7c7bda1 100644
--- a/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
+++ b/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
@@ -502,15 +502,9 @@
 	return (_extensions.get(uri) != null);
     }
 
-    public void excludeExtensionPrefixes(Parser parser) {
+    public void declareExtensionPrefixes(Parser parser) {
 	final SymbolTable stable = parser.getSymbolTable();
-    	final String excludePrefixes = getAttribute("exclude-result-prefixes");
 	final String extensionPrefixes = getAttribute("extension-element-prefixes");
-	
-	// Exclude XSLT uri 
-	stable.excludeURI(Constants.XSLT_URI);
-	stable.excludeNamespaces(excludePrefixes);
-	stable.excludeNamespaces(extensionPrefixes);
 	extensionURI(extensionPrefixes, stable);
     }
 
@@ -564,6 +558,16 @@
      * Parse all direct children of the <xsl:stylesheet/> element.
      */
     public final void parseOwnChildren(Parser parser) {
+        final SymbolTable stable = parser.getSymbolTable();
+        final String excludePrefixes = getAttribute("exclude-result-prefixes");
+        final String extensionPrefixes = getAttribute("extension-element-prefixes");
+        
+        // Exclude XSLT uri 
+        stable.pushExcludedNamespacesContext();
+        stable.excludeURI(Constants.XSLT_URI);
+        stable.excludeNamespaces(excludePrefixes);
+        stable.excludeNamespaces(extensionPrefixes);
+
 	final Vector contents = getContents();
 	final int count = contents.size();
 
@@ -595,6 +599,8 @@
 		template.setName(parser.getQName(name));
 	    }
 	}
+
+	stable.popExcludedNamespacesContext();
     }
 
     public void processModes() {
diff --git a/src/org/apache/xalan/xsltc/compiler/SymbolTable.java b/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
index 7c4ea7a..b6bdec7 100644
--- a/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
+++ b/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
@@ -22,6 +22,7 @@
 package org.apache.xalan.xsltc.compiler;
 
 import java.util.Hashtable;
+import java.util.Stack;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -44,6 +45,7 @@
     private Hashtable _attributeSets = null;
     private Hashtable _aliases = null;
     private Hashtable _excludedURI = null;
+    private Stack     _excludedURIStack = null;
     private Hashtable _decimalFormats = null;
     private Hashtable _keys = null;
 
@@ -260,5 +262,34 @@
 	}	
     }
 
+    /**
+     * Exclusion of namespaces by a stylesheet does not extend to any stylesheet
+     * imported or included by the stylesheet.  Upon entering the context of a
+     * new stylesheet, a call to this method is needed to clear the current set
+     * of excluded namespaces temporarily.  Every call to this method requires
+     * a corresponding call to {@link #popExcludedNamespacesContext()}.
+     */
+    public void pushExcludedNamespacesContext() {
+        if (_excludedURIStack == null) {
+            _excludedURIStack = new Stack();
+        }
+        _excludedURIStack.push(_excludedURI);
+        _excludedURI = null;
+    }
+    
+    /**
+     * Exclusion of namespaces by a stylesheet does not extend to any stylesheet
+     * imported or included by the stylesheet.  Upon exiting the context of a
+     * stylesheet, a call to this method is needed to restore the set of
+     * excluded namespaces that was in effect prior to entering the context of
+     * the current stylesheet.
+     */
+    public void popExcludedNamespacesContext() {
+        _excludedURI = (Hashtable) _excludedURIStack.pop();
+        if (_excludedURIStack.isEmpty()) {
+            _excludedURIStack = null;
+        }
+    }
+
 }