You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mu...@apache.org on 2025/10/24 11:55:01 UTC

(xalan-java) branch xalan-j_xslt3.0_mvn updated: committing xalan-j xslt 3.0 implementation improvements for xsl:mode instruction

This is an automated email from the ASF dual-hosted git repository.

mukulg pushed a commit to branch xalan-j_xslt3.0_mvn
in repository https://gitbox.apache.org/repos/asf/xalan-java.git


The following commit(s) were added to refs/heads/xalan-j_xslt3.0_mvn by this push:
     new 6ecee35e7 committing xalan-j xslt 3.0 implementation improvements for xsl:mode instruction
6ecee35e7 is described below

commit 6ecee35e7c1c7d7346af6406268a17808aa8aa4e
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Fri Oct 24 17:24:27 2025 +0530

    committing xalan-j xslt 3.0 implementation improvements for xsl:mode instruction
---
 .../apache/xalan/processor/XSLTAttributeDef.java   |  28 +++-
 .../org/apache/xalan/processor/XSLTSchema.java     |   5 +
 .../java/org/apache/xalan/templates/Constants.java |   4 +
 .../apache/xalan/templates/ElemApplyTemplates.java | 114 ++++++++-----
 .../java/org/apache/xalan/templates/ElemMode.java  |  38 ++++-
 .../org/apache/xalan/templates/Stylesheet.java     | 176 ++++++++++++++++++---
 .../org/apache/xalan/templates/StylesheetRoot.java |   4 +-
 .../org/apache/xalan/templates/TemplateList.java   |  23 ++-
 .../apache/xalan/transformer/TransformerImpl.java  |  49 +++---
 .../w3c/xslt3/misc/XslBuiltInTemplateTests.java    |   8 -
 10 files changed, 344 insertions(+), 105 deletions(-)

diff --git a/src/main/java/org/apache/xalan/processor/XSLTAttributeDef.java b/src/main/java/org/apache/xalan/processor/XSLTAttributeDef.java
index 12df77400..d4c08c7ce 100644
--- a/src/main/java/org/apache/xalan/processor/XSLTAttributeDef.java
+++ b/src/main/java/org/apache/xalan/processor/XSLTAttributeDef.java
@@ -33,6 +33,7 @@ import org.apache.xalan.res.XSLMessages;
 import org.apache.xalan.res.XSLTErrorResources;
 import org.apache.xalan.templates.AVT;
 import org.apache.xalan.templates.Constants;
+import org.apache.xalan.templates.ElemApplyTemplates;
 import org.apache.xalan.templates.ElemForEachGroup;
 import org.apache.xalan.templates.ElemTemplateElement;
 import org.apache.xalan.xslt.util.StringUtil;
@@ -1040,14 +1041,27 @@ public class XSLTAttributeDef
     			return null; 
         	 }
     	  }
+    	  else if ((owner instanceof ElemApplyTemplates) && (Constants.ATTRNAME_MODE).equals(name) && 
+    			                                                                                 (Constants.ATTRVAL_DEFAULT_PREFIX).equals(value)) {
+    		  // We use, non-standard namespace for this QName object, because 
+    		  // string #default is not a valid QName string.
+    		  qname = new QName("http://xml.apache.org/xalan", "default", true); 
+    	  }
+    	  else if ((owner instanceof ElemApplyTemplates) && (Constants.ATTRNAME_MODE).equals(name) && 
+    			                                                                                 (Constants.ATTRVAL_UNNAMED_PREFIX).equals(value)) {
+    		  // We use, non-standard namespace for this QName object, because 
+    		  // string #unnamed is not a valid QName string.
+    		  qname = new QName("http://xml.apache.org/xalan", "unnamed", true); 
+    	  }
+    	  else if ((owner instanceof ElemApplyTemplates) && (Constants.ATTRNAME_MODE).equals(name) && 
+    			                                                                                 (Constants.ATTRVAL_CURRENT_PREFIX).equals(value)) {
+    		  // We use, non-standard namespace for this QName object, because 
+    		  // string #current is not a valid QName string.
+    		  qname = new QName("http://xml.apache.org/xalan", "current", true); 
+    	  }
     	  else {
-    		 if ((Constants.ATTRNAME_MODE).equals(name) && (Constants.ATTRVAL_DEFAULT_PREFIX).equals(value)) {
-    			qname = new QName("http://xml.apache.org/xalan", "default", true); 
-    		 }
-    		 else {
-   	            qname = new QName(value, handler, true);
-    		 }
-    	  }    	      	  
+    		  qname = new QName(value, handler, true);
+    	  }   	      	  
    	      
           return qname;
         }
diff --git a/src/main/java/org/apache/xalan/processor/XSLTSchema.java b/src/main/java/org/apache/xalan/processor/XSLTSchema.java
index 364d23866..e37c2acfe 100644
--- a/src/main/java/org/apache/xalan/processor/XSLTSchema.java
+++ b/src/main/java/org/apache/xalan/processor/XSLTSchema.java
@@ -180,6 +180,10 @@ public class XSLTSchema extends XSLTElementDef
                                     XSLTAttributeDef.T_YESNO, false, false, XSLTAttributeDef.ERROR);
     XSLTAttributeDef mediaTypeAttr = new XSLTAttributeDef(null, "media-type",
                                        XSLTAttributeDef.T_CDATA, false, false, XSLTAttributeDef.ERROR);
+    
+    // xsl:stylesheet, xsl:transform
+    XSLTAttributeDef defaultModeAttr = new XSLTAttributeDef(null, "default-mode",
+                                                       XSLTAttributeDef.T_QNAME, false, false, XSLTAttributeDef.ERROR);
                                        
                   
     // Required.
@@ -1366,6 +1370,7 @@ public class XSLTSchema extends XSLTElementDef
                                            versionAttrRequired,
                                            xpathDefaultNamespaceAttrOpt,
                                            expandTextAttrOpt,
+                                           defaultModeAttr,
                                            spaceAttr }, new ProcessorStylesheetElement(),  /* ContentHandler */
                                          null  /* class object */,
                                          true, -1, false);
diff --git a/src/main/java/org/apache/xalan/templates/Constants.java b/src/main/java/org/apache/xalan/templates/Constants.java
index f3fe074a9..cddd98285 100644
--- a/src/main/java/org/apache/xalan/templates/Constants.java
+++ b/src/main/java/org/apache/xalan/templates/Constants.java
@@ -450,6 +450,10 @@ public class Constants extends org.apache.xml.utils.Constants
   /** For Stylesheet-prefix and result-prefix in xsl:namespace-alias          */
   public static final String ATTRVAL_DEFAULT_PREFIX = "#default";
   
+  public static final String ATTRVAL_UNNAMED_PREFIX = "#unnamed";
+  
+  public static final String ATTRVAL_CURRENT_PREFIX = "#current";
+  
   public static final String ATTRVAL_ALL_PREFIX = "#all";
 
  /** Integer equivalents for above        */
diff --git a/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java b/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
index 0b7ad88e3..9458159a0 100644
--- a/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
+++ b/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
@@ -28,6 +28,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.Vector;
 
+import javax.xml.transform.ErrorListener;
 import javax.xml.transform.SourceLocator;
 import javax.xml.transform.TransformerException;
 
@@ -38,7 +39,6 @@ import org.apache.xerces.xs.XSTypeDefinition;
 import org.apache.xml.dtm.DTM;
 import org.apache.xml.dtm.DTMCursorIterator;
 import org.apache.xml.serializer.SerializationHandler;
-import org.apache.xml.utils.DefaultErrorHandler;
 import org.apache.xml.utils.IntStack;
 import org.apache.xml.utils.QName;
 import org.apache.xpath.Expression;
@@ -559,9 +559,40 @@ public class ElemApplyTemplates extends ElemCallTemplate
 
 		  IntStack currentNodes = xctxt.getCurrentNodeStack();
 
-		  IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();
-
-		  int child;		  
+		  IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();		  
+		  
+		  QName mode = transformer.getMode();
+			  
+		  QName qnameCurrent = new QName("http://xml.apache.org/xalan", "current", true);
+		  QName qnameUnnamed = new QName("http://xml.apache.org/xalan", "unnamed", true);
+		  if (qnameCurrent.equals(mode)) {
+			 mode = transformer.getCurrentMode();  
+		  }
+		  else if (qnameUnnamed.equals(mode)) {
+			 mode = null; 
+		  }
+		  
+		  ElemMode elemMode = sroot.getElemMode(mode);
+		  
+		  String onNoMatchStr = null;
+		  String xslOnMultipleMatchStr = null;
+		  boolean xslWarningOnMultipleMatch = false;
+		  
+		  if (elemMode != null) {
+			  xslOnMultipleMatchStr = elemMode.getOnMultipleMatch();				  
+			  if (xslOnMultipleMatchStr != null) {
+				  if (!((Constants.ATTRVAL_USE_LAST).equals(xslOnMultipleMatchStr) || (Constants.ATTRVAL_FAIL).equals(xslOnMultipleMatchStr))) {
+					  throw new TransformerException("XTTE0505 : An xsl:mode instruction's \"on-multiple-match\" attribute has in-correct "
+							                                                                                + "value '" + xslOnMultipleMatchStr + "'.", srcLocator); 
+				  }
+			  }
+			  
+			  xslWarningOnMultipleMatch = elemMode.isWarningOnMultipleMatch();
+			  
+			  onNoMatchStr = elemMode.getOnNoMatch();
+		  }
+		  
+		  int child;
 		  while (DTM.NULL != (child = sourceNodes.nextNode()))
 		  {
 			  currentNodes.setTop(child);
@@ -575,24 +606,6 @@ public class ElemApplyTemplates extends ElemCallTemplate
 			  final int exNodeType = dtm.getExpandedTypeID(child);
 
 			  final int nodeType = dtm.getNodeType(child);
-
-			  final QName mode = transformer.getMode();
-			  
-			  ElemMode elemMode = sroot.getElemMode(mode);
-			  
-			  String xslOnMultipleMatchStr = null;
-			  boolean xslWarningOnMultipleMatch = false;
-			  if (elemMode != null) {
-				  xslOnMultipleMatchStr = elemMode.getOnMultipleMatch();				  
-				  if (xslOnMultipleMatchStr != null) {
-					  if (!((Constants.ATTRVAL_USE_LAST).equals(xslOnMultipleMatchStr) || (Constants.ATTRVAL_FAIL).equals(xslOnMultipleMatchStr))) {
-						  throw new TransformerException("XTTE0505 : An xsl:mode instruction's \"on-multiple-match\" attribute has in-correct "
-								                                                                                + "value '" + xslOnMultipleMatchStr + "'.", srcLocator); 
-					  }
-				  }
-				  
-				  xslWarningOnMultipleMatch = elemMode.isWarningOnMultipleMatch();
-			  }
 			  
 			  ElemTemplate template = tl.getTemplateFast(xctxt, child, exNodeType, mode, -1, true, dtm, 
 					                                                                                   xslOnMultipleMatchStr, xslWarningOnMultipleMatch);			 
@@ -605,9 +618,14 @@ public class ElemApplyTemplates extends ElemCallTemplate
 				  case DTM.DOCUMENT_FRAGMENT_NODE :
 				  case DTM.ELEMENT_NODE :
 					  if (elemMode != null) {						  						  
-						  String elemName = dtm.getNodeName(child);
-						  String onNoMatchStr = elemMode.getOnNoMatch();						  
-						  if (onNoMatchStr != null) {							  							  
+						  String elemName = dtm.getNodeName(child);						  						  
+						  if (onNoMatchStr != null) {
+							  /**
+							   * Finding an XSL stylesheet built-in template rule, when 
+							   * xsl:mode instruction specifies an attribute 'on-no-match',
+							   * with an allowed non-null value.
+							   */
+							  
 							  if ((Constants.ATTRVAL_TEXT_ONLY_COPY).equals(onNoMatchStr)) {
 								  template = sroot.getTextOnlyCopyRule(elemMode.getName(), nodeType);
 							  }
@@ -624,7 +642,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
 								  template = sroot.getShallowSkipRule(elemMode.getName(), nodeType);
 							  }							  
 							  else if ((Constants.ATTRVAL_FAIL).equals(onNoMatchStr)) {
-								  String errMesg = "XTDE0555 : An xsl:template declaration could not be found to process an XML element node";
+								  String errMesg = "XTDE0555 : An xsl:template declaration could not be located to process an XML element node";
 								  if (elemName != null) {
 									 errMesg = (errMesg + " '" + elemName + "'."); 
 								  }
@@ -639,23 +657,35 @@ public class ElemApplyTemplates extends ElemCallTemplate
 								  		                                                                          + "value '" + onNoMatchStr + "'.", srcLocator);
 							  }
 						  }
-						  else {
-							  if (elemMode.isWarningOnNoMatch()) {
-								  int errLineNo = srcLocator.getLineNumber();
-								  if (errLineNo != 0) {
-									 DefaultErrorHandler errorListener = new DefaultErrorHandler();
-									 String errMesg = "Warning : An xsl:template declaration could not be found to process an XML element node";
-									 if (elemName != null) {
-										 errMesg = (errMesg + " '" + elemName + "'."); 
-									 }
-									 else {
-										 errMesg = (errMesg + "."); 
-									 }
-								     errorListener.warning(new TransformerException(errMesg, srcLocator));
+
+						  if (elemMode.isWarningOnNoMatch()) {
+							  /**
+							   * Emitting an XSL stylesheet processing warning, when xsl:mode
+							   * instruction specifies an attribute 'warning-on-no-match' with
+							   * value true.
+							   */
+							  
+							  int errLineNo = srcLocator.getLineNumber();
+							  if (errLineNo != 0) {
+								  ErrorListener errorListener = xctxt.getErrorListener();									 
+								  String errMesg = "Warning : An xsl:template declaration could not be located to process an XML element node";
+								  if (elemName != null) {
+									  errMesg = (errMesg + " '" + elemName + "'."); 
+								  }
+								  else {
+									  errMesg = (errMesg + "."); 
 								  }
+
+								  errorListener.warning(new TransformerException(errMesg, srcLocator));
 							  }
-							  
-							  template = sroot.getDefaultRule();
+						  }
+						  
+						  if ((Constants.ATTRVAL_TEXT_ONLY_COPY).equals(onNoMatchStr)) {
+							 transformer.pushPairCurrentMatched(template, child); 
+							 transformer.setCurrentElement(template);
+							 dtm.dispatchCharactersEvents(child, rth, false);
+							 transformer.popCurrentMatched();							 
+							 continue;
 						  }
 					  }
 					  else {
@@ -669,7 +699,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
 					  transformer.pushPairCurrentMatched(sroot.getDefaultTextRule(), child);
 					  transformer.setCurrentElement(sroot.getDefaultTextRule());
 					  dtm.dispatchCharactersEvents(child, rth, false);
-					  transformer.popCurrentMatched();
+					  transformer.popCurrentMatched();					  
 					  continue;
 				  case DTM.DOCUMENT_NODE :
 					  template = sroot.getDefaultRootRule();
diff --git a/src/main/java/org/apache/xalan/templates/ElemMode.java b/src/main/java/org/apache/xalan/templates/ElemMode.java
index 58e677529..11100ddad 100644
--- a/src/main/java/org/apache/xalan/templates/ElemMode.java
+++ b/src/main/java/org/apache/xalan/templates/ElemMode.java
@@ -88,23 +88,45 @@ public class ElemMode extends ElemTemplateElement
   
   /**
    * An xsl:mode element's 'on-no-match' attribute.
+   * 
+   * This has default value "text-only-copy", which may be 
+   * overridden by XSL stylesheet's xsl:mode declaration. 
    */
-  private String m_onNoMatch = null;
+  private String m_onNoMatch = Constants.ATTRVAL_TEXT_ONLY_COPY;
   
   /**
    * An xsl:mode element's 'on-multiple-match' attribute.
+   * 
+   * This has default value "use-last", which may be overridden 
+   * by XSL stylesheet's xsl:mode declaration.
    */
-  private String m_onMultipleMatch = null;
+  private String m_onMultipleMatch = Constants.ATTRVAL_USE_LAST;
   
   /**
    * An xsl:mode element's 'warning-on-no-match' attribute.
+   * 
+   * Xalan's default value for this attribute is false.
    */
   private boolean m_warningOnNoMatch = false;
   
+  /**
+   * This has boolean value true, if xsl:mode instruction's attribute 
+   * 'warning-on-no-match' is declared within an XSL stylesheet. 
+   */
+  private boolean m_warningOnNoMatchDeclared = false;
+  
   /**
    * An xsl:mode element's 'warning-on-multiple-match' attribute.
+   * 
+   * Xalan's default value for this attribute is false.
    */
   private boolean m_warningOnMultipleMatch = false;
+  
+  /**
+   * This has boolean value true, if xsl:mode instruction's attribute 
+   * 'warning-on-multiple-match' is declared within an XSL stylesheet. 
+   */
+  private boolean m_warningOnMultipleMatchDeclared = false;
 
   /**
    * Set the "name" attribute.
@@ -180,6 +202,12 @@ public class ElemMode extends ElemTemplateElement
    */
   public void setWarningOnNoMatch(boolean warningOnNoMatch) {
 	  this.m_warningOnNoMatch = warningOnNoMatch;
+	  
+	  m_warningOnNoMatchDeclared = true;
+  }
+  
+  public boolean isWarningOnNoMatchDeclared() {
+	  return m_warningOnNoMatchDeclared;
   }
 
   /**
@@ -198,6 +226,12 @@ public class ElemMode extends ElemTemplateElement
    */
   public void setWarningOnMultipleMatch(boolean warningOnMultipleMatch) {
 	  this.m_warningOnMultipleMatch = warningOnMultipleMatch;
+	  
+	  m_warningOnMultipleMatchDeclared = true;
+  }
+  
+  public boolean isWarningOnMultipleMatchDeclared() {
+	  return m_warningOnMultipleMatchDeclared;
   }
 
 /**
diff --git a/src/main/java/org/apache/xalan/templates/Stylesheet.java b/src/main/java/org/apache/xalan/templates/Stylesheet.java
index 85b3753cc..a0d5de7c2 100644
--- a/src/main/java/org/apache/xalan/templates/Stylesheet.java
+++ b/src/main/java/org/apache/xalan/templates/Stylesheet.java
@@ -407,6 +407,30 @@ public class Stylesheet extends ElemTemplateElement implements java.io.Serializa
 	public boolean getExpandText() {
 		return m_expand_text;
 	}
+	
+	/**
+	  * An xsl:stylesheet element's 'default-mode' attribute.
+	  */
+	private QName m_xsl_default_mode = null;
+	
+	/**
+	 * Set the value of "default-mode" attribute.
+	 *
+	 * @param v   Value of the "default-mode" attribute
+	 */
+	public void setDefaultMode(QName modeName)
+	{
+		m_xsl_default_mode = modeName; 
+	}
+
+	/**
+	 * Get the value of "default-mode" attribute.
+	 *  
+	 * @return		  The value of "default-mode" attribute 
+	 */
+	public QName getDefaultMode() {
+		return m_xsl_default_mode;
+	}
 
 	/**
 	 * The "version" property.
@@ -1090,9 +1114,10 @@ public class Stylesheet extends ElemTemplateElement implements java.io.Serializa
 	
 	/**
 	 * An ElemMode object instance, referring to the default 
-	 * mode, that doesn't have an attribute 'name'.
+	 * mode, for xsl:mode instruction that doesn't have an 
+	 * attribute 'name'.
 	 */
-	private ElemMode m_defaultMode;
+	private ElemMode m_defaultElemMode;
 	
 	/**
 	 * Set an "xsl:mode" property.
@@ -1111,25 +1136,130 @@ public class Stylesheet extends ElemTemplateElement implements java.io.Serializa
 			
 			ElemMode elemModePrev = m_modeList.getElemMode(modeName);
             if (elemModePrev == null) {
+            	elemMode.setStylesheet(this);
 			    m_modeList.setElemMode(elemMode);
             }
             else {
-            	throw new TransformerException("XTTE0505 : An XSL stylesheet has more than one xsl:mode declaration "
-            			                                                    + "with name '" + modeName.toString() + "'.", elemMode);
+            	String modeNameStr = modeName.toString();
+            	
+            	String prevOnNoMatchDeclStr = elemModePrev.getOnNoMatch();
+            	String prevOnMultipleMatchStr = elemModePrev.getOnMultipleMatch();
+            	boolean prevWarningOnNoMatch = elemModePrev.isWarningOnNoMatch();
+            	boolean prevWarningOnMultipleMatch = elemModePrev.isWarningOnMultipleMatch();
+            	
+            	boolean prevWarningOnNoMatchDeclared = elemModePrev.isWarningOnNoMatchDeclared();
+            	boolean prevWarningOnMultipleMatchDeclared = elemModePrev.isWarningOnMultipleMatchDeclared();
+            	
+            	String onNoMatchDeclStr = elemMode.getOnNoMatch();
+            	String onMultipleMatchStr = elemMode.getOnMultipleMatch();
+            	boolean warningOnNoMatch = elemMode.isWarningOnNoMatch();
+            	boolean warningOnMultipleMatch = elemMode.isWarningOnMultipleMatch();
+            	
+            	boolean warningOnNoMatchDeclared = elemMode.isWarningOnNoMatchDeclared();
+            	boolean warningOnMultipleMatchDeclared = elemMode.isWarningOnMultipleMatchDeclared();
+            	
+            	if ((prevOnNoMatchDeclStr != null) && (onNoMatchDeclStr != null) 
+            			                                               && !onNoMatchDeclStr.equals(prevOnNoMatchDeclStr)) {
+            		throw new TransformerException("XTSE0545 : An XSL stylesheet has more than one xsl:mode declaration with "
+            				                                                            + "name '" + modeNameStr + "', that have conflicting "
+            				                                                            + "values for \"xsl:mode\" attribute 'on-no-match'.");
+            	}
+            	else if ((prevOnNoMatchDeclStr != null) && (onNoMatchDeclStr == null)) {
+            		elemMode.setOnNoMatch(prevOnNoMatchDeclStr);
+            	}
+            	
+            	if ((prevOnMultipleMatchStr != null) && (onMultipleMatchStr != null) 
+                                                                      && onMultipleMatchStr.equals(prevOnMultipleMatchStr)) {
+            		throw new TransformerException("XTSE0545 : An XSL stylesheet has more than one xsl:mode declaration with "
+															                            + "name '" + modeNameStr + "', that have conflicting "
+															                            + "values for \"xsl:mode\" attribute 'on-multiple-match'.");
+                }
+            	else if ((prevOnMultipleMatchStr != null) && (onMultipleMatchStr == null)) {
+            		elemMode.setOnMultipleMatch(prevOnMultipleMatchStr);
+            	}
+            	
+            	if (prevWarningOnNoMatchDeclared && warningOnNoMatchDeclared && (prevWarningOnNoMatch != warningOnNoMatch)) {
+            		throw new TransformerException("XTSE0545 : An XSL stylesheet has more than one xsl:mode declaration with "
+															                            + "name '" + modeNameStr + "', that have conflicting "
+															                            + "values for \"xsl:mode\" attribute 'warning-on-no-match'.");
+            	}
+            	else if (prevWarningOnNoMatchDeclared) {
+            		elemMode.setWarningOnNoMatch(prevWarningOnNoMatch);
+            	}
+            	
+            	if (prevWarningOnMultipleMatchDeclared && warningOnMultipleMatchDeclared && (prevWarningOnMultipleMatch != warningOnMultipleMatch)) {
+            		throw new TransformerException("XTSE0545 : An XSL stylesheet has more than one xsl:mode declaration with "
+															                            + "name '" + modeNameStr + "', that have conflicting "
+															                            + "values for \"xsl:mode\" attribute 'warning-on-multiple-match'.");
+            	}
+            	else if (prevWarningOnMultipleMatchDeclared) {
+            		elemMode.setWarningOnMultipleMatch(prevWarningOnMultipleMatch);
+            	}
+            	
+            	elemMode.setStylesheet(this);
+            	m_modeList.setElemMode(elemMode);
             }
 		}
 		else {
-			if (m_defaultMode == null) {
-				m_defaultMode = elemMode; 
+			if (m_defaultElemMode == null) {
+				elemMode.setStylesheet(this);
+				m_defaultElemMode = elemMode; 
 			}
 			else {
-				throw new TransformerException("XTTE0505 : An XSL stylesheet cannot have more than one "
-						                                                   + "xsl:mode declaration for default mode (i.e, xsl:mode "
-						                                                   + "declaration without 'name' attribute).", elemMode);
+				ElemMode elemModePrev = m_defaultElemMode;
+				
+				String prevOnNoMatchDeclStr = elemModePrev.getOnNoMatch();
+            	String prevOnMultipleMatchStr = elemModePrev.getOnMultipleMatch();
+            	boolean prevWarningOnNoMatch = elemModePrev.isWarningOnNoMatch();
+            	boolean prevWarningOnMultipleMatch = elemModePrev.isWarningOnMultipleMatch();
+            	
+            	boolean prevWarningOnNoMatchDeclared = elemModePrev.isWarningOnNoMatchDeclared();
+            	boolean prevWarningOnMultipleMatchDeclared = elemModePrev.isWarningOnMultipleMatchDeclared();
+            	
+            	String onNoMatchDeclStr = elemMode.getOnNoMatch();
+            	String onMultipleMatchStr = elemMode.getOnMultipleMatch();
+            	boolean warningOnNoMatch = elemMode.isWarningOnNoMatch();
+            	boolean warningOnMultipleMatch = elemMode.isWarningOnMultipleMatch();
+            	
+            	boolean warningOnNoMatchDeclared = elemMode.isWarningOnNoMatchDeclared();
+            	boolean warningOnMultipleMatchDeclared = elemMode.isWarningOnMultipleMatchDeclared();
+            	
+            	if ((prevOnNoMatchDeclStr != null) && (onNoMatchDeclStr != null) 
+            			                                               && !onNoMatchDeclStr.equals(prevOnNoMatchDeclStr)) {
+            		throw new TransformerException("XTSE0545 : An XSL stylesheet has more than one xsl:mode declaration for an unnamed mode, that "
+							            				                                                   + "have conflicting values for \"xsl:mode\" "
+							            				                                                   + "attribute 'on-no-match'.");
+            	}
+            	else if ((prevOnNoMatchDeclStr != null) && (onNoMatchDeclStr == null)) {
+            		elemMode.setOnNoMatch(prevOnNoMatchDeclStr);
+            	}
+
+            	if ((prevOnMultipleMatchStr != null) && (onMultipleMatchStr != null) 
+            			                                                   && onMultipleMatchStr.equals(prevOnMultipleMatchStr)) {
+            		throw new TransformerException("XTSE0545 : An XSL stylesheet has more than one xsl:mode declaration for an unnamed mode, that "
+																				                            + "have conflicting values for \"xsl:mode\" "
+																				                            + "attribute 'on-multiple-match'.");
+            	}
+            	else if ((prevOnMultipleMatchStr != null) && (onMultipleMatchStr == null)) {
+            		elemMode.setOnMultipleMatch(prevOnMultipleMatchStr);
+            	}
+
+            	if (prevWarningOnNoMatchDeclared && warningOnNoMatchDeclared && (prevWarningOnNoMatch != warningOnNoMatch)) {
+            		throw new TransformerException("XTSE0545 : An XSL stylesheet has more than one xsl:mode declaration for an unnamed mode, that "
+																				                            + "have conflicting values for \"xsl:mode\" "
+																				                            + "attribute 'warning-on-no-match'.");
+            	}
+
+            	if (prevWarningOnMultipleMatchDeclared && warningOnMultipleMatchDeclared && (prevWarningOnMultipleMatch != warningOnMultipleMatch)) {
+            		throw new TransformerException("XTSE0545 : An XSL stylesheet has more than one xsl:mode declaration for an unnamed mode, that "
+																				                            + "have conflicting values for \"xsl:mode\" "
+																				                            + "attribute 'warning-on-multiple-match'.");
+            	}
+
+            	elemMode.setStylesheet(this);
+            	m_defaultElemMode = elemMode; 
 			}
-		}
-		
-		elemMode.setStylesheet(this);
+		}				
 	}
 	
 	/**
@@ -1143,20 +1273,24 @@ public class Stylesheet extends ElemTemplateElement implements java.io.Serializa
 	 */
 	public ElemMode getElemMode(QName modeName) {
 		
-		ElemMode result = null;
+		ElemMode result = null;		
 		
-		QName defaultMode = new QName("http://xml.apache.org/xalan", "default", true);
-		
-		if (modeName != null) {
-			if (defaultMode.equals(modeName) && (m_defaultMode != null)) {
-			   result = m_defaultMode;
+		if (modeName != null) {			
+			if ((m_xsl_default_mode != null) && (m_modeList != null)) {
+				result = m_modeList.getElemMode(m_xsl_default_mode);  
+			}
+			else if (m_defaultElemMode != null) {
+				result = m_defaultElemMode;
 			}
 			else if (m_modeList != null) {
-			   result = m_modeList.getElemMode(modeName);
+				result = m_modeList.getElemMode(modeName);
 			}
 		}
-		else if (m_defaultMode != null) {
-			result = m_defaultMode;
+		else if ((m_xsl_default_mode != null) && (m_modeList != null)) {
+			result = m_modeList.getElemMode(m_xsl_default_mode);
+		}
+		else if (m_defaultElemMode != null) {
+			result = m_defaultElemMode;
 		}
 		
 		return result;
diff --git a/src/main/java/org/apache/xalan/templates/StylesheetRoot.java b/src/main/java/org/apache/xalan/templates/StylesheetRoot.java
index d1cfc3ee6..a583eba78 100644
--- a/src/main/java/org/apache/xalan/templates/StylesheetRoot.java
+++ b/src/main/java/org/apache/xalan/templates/StylesheetRoot.java
@@ -1126,7 +1126,7 @@ public class StylesheetRoot extends StylesheetComposed
 		  elemTemplate.appendChild(elemApplyTemplates);		  
 	  }
 	  else if (nodeType == DTM.ELEMENT_NODE) {
-		  XPath xpathMatch = new XPath("element()", this, this, XPath.MATCH, m_errorListener);
+		  XPath xpathMatch = new XPath("*", this, this, XPath.MATCH, m_errorListener);
 		  elemTemplate.setMatch(xpathMatch);
 		  
 		  ElemApplyTemplates elemApplyTemplates = new ElemApplyTemplates();
@@ -1282,7 +1282,7 @@ public class StylesheetRoot extends StylesheetComposed
 		  elemTemplate.appendChild(elemApplyTemplates2);		  
 	  }
 	  else if (nodeType == DTM.ELEMENT_NODE) {
-		  XPath xpathMatch = new XPath("element()", this, this, XPath.MATCH, m_errorListener);
+		  XPath xpathMatch = new XPath("*", this, this, XPath.MATCH, m_errorListener);
 		  elemTemplate.setMatch(xpathMatch);
 		  
 		  ElemApplyTemplates elemApplyTemplates1 = new ElemApplyTemplates();
diff --git a/src/main/java/org/apache/xalan/templates/TemplateList.java b/src/main/java/org/apache/xalan/templates/TemplateList.java
index 5f6a860be..4754cacd6 100644
--- a/src/main/java/org/apache/xalan/templates/TemplateList.java
+++ b/src/main/java/org/apache/xalan/templates/TemplateList.java
@@ -26,12 +26,12 @@ import java.util.Hashtable;
 import java.util.Map;
 import java.util.Vector;
 
+import javax.xml.transform.ErrorListener;
 import javax.xml.transform.SourceLocator;
 import javax.xml.transform.TransformerException;
 
 import org.apache.xalan.res.XSLTErrorResources;
 import org.apache.xml.dtm.DTM;
-import org.apache.xml.utils.DefaultErrorHandler;
 import org.apache.xml.utils.QName;
 import org.apache.xpath.Expression;
 import org.apache.xpath.XPath;
@@ -869,6 +869,12 @@ public class TemplateList implements java.io.Serializable
 			   while ((next = next.getNext()) != null) {
 				   if ((next.m_stepPattern.execute(xctxt, targetNode) != NodeTest.SCORE_NONE) 
 						   																	&& next.matchMode(mode)) {
+					   /**
+					    * Emitting an XSL stylesheet dynamic error, when xsl:mode 
+					    * instruction specifies an attribute "on-multiple-match" with
+					    * value 'fail'.   
+					    */
+					   
 					   String elemName = dtm.getNodeName(targetNode);
 
 					   SourceLocator srcLocator1 = (SourceLocator)(head.getTemplate());
@@ -877,9 +883,9 @@ public class TemplateList implements java.io.Serializable
 					   int lineNo2 = srcLocator2.getLineNumber();
 
 					   throw new TransformerException("XTDE0540 : More than one xsl:template rule matched "
-																							   + "an XML element node '" + elemName + "'. "
-																							   + "Conflicting xsl:template rule locations are "
-																							   + "line " + lineNo1 + " and line " + lineNo2 +"."); 
+																							+ "an XML element node '" + elemName + "'. "
+																							+ "Conflicting xsl:template rule locations are "
+																							+ "line " + lineNo1 + " and line " + lineNo2 +".", srcLocator1); 
 				   }
 			   }
 		   }
@@ -889,6 +895,12 @@ public class TemplateList implements java.io.Serializable
 		   while ((next = next.getNext()) != null) {
 			   if ((next.m_stepPattern.execute(xctxt, targetNode) != NodeTest.SCORE_NONE) 
 					   																	&& next.matchMode(mode)) {
+				   /**
+					* Emitting an XSL stylesheet processing warning, when xsl:mode
+					* instruction specifies an attribute "warning-on-multiple-match" with
+					* value true.
+				   */
+				   
 				   String elemName = dtm.getNodeName(targetNode);
 
 				   SourceLocator srcLocator1 = (SourceLocator)(head.getTemplate());
@@ -896,7 +908,8 @@ public class TemplateList implements java.io.Serializable
 				   SourceLocator srcLocator2 = (SourceLocator)(next.getTemplate());
 				   int lineNo2 = srcLocator2.getLineNumber();
 
-				   DefaultErrorHandler errorListener = new DefaultErrorHandler();				   
+				   ErrorListener errorListener = xctxt.getErrorListener();
+				   
 				   errorListener.warning(new TransformerException("Warning : More than one xsl:template rule matched "
 																						   + "an XML element node '" + elemName + "'. "
 																						   + "Conflicting xsl:template rule locations are "
diff --git a/src/main/java/org/apache/xalan/transformer/TransformerImpl.java b/src/main/java/org/apache/xalan/transformer/TransformerImpl.java
index dd37c3ac2..277f73052 100644
--- a/src/main/java/org/apache/xalan/transformer/TransformerImpl.java
+++ b/src/main/java/org/apache/xalan/transformer/TransformerImpl.java
@@ -3675,43 +3675,56 @@ public class TransformerImpl extends Transformer
 
     throw new SAXNotRecognizedException(name);
   }
-
-  // %TODO% Doc
-
+  
   /**
-   * NEEDSDOC Method getMode 
-   *
-   *
-   * NEEDSDOC (getMode) @return
+   * Get an XSL transformation's present mode value.
+   *  
+   * @return						QName object reference of the mode 
    */
   public QName getMode()
   {
     return m_modes.isEmpty() ? null : (QName) m_modes.peek();
   }
-
-  // %TODO% Doc
-
+  
   /**
-   * NEEDSDOC Method pushMode 
-   *
-   *
-   * NEEDSDOC @param mode
+   * Push an XSL mode reference, to mode stack.
+   * 
+   * @param mode					QName object value of the mode
    */
   public void pushMode(QName mode)
   {
     m_modes.push(mode);
   }
 
-  // %TODO% Doc
-
   /**
-   * NEEDSDOC Method popMode 
-   *
+   * Pop an XSL mode reference, from mode stack.
    */
   public void popMode()
   {
     m_modes.pop();
   }
+  
+  /**
+   * Method definition, to get XSL transformation's current mode 
+   * reference, for the given XSL evaluation context.
+   * 
+   * @return				QName object reference of the mode
+   */
+  public QName getCurrentMode() {
+	  
+	  QName result = null;
+	  
+	  if (!m_modes.isEmpty()) {
+		 Object stackTop = m_modes.pop();
+		 if ((stackTop != null) && !m_modes.isEmpty()) {
+			result = (QName)m_modes.peek();
+			
+			m_modes.push(stackTop);
+		 }
+	  }
+	  
+	  return null;
+  }
 
   /**
    * Called by SourceTreeHandler to start the transformation
diff --git a/src/test/java/org/apache/xalan/tests/w3c/xslt3/misc/XslBuiltInTemplateTests.java b/src/test/java/org/apache/xalan/tests/w3c/xslt3/misc/XslBuiltInTemplateTests.java
index ec43d500b..dac7fffc6 100644
--- a/src/test/java/org/apache/xalan/tests/w3c/xslt3/misc/XslBuiltInTemplateTests.java
+++ b/src/test/java/org/apache/xalan/tests/w3c/xslt3/misc/XslBuiltInTemplateTests.java
@@ -30,14 +30,6 @@ import org.junit.Test;
  * @xsl.usage advanced
  */
 public class XslBuiltInTemplateTests extends W3CXslTransformTestsUtil {
-	
-	/**
-	 * Xalan may probably have bugs for this W3C XSLT 3.0 test set.
-	 * Adding this XSLT 3.0 test set to Xalan's XSLT 3.0 test suite 
-	 * driver, for tracking.
-	 * 
-	 * REVISIT
-	 */
 
     @BeforeClass
     public static void setUpBeforeClass() throws Exception {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org