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/03/22 09:02:52 UTC

(xalan-java) branch xalan-j_xslt3.0_mvn updated: improving implementation of xsl 3 xsl:template processing, when xsl:template element has 'mode' attribute and xsl:template match pattern string starts with '.', along with related working test case

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 7902b504f improving implementation of xsl 3 xsl:template processing, when xsl:template element has 'mode' attribute and xsl:template match pattern string starts with '.', along with related working test case
7902b504f is described below

commit 7902b504fe3b6ed1e3f1499ef00b49bb3b379809
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sat Mar 22 14:32:42 2025 +0530

    improving implementation of xsl 3 xsl:template processing, when xsl:template element has 'mode' attribute and xsl:template match pattern string starts with '.', along with related working test case
---
 README                                             |   4 +-
 .../java/org/apache/xalan/templates/Constants.java |   2 +
 .../apache/xalan/templates/ElemApplyTemplates.java | 136 ++++++++++++---------
 .../org/apache/xalan/templates/TemplateList.java   |  15 +++
 .../apache/xalan/tests/xslt3/XslTemplateTests.java |  10 ++
 src/test/resources/xsl_template/gold/test18.out    |  15 +++
 src/test/resources/xsl_template/test18.xsl         |  77 ++++++++++++
 7 files changed, 201 insertions(+), 58 deletions(-)

diff --git a/README b/README
index d9e08bffc..3d91757aa 100644
--- a/README
+++ b/README
@@ -59,11 +59,11 @@ This produces Maven build output with trailing information like following:
 [INFO]  T E S T S
 [INFO] -------------------------------------------------------
 [INFO] Running org.apache.xalan.tests.main.AllXsl3Tests
-[INFO] Tests run: 949, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 44.034 s - in org.apache.xalan.tests.main.AllXsl3Tests
+[INFO] Tests run: 950, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 19.383 s - in org.apache.xalan.tests.main.AllXsl3Tests
 [INFO]
 [INFO] Results:
 [INFO]
-[INFO] Tests run: 949, Failures: 0, Errors: 0, Skipped: 0
+[INFO] Tests run: 950, Failures: 0, Errors: 0, Skipped: 0
 [INFO]
 [INFO] ------------------------------------------------------------------------
 [INFO] BUILD SUCCESS
diff --git a/src/main/java/org/apache/xalan/templates/Constants.java b/src/main/java/org/apache/xalan/templates/Constants.java
index 9874ba180..ddcdc0e02 100644
--- a/src/main/java/org/apache/xalan/templates/Constants.java
+++ b/src/main/java/org/apache/xalan/templates/Constants.java
@@ -442,7 +442,9 @@ public class Constants extends org.apache.xml.utils.Constants
                              ATTRVAL_NAN = "NaN",
                              DEFAULT_DECIMAL_FORMAT = "#default";
 
+  public static final String XSL3_PATTERN_TABLE_DELIM = "#####";
   
   /** temp dummy         */
   public static final String ATTRNAME_XXXX = "XXXX";
+  
 }
diff --git a/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java b/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
index de8859b07..f475aaf7f 100644
--- a/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
+++ b/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
@@ -212,17 +212,16 @@ public class ElemApplyTemplates extends ElemCallTemplate
     
     DTMIterator sourceNodes = null;
     
-    SourceLocator srcLocator = xctxt.getSAXLocator();
-    
-    XObject varEvalResult = null;
-    
+    SourceLocator srcLocator = xctxt.getSAXLocator();    
+    XObject varEvalResult = null;    
     ResultSequence resultSeq = null;
+    QName xslTemplateInvokeMode = getMode();
     
     if (m_selectExpression instanceof XPathSequenceConstructor) {
     	resultSeq = (ResultSequence)(((XPathSequenceConstructor)m_selectExpression).execute(xctxt));
     	
     	if (isAllSeqItemsXdmAtomicValues(resultSeq)) {    		
-    		executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq);
+    		executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq, xslTemplateInvokeMode);
     		
     		return;
     	}
@@ -243,7 +242,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
     	   resultSeq = (ResultSequence)varEvalResult;
     	   
     	   if (isAllSeqItemsXdmAtomicValues(resultSeq)) {
-    		   executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq);
+    		   executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq, xslTemplateInvokeMode);
 
     		   return;
     	   }
@@ -258,7 +257,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
     	   }
        }
        else if (varEvalResult instanceof XSAnyAtomicType) {   	       	       	   
-    	   executeXslTransformAtomicValue(transformer, xctxt, varEvalResult);
+    	   executeXslTransformAtomicValue(transformer, xctxt, varEvalResult, xslTemplateInvokeMode);
 
     	   return; 
        }
@@ -277,7 +276,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
     	   resultSeq = (ResultSequence)varEvalResult;
     	   
     	   if (isAllSeqItemsXdmAtomicValues(resultSeq)) {
-    		   executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq);
+    		   executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq, xslTemplateInvokeMode);
 
     		   return;
     	   }
@@ -295,7 +294,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
     	   sourceNodes = ((XNodeSet)varEvalResult).asIterator(xctxt, sourceNode);
        }
        else if (isXdmItemAtomicValue(varEvalResult)) {    	   
-    	   executeXslTransformAtomicValue(transformer, xctxt, varEvalResult);
+    	   executeXslTransformAtomicValue(transformer, xctxt, varEvalResult, xslTemplateInvokeMode);
 
     	   return;
        }
@@ -641,7 +640,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
    * XDM atomic values.
    */
   private void executeXslTransformAtomicValueSeq(TransformerImpl transformer, final XPathContext xctxt,
-		  														ResultSequence resultSeq) throws TransformerException {
+		  														ResultSequence resultSeq, QName xslTemplateInvokeMode) throws TransformerException {
 	  
 	  final StylesheetRoot sroot = transformer.getStylesheet();
 	  final TemplateList tl = sroot.getTemplateListComposed();
@@ -652,7 +651,8 @@ public class ElemApplyTemplates extends ElemCallTemplate
 	  
 	  for (int idx = 0; idx < resultSeq.size(); idx++) {
 		  XObject xObj = resultSeq.item(idx);
-		  executeXslTransformAtomicValue(transformer, xctxt, xObj, iter);
+		  
+		  executeXslTransformAtomicValue(transformer, xctxt, xObj, iter, xslTemplateInvokeMode);
 		  
 		  // Reset an iterator object instance
 		  iter = hashTableEntrySet.iterator();		  
@@ -664,7 +664,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
    * transformation for one XDM atomic value.
    */
   private void executeXslTransformAtomicValue(TransformerImpl transformer, final XPathContext xctxt,
-		  														XObject xObj) throws TransformerException {
+		  														XObject xObj, QName xslTemplateInvokeMode) throws TransformerException {
 	  
 	  final StylesheetRoot sroot = transformer.getStylesheet();
 	  final TemplateList tl = sroot.getTemplateListComposed();
@@ -673,9 +673,9 @@ public class ElemApplyTemplates extends ElemCallTemplate
 	  Set hashTableEntrySet = templateListHashTable.entrySet();
 	  Iterator iter = hashTableEntrySet.iterator();
 
-	  executeXslTransformAtomicValue(transformer, xctxt, xObj, iter);
+	  executeXslTransformAtomicValue(transformer, xctxt, xObj, iter, xslTemplateInvokeMode);
 	  
-	  // Reset an iterator object instance
+	  // Recreate an iterator object instance
 	  iter = hashTableEntrySet.iterator();
   }
 
@@ -683,9 +683,9 @@ public class ElemApplyTemplates extends ElemCallTemplate
    * This method definition does, an XSL transform for one XDM atomic value.
    */
   private void executeXslTransformAtomicValue(TransformerImpl transformer, final XPathContext xctxt, XObject xObj,
-		  									 		   Iterator iter) throws TransformerException {
+		  									 		   Iterator iter, QName xslTemplateInvokeMode) throws TransformerException {
 	  
-	  ElemTemplate template = null;
+	  ElemTemplate elemTemplate = null;
 	  
 	  SourceLocator srcLocator = xctxt.getSAXLocator();
 	  
@@ -693,56 +693,80 @@ public class ElemApplyTemplates extends ElemCallTemplate
 	  
 	  while (iter.hasNext()) {
 		  Entry<Object, Object> hashTableEntry = (Entry<Object, Object>)iter.next();
-		  Object hTableKeyObj = hashTableEntry.getKey();
-		  TemplateSubPatternAssociation htValueObj = (TemplateSubPatternAssociation)(hashTableEntry.getValue());		
-		  template = htValueObj.getTemplate();
+		  Object hashTableKeyObj = hashTableEntry.getKey();
+		  TemplateSubPatternAssociation hashTableValueObj = (TemplateSubPatternAssociation)(hashTableEntry.getValue());		
+		  elemTemplate = hashTableValueObj.getTemplate();
 		  
-		  xctxt.setXPath3ContextItem(xObj);
+		  QName templateDefnMode = elemTemplate.getMode();
+		  boolean templateSelected = false;
+		  if ((xslTemplateInvokeMode != null) && (templateDefnMode != null)) {
+			 if (xslTemplateInvokeMode.equals(templateDefnMode)) {			  
+				templateSelected = true;
+			 }
+		  }
+		  else if ((xslTemplateInvokeMode != null) && (templateDefnMode == null)) {
+			 templateSelected = false; 
+		  }
+		  else if ((xslTemplateInvokeMode == null) && (templateDefnMode != null)) {
+			 templateSelected = false; 
+		  }
+		  else {
+			 templateSelected = true; 
+		  }
 		  
-		  String keyValueStr = (String)hTableKeyObj;
-		  if (keyValueStr.startsWith(".[")) {				  				  
-			  String xpathStr = keyValueStr.substring(2);
-			  xpathStr = xpathStr.substring(0, xpathStr.length() - 1);
-			  XPath xpath = new XPath(xpathStr, srcLocator, xctxt.getNamespaceContext(), 
-					  																XPath.SELECT, null);						
-			  XObject xpathEvalResult = xpath.execute(xctxt, DTM.NULL, xctxt.getNamespaceContext());						
-			  boolean isSuccess = false;
-			  if (xpathEvalResult instanceof XBooleanStatic) {
-				  XBooleanStatic xBoolStatic = (XBooleanStatic)xpathEvalResult;
-				  isSuccess = xBoolStatic.bool(); 
-			  }
-			  else if (xpathEvalResult instanceof XBoolean) {
-				  XBoolean xBoolean = (XBoolean)xpathEvalResult;
-				  isSuccess = xBoolean.bool(); 
-			  }
-			  else if (xpathEvalResult instanceof XSBoolean) {
-				  XSBoolean xsBoolean = (XSBoolean)xpathEvalResult;
-				  isSuccess = xsBoolean.bool();
-			  }
+		  String keyValueStr = (String)hashTableKeyObj;
+		  int index1 = keyValueStr.indexOf(Constants.XSL3_PATTERN_TABLE_DELIM);
+		  if (index1 >= 0) {
+			 keyValueStr = keyValueStr.substring(0, index1);
+		  }		  
+		  
+		  if (templateSelected) {
+			  xctxt.setXPath3ContextItem(xObj);
+			  
+			  if (keyValueStr.startsWith(".[")) {				  				  
+				  String xpathStr = keyValueStr.substring(2);
+				  xpathStr = xpathStr.substring(0, xpathStr.length() - 1);
+				  XPath xpath = new XPath(xpathStr, srcLocator, xctxt.getNamespaceContext(), 
+						  															  XPath.SELECT, null);						
+				  XObject xpathEvalResult = xpath.execute(xctxt, DTM.NULL, xctxt.getNamespaceContext());						
+				  boolean isSuccess = false;
+				  if (xpathEvalResult instanceof XBooleanStatic) {
+					  XBooleanStatic xBoolStatic = (XBooleanStatic)xpathEvalResult;
+					  isSuccess = xBoolStatic.bool(); 
+				  }
+				  else if (xpathEvalResult instanceof XBoolean) {
+					  XBoolean xBoolean = (XBoolean)xpathEvalResult;
+					  isSuccess = xBoolean.bool(); 
+				  }
+				  else if (xpathEvalResult instanceof XSBoolean) {
+					  XSBoolean xsBoolean = (XSBoolean)xpathEvalResult;
+					  isSuccess = xsBoolean.bool();
+				  }
 
-			  if (isSuccess) {							  	 
-				  for (ElemTemplateElement t = template.m_firstChild; 
-						  									    t != null; t = t.m_nextSibling) {
+				  if (isSuccess) {							  	 
+					  for (ElemTemplateElement t = elemTemplate.m_firstChild; 
+							  											t != null; t = t.m_nextSibling) {
+						  xctxt.setSAXLocator(t);
+						  transformer.pushElemTemplateElement(t);    		   
+						  t.execute(transformer);
+						  transformer.popElemTemplateElement();
+					  }
+
+					  break;
+				  }				  				  
+			  }
+			  else if (".".equals(keyValueStr)) {						 						  		 
+				  for (ElemTemplateElement t = elemTemplate.m_firstChild; 
+						  											t != null; t = t.m_nextSibling) {
 					  xctxt.setSAXLocator(t);
 					  transformer.pushElemTemplateElement(t);    		   
 					  t.execute(transformer);
 					  transformer.popElemTemplateElement();
 				  }
-				  
+
 				  break;
-			  }				  				  
-		  }
-		  else if (".".equals(keyValueStr)) {						 						  		 
-			  for (ElemTemplateElement t = template.m_firstChild; 
-					  										  t != null; t = t.m_nextSibling) {
-				  xctxt.setSAXLocator(t);
-				  transformer.pushElemTemplateElement(t);    		   
-				  t.execute(transformer);
-				  transformer.popElemTemplateElement();
 			  }
-			  
-			  break;
-		  }		  
+		  }
 	  }
 	  
 	  xctxt.setXPath3ContextItem(prevCtxItem);
diff --git a/src/main/java/org/apache/xalan/templates/TemplateList.java b/src/main/java/org/apache/xalan/templates/TemplateList.java
index 186b7003a..141f9ee6c 100644
--- a/src/main/java/org/apache/xalan/templates/TemplateList.java
+++ b/src/main/java/org/apache/xalan/templates/TemplateList.java
@@ -398,6 +398,21 @@ public class TemplateList implements java.io.Serializable
 	  TemplateSubPatternAssociation association =
 			  								new TemplateSubPatternAssociation(template, null, xpathMatchPatternStr);
 
+	  QName templateModeQname = template.getMode();
+	  String templateModeStr = null;
+	  if (templateModeQname != null) {
+		  templateModeStr = templateModeQname.toString();   
+	  }
+	  if (templateModeStr != null) {
+		  /**
+		   * This allows us to store within an Hashtable m_patternTable object, 
+		   * more than one xsl:template definition object instances having 
+		   * same value of "match" attribute but with different template 
+		   * definition mode names.
+		   */
+		  xpathMatchPatternStr = (xpathMatchPatternStr + Constants.XSL3_PATTERN_TABLE_DELIM + templateModeStr);  
+	  }
+	  
 	  m_patternTable.put(xpathMatchPatternStr, association);
   }
 
diff --git a/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java b/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java
index 5714f52ec..a30cdf0aa 100644
--- a/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java
+++ b/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java
@@ -217,5 +217,15 @@ public class XslTemplateTests extends XSLTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslTemplateTest18() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test18.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test18.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test18.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
 
 }
diff --git a/src/test/resources/xsl_template/gold/test18.out b/src/test/resources/xsl_template/gold/test18.out
new file mode 100644
index 000000000..d06b27ebc
--- /dev/null
+++ b/src/test/resources/xsl_template/gold/test18.out
@@ -0,0 +1,15 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>XSL transformation result</title>
+</head>
+<body>
+<h3>Hello world, this text file is used for testing purpose</h3>
+<h1>?? Thanks for reading this</h1>
+<h3>Many thanks</h3>
+<h2> Thank you</h2>
+<h2>## Your's sincerely</h2>
+<h3>--</h3>
+<h3>Apache Xalan</h3>
+</body>
+</html>
diff --git a/src/test/resources/xsl_template/test18.xsl b/src/test/resources/xsl_template/test18.xsl
new file mode 100644
index 000000000..4a5f8f896
--- /dev/null
+++ b/src/test/resources/xsl_template/test18.xsl
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+				exclude-result-prefixes="xs"
+			    version="3.0">
+			    
+  <!-- Author: mukulg@apache.org -->
+
+  <!--  An XSL 3 stylesheet test case, to test xsl:template match 
+        with pattern ".", and ".[...]" (i.e, XPath string "." 
+        followed by an XPath predicate.
+        
+        This stylesheet also tests, related xsl:apply-templates 
+        instruction having XSL 'mode' attribute. 
+  -->			      
+
+  <xsl:output method="html"/>
+
+  <xsl:template match="/">
+      <html>
+	     <head>
+		   <title>XSL transformation result</title>
+		 </head>
+		 <body>		   
+		   <xsl:for-each select="unparsed-text-lines('input.txt')">
+		      <xsl:variable name="item1" select="." as="xs:string"/>
+		      <xsl:choose>
+			     <xsl:when test="position() eq 2">
+				    <xsl:apply-templates select="$item1" mode="m1"/>
+				 </xsl:when>
+				 <xsl:when test="position() eq 5">
+				     <xsl:apply-templates select="$item1" mode="m2"/>
+				 </xsl:when>
+				 <xsl:otherwise>
+				    <xsl:apply-templates select="$item1"/>
+				 </xsl:otherwise>
+			  </xsl:choose>
+		   </xsl:for-each>
+		 </body>
+	  </html>
+  </xsl:template>
+  
+  <xsl:template match=".[starts-with(., '==')]" mode="m1">
+    <h1><xsl:value-of select="replace(., '==', '??')"/></h1>
+  </xsl:template>
+  
+  <xsl:template match=".[starts-with(., '==')]" mode="m2">
+    <h2><xsl:value-of select="replace(., '==', '##')"/></h2>
+  </xsl:template>
+  
+  <xsl:template match=".[starts-with(., '::')]">
+    <h2><xsl:value-of select="replace(., '::', '')"/></h2>
+  </xsl:template>
+
+  <xsl:template match=".">
+    <h3><xsl:value-of select="."/></h3>
+  </xsl:template>
+  
+  <!--
+      * Licensed to the Apache Software Foundation (ASF) under one
+      * or more contributor license agreements. See the NOTICE file
+      * distributed with this work for additional information
+      * regarding copyright ownership. The ASF licenses this file
+      * to you under the Apache License, Version 2.0 (the "License");
+      * you may not use this file except in compliance with the License.
+      * You may obtain a copy of the License at
+      *
+      *     http://www.apache.org/licenses/LICENSE-2.0
+      *
+      * Unless required by applicable law or agreed to in writing, software
+      * distributed under the License is distributed on an "AS IS" BASIS,
+      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      * See the License for the specific language governing permissions and
+      * limitations under the License.
+  -->
+
+</xsl:stylesheet>


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