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 2023/09/30 12:11:01 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing improvements to implementation of xslt 3.0's xsl:iterate instruction, making it more correct. also committing few new working related test cases.

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

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


The following commit(s) were added to refs/heads/xalan-j_xslt3.0 by this push:
     new 0e3d0cae committing improvements to implementation of xslt 3.0's xsl:iterate instruction, making it more correct. also committing few new working related test cases.
     new 6c3babb1 Merge pull request #92 from mukulga/xalan-j_xslt3.0_mukul
0e3d0cae is described below

commit 0e3d0cae9c83771f55fb73be4361b3c189cfb3bf
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sat Sep 30 17:36:40 2023 +0530

    committing improvements to implementation of xslt 3.0's xsl:iterate instruction, making it more correct. also committing few new working related test cases.
---
 src/org/apache/xalan/templates/ElemIterate.java    | 297 ++++++++++-----------
 .../apache/xalan/templates/ElemIterateBreak.java   |  20 +-
 .../xalan/templates/ElemIterateNextIteration.java  | 137 +++++++---
 .../xalan/templates/ElemIterateOnCompletion.java   |  41 ++-
 src/org/apache/xalan/templates/ElemParam.java      |  47 ++--
 .../apache/xalan/transformer/TransformerImpl.java  |  26 ++
 .../xslt/util/XslTransformSharedDatastore.java     |   6 -
 tests/org/apache/xalan/xslt3/XslIterateTests.java  |  40 +++
 tests/xsl_iterate/gold/test23.out                  |   4 +
 tests/xsl_iterate/gold/test24.out                  |   9 +
 tests/xsl_iterate/gold/test25.out                  |   4 +
 tests/xsl_iterate/gold/test26.out                  |   9 +
 tests/xsl_iterate/test1_g.xml                      |   4 +
 tests/xsl_iterate/test23.xsl                       |  64 +++++
 tests/xsl_iterate/test24.xsl                       |  72 +++++
 tests/xsl_iterate/test25.xsl                       |  69 +++++
 tests/xsl_iterate/test26.xsl                       |  75 ++++++
 17 files changed, 666 insertions(+), 258 deletions(-)

diff --git a/src/org/apache/xalan/templates/ElemIterate.java b/src/org/apache/xalan/templates/ElemIterate.java
index 62765e9a..8e767d36 100644
--- a/src/org/apache/xalan/templates/ElemIterate.java
+++ b/src/org/apache/xalan/templates/ElemIterate.java
@@ -23,7 +23,6 @@ import java.util.List;
 import javax.xml.transform.TransformerException;
 
 import org.apache.xalan.transformer.TransformerImpl;
-import org.apache.xalan.xslt.util.XslTransformSharedDatastore;
 import org.apache.xml.dtm.DTM;
 import org.apache.xml.dtm.DTMIterator;
 import org.apache.xml.utils.IntStack;
@@ -32,42 +31,19 @@ import org.apache.xpath.Expression;
 import org.apache.xpath.ExpressionOwner;
 import org.apache.xpath.XPath;
 import org.apache.xpath.XPathContext;
-import org.apache.xpath.functions.DynamicFunctionCall;
-import org.apache.xpath.functions.Function;
 import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XNodeSet;
 import org.apache.xpath.objects.XObject;
-import org.apache.xpath.operations.Operation;
-import org.apache.xpath.operations.Variable;
 
-/**
- * XSLT 3.0 xsl:iterate element.
+/*
+ * Implementation of the XSLT 3.0 xsl:iterate instruction.
  * 
-   <xsl:iterate select = expression>
-      <!-- Content: (xsl:param*, xsl:on-completion?, sequence-constructor) -->
-   </xsl:iterate>
-   
-   <xsl:next-iteration>
-      <!-- Content: (xsl:with-param*) -->
-   </xsl:next-iteration>
-
-   <xsl:break select? = expression>
-      <!-- Content: sequence-constructor -->
-   </xsl:break>
-
-   <xsl:on-completion select? = expression>
-      <!-- Content: sequence-constructor -->
-   </xsl:on-completion>
-   
-   Ref : https://www.w3.org/TR/xslt-30/#iterate
-         
-   @author Mukul Gandhi <mu...@apache.org>
+ * Ref : https://www.w3.org/TR/xslt-30/#element-iterate
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
  * 
  * @xsl.usage advanced
  */
-/*
- * Implementation of the XSLT 3.0 xsl:iterate instruction.
- */
 public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
 {
 
@@ -190,9 +166,7 @@ public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
        * 
        * @xsl.usage advanced
        */
-       public void transformSelectedNodes(TransformerImpl transformer) throws TransformerException {
-    
-           final XPathContext xctxtOriginal = transformer.getXPathContext();
+       private void transformSelectedNodes(TransformerImpl transformer) throws TransformerException {
         
            XPathContext xctxt = transformer.getXPathContext();
          
@@ -202,154 +176,163 @@ public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
            // instruction's evaluation.
            fXslIterateParamWithparamDataList.clear();
            
-           validateXslElemIterateChildElementsSequence(xctxt);
-           
-           // Evaluate xsl:iterate instruction, when value of its "select" attribute evaluates 
-           // to a 'ResultSequence'. 
-           if ((m_selectExpression instanceof Variable) || 
-                                                  (m_selectExpression instanceof Operation) || 
-                                                  (m_selectExpression instanceof Function)  ||
-                                                  (m_selectExpression instanceof DynamicFunctionCall)) {
+           validateXslElemIterateChildElementsSequence(xctxt); 
                
-               XObject  evalResult = m_selectExpression.execute(xctxt);
+           XObject evalResult = m_selectExpression.execute(xctxt);                              
                
-               if (evalResult instanceof ResultSequence) {
-                   ResultSequence resultSeq = (ResultSequence)evalResult;
-                   List<XObject> resultSeqItems = resultSeq.getResultSequenceItems();                                      
+           if (evalResult instanceof ResultSequence) {
+               ResultSequence resultSeq = (ResultSequence)evalResult;
+               List<XObject> resultSeqItems = resultSeq.getResultSequenceItems();                                      
                    
-                   ElemIterateOnCompletion xslOnCompletionTemplate = null;
+               ElemIterateOnCompletion xslOnCompletionTemplate = null;
                    
-                   for (int idx = 0; idx < resultSeqItems.size(); idx++) {
-                       XObject resultSeqItem = resultSeqItems.get(idx);
-                       
-                       if (resultSeqItem instanceof XNodeSet) {
-                          resultSeqItem = ((XNodeSet)resultSeqItem).getFresh(); 
-                       }
-                       
-                       setXPathContextForXslSequenceProcessing(resultSeqItems.size(), idx, resultSeqItem, xctxt);
-                       
-                       boolean isBreakFromXslContentLoop = false;
+               boolean isBreakFromXslContentLoop = false;
+                   
+               for (int idx = 0; idx < resultSeqItems.size(); idx++) {
+                  XObject resultSeqItem = resultSeqItems.get(idx);
                        
-                       for (ElemTemplateElement elemTemplate = this.m_firstChild; elemTemplate != null; 
-                                                                             elemTemplate = elemTemplate.m_nextSibling) {
-                           if ((elemTemplate instanceof ElemIterateOnCompletion) && (xslOnCompletionTemplate == null)) {
-                               xslOnCompletionTemplate = (ElemIterateOnCompletion)elemTemplate;     
-                           }
-                           
-                           if (!(XslTransformSharedDatastore.isXslIterateBreakEvaluated).booleanValue()) {
-                               xctxt.setSAXLocator(elemTemplate);
-                               transformer.setCurrentElement(elemTemplate);
-                               elemTemplate.execute(transformer);
-                           }
-                           else {                              
-                               resetXPathContextForXslSequenceProcessing(resultSeqItem, xctxt);                               
-                               isBreakFromXslContentLoop = true;                               
-                               break;    
-                           }
-                       }
+                  if (resultSeqItem instanceof XNodeSet) {
+                     resultSeqItem = ((XNodeSet)resultSeqItem).getFresh(); 
+                  }
                        
-                       if (!isBreakFromXslContentLoop) {                         
-                          resetXPathContextForXslSequenceProcessing(resultSeqItem, xctxt);
-                       }
+                  setXPathContextForXslSequenceProcessing(resultSeqItems.size(), idx, resultSeqItem, xctxt);
+                                                                     
+                  for (ElemTemplateElement elemTemplate = this.m_firstChild; elemTemplate != null; 
+                                                                                       elemTemplate = elemTemplate.m_nextSibling) {                           
+                     if (idx == 0) {
+                          if (elemTemplate instanceof ElemParam) {
+                              // For xsl:iterate's first iteration, evaluate xsl:param element
+                              xctxt.setSAXLocator(elemTemplate);
+                              transformer.setCurrentElement(elemTemplate);
+                              ((ElemParam)elemTemplate).setXslIterateIterationIdx(idx);
+                              elemTemplate.execute(transformer);
+                          }                                
+                          else if (elemTemplate instanceof ElemIterateOnCompletion) {
+                              xslOnCompletionTemplate = (ElemIterateOnCompletion)elemTemplate;
+                          }
+                          else {
+                             if (!transformer.isXslIterateBreakEvaluated()) {
+                                xctxt.setSAXLocator(elemTemplate);
+                                transformer.setCurrentElement(elemTemplate);
+                                elemTemplate.execute(transformer);
+                             }
+                             else {                              
+                                resetXPathContextForXslSequenceProcessing(resultSeqItem, xctxt);                               
+                                isBreakFromXslContentLoop = true;                               
+                                break;    
+                             }
+                          }
+                      }
+                      else {
+                          if (!transformer.isXslIterateBreakEvaluated()) {
+                             xctxt.setSAXLocator(elemTemplate);
+                             transformer.setCurrentElement(elemTemplate);
+                             elemTemplate.execute(transformer);
+                          }
+                          else {                              
+                             resetXPathContextForXslSequenceProcessing(resultSeqItem, xctxt);                               
+                             isBreakFromXslContentLoop = true;                               
+                             break;    
+                          }
+                      }
+                  }
                        
-                       if ((XslTransformSharedDatastore.isXslIterateBreakEvaluated).booleanValue()) {                       
-                          break;   
-                       }
-                   }
+                  if (!isBreakFromXslContentLoop) {                         
+                     resetXPathContextForXslSequenceProcessing(resultSeqItem, xctxt);  
+                  }
+                  else {                          
+                     break;
+                  }
+               }
                    
-                   // Reset the, XPath context's size, item and position variables
-                   xctxt.setXPath3ContextSize(-1);
-                   xctxt.setXPath3ContextItem(null);
-                   xctxt.setXPath3ContextPosition(-1);                                      
+               // Reset the, XPath context's size, item and position variables
+               xctxt.setXPath3ContextSize(-1);
+               xctxt.setXPath3ContextItem(null);
+               xctxt.setXPath3ContextPosition(-1);                                      
                    
-                   if ((xslOnCompletionTemplate != null) && !(XslTransformSharedDatastore.
-                                                                              isXslIterateBreakEvaluated).booleanValue()) {
-                        XslTransformSharedDatastore.isXslIterateOnCompletionActive = Boolean.TRUE;
-                        xctxt.setSAXLocator(xslOnCompletionTemplate);
-                        transformer.setCurrentElement(xslOnCompletionTemplate);
-                        xslOnCompletionTemplate.execute(transformer);
-                        XslTransformSharedDatastore.isXslIterateOnCompletionActive = Boolean.FALSE;
-                  }
-
-                  XslTransformSharedDatastore.isXslIterateBreakEvaluated = Boolean.FALSE;
-                  
-                  transformer.setXPathContext(xctxtOriginal);
-                
-                  // return from this xsl:iterate instruction's evaluation
-                  return;                  
+               if ((xslOnCompletionTemplate != null) && !transformer.isXslIterateBreakEvaluated()) {
+                  transformer.setXslIterateOnCompletionActive(true);
+                  xctxt.setSAXLocator(xslOnCompletionTemplate);
+                  transformer.setCurrentElement(xslOnCompletionTemplate);
+                  xslOnCompletionTemplate.execute(transformer);
+                  transformer.setXslIterateOnCompletionActive(false);
                }
+
+               transformer.setXslIterateBreakEvaluated(false);
            }
-           
-           // Evaluate xsl:iterate instruction, when value of its "select" attribute evaluates 
-           // to a node set. 
-           DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);
+           else {
+               // Evaluate xsl:iterate instruction, when value of its "select" attribute evaluates 
+               // to a node set. 
+               DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);
         
-           try {               
-               xctxt.pushCurrentNode(DTM.NULL);
-
-               IntStack currentNodes = xctxt.getCurrentNodeStack();
-
-               xctxt.pushCurrentExpressionNode(DTM.NULL);
-
-               IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();
-
-               xctxt.pushSAXLocatorNull();
-               xctxt.pushContextNodeList(sourceNodes);
-               transformer.pushElemTemplateElement(null);                              
+               try {               
+                   xctxt.pushCurrentNode(DTM.NULL);
+                   IntStack currentNodes = xctxt.getCurrentNodeStack();
+                   xctxt.pushCurrentExpressionNode(DTM.NULL);
+                   IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();
+                   xctxt.pushSAXLocatorNull();
+                   xctxt.pushContextNodeList(sourceNodes);
+                   transformer.pushElemTemplateElement(null);                              
                           
-               int nextNode;
+                   int nextNode;
                
-               ElemIterateOnCompletion xslOnCompletionTemplate = null;
+                   ElemIterateOnCompletion xslOnCompletionTemplate = null;
                
-               while ((nextNode = sourceNodes.nextNode()) != DTM.NULL) {
-                   currentNodes.setTop(nextNode);
-                   currentExpressionNodes.setTop(nextNode);
+                   int idx = -1;
+                   while ((nextNode = sourceNodes.nextNode()) != DTM.NULL) {
+                      idx++;
+                      currentNodes.setTop(nextNode);
+                      currentExpressionNodes.setTop(nextNode);
                                                                         
-                   for (ElemTemplateElement elemTemplate = this.m_firstChild; elemTemplate != null; 
+                      for (ElemTemplateElement elemTemplate = this.m_firstChild; elemTemplate != null; 
                                                                           elemTemplate = elemTemplate.m_nextSibling) {
-                       if ((elemTemplate instanceof ElemIterateOnCompletion) && 
+                          if ((elemTemplate instanceof ElemIterateOnCompletion) && 
                                                                         (xslOnCompletionTemplate == null)) {
-                           xslOnCompletionTemplate = (ElemIterateOnCompletion)elemTemplate;     
-                       }
+                              xslOnCompletionTemplate = (ElemIterateOnCompletion)elemTemplate;     
+                          }
                        
-                       if (!(XslTransformSharedDatastore.isXslIterateBreakEvaluated).booleanValue()) {
-                           xctxt.setSAXLocator(elemTemplate);
-                           transformer.setCurrentElement(elemTemplate);
-                           elemTemplate.execute(transformer);
-                       }
-                       else {
-                           break;    
-                       }                                              
-                   }                                      
+                          if ((idx == 0) && (elemTemplate instanceof ElemParam)) {
+                              xctxt.setSAXLocator(elemTemplate);
+                              transformer.setCurrentElement(elemTemplate);
+                              ((ElemParam)elemTemplate).setXslIterateIterationIdx(idx);
+                              elemTemplate.execute(transformer); 
+                          }
+                          else {
+                              if (!transformer.isXslIterateBreakEvaluated()) {
+                                  xctxt.setSAXLocator(elemTemplate);
+                                  transformer.setCurrentElement(elemTemplate);
+                                  elemTemplate.execute(transformer);
+                              }
+                              else {
+                                  break;    
+                              }
+                          }
+                      }                                      
                    
-                   if ((XslTransformSharedDatastore.isXslIterateBreakEvaluated).booleanValue()) {                       
-                       break;   
+                      if (transformer.isXslIterateBreakEvaluated()) {
+                          break;   
+                      }
                    }
-               }
                
-               if ((xslOnCompletionTemplate != null) && !(XslTransformSharedDatastore.
-                                                                                isXslIterateBreakEvaluated).booleanValue()) {
-                    XslTransformSharedDatastore.isXslIterateOnCompletionActive = Boolean.TRUE;
-                    xctxt.setSAXLocator(xslOnCompletionTemplate);
-                    transformer.setCurrentElement(xslOnCompletionTemplate);
-                    xslOnCompletionTemplate.execute(transformer);
-                    XslTransformSharedDatastore.isXslIterateOnCompletionActive = Boolean.FALSE;
-               }
+                  if ((xslOnCompletionTemplate != null) && !transformer.isXslIterateBreakEvaluated()) {
+                       transformer.setXslIterateOnCompletionActive(true);
+                       xctxt.setSAXLocator(xslOnCompletionTemplate);
+                       transformer.setCurrentElement(xslOnCompletionTemplate);
+                       xslOnCompletionTemplate.execute(transformer);
+                       transformer.setXslIterateOnCompletionActive(false);
+                  }
                
-               XslTransformSharedDatastore.isXslIterateBreakEvaluated = Boolean.FALSE; 
-           }
-           finally {
-              xctxt.popSAXLocator();
-              xctxt.popContextNodeList();
-              transformer.popElemTemplateElement();
-              xctxt.popCurrentExpressionNode();
-              xctxt.popCurrentNode();
-              sourceNodes.detach();
-           }
-        
-           // Restore the xpath context, to where it was before this xsl:iterate 
-           // instruction began an evaluation.
-           transformer.setXPathContext(xctxtOriginal);        
+                  transformer.setXslIterateBreakEvaluated(false);
+             }
+             finally {
+                 xctxt.popSAXLocator();
+                 xctxt.popContextNodeList();
+                 transformer.popElemTemplateElement();
+                 xctxt.popCurrentExpressionNode();
+                 xctxt.popCurrentNode();
+                 sourceNodes.detach();
+             }
+          }       
       }
       
       /**
diff --git a/src/org/apache/xalan/templates/ElemIterateBreak.java b/src/org/apache/xalan/templates/ElemIterateBreak.java
index c2df8afc..e8eee619 100644
--- a/src/org/apache/xalan/templates/ElemIterateBreak.java
+++ b/src/org/apache/xalan/templates/ElemIterateBreak.java
@@ -20,7 +20,6 @@ package org.apache.xalan.templates;
 import javax.xml.transform.TransformerException;
 
 import org.apache.xalan.transformer.TransformerImpl;
-import org.apache.xalan.xslt.util.XslTransformSharedDatastore;
 import org.apache.xml.serializer.SerializationHandler;
 import org.apache.xpath.Expression;
 import org.apache.xpath.ExpressionOwner;
@@ -28,21 +27,14 @@ import org.apache.xpath.XPath;
 import org.apache.xpath.XPathContext;
 import org.xml.sax.SAXException;
 
-/**
- * XSLT 3.0 xsl:break element.
- * 
-   <xsl:break select? = expression>
-      <!-- Content: sequence-constructor -->
-   </xsl:break>
-         
-   @author Mukul Gandhi <mu...@apache.org>
- * 
- * @xsl.usage advanced
- */
 /*
  * Implementation of the XSLT 3.0 xsl:break instruction.
  * 
- * The XSLT xsl:break element is intended to be used, within xsl:iterate element.
+ * Ref : https://www.w3.org/TR/xslt-30/#element-iterate
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
  */
 public class ElemIterateBreak extends ElemTemplateElement implements ExpressionOwner
 {
@@ -169,7 +161,7 @@ public class ElemIterateBreak extends ElemTemplateElement implements ExpressionO
                       
             if (isXslBreakDescendantOfXslIterate && isXslInstructionInTailPositionOfSequenceConstructor(this)) {              
                 transformXslBreakInstruction(transformer);
-                XslTransformSharedDatastore.isXslIterateBreakEvaluated = Boolean.TRUE;
+                transformer.setXslIterateBreakEvaluated(true);
             }
             else {
                 throw new TransformerException("XTSE3120 : an xsl:break instruction is not in a "
diff --git a/src/org/apache/xalan/templates/ElemIterateNextIteration.java b/src/org/apache/xalan/templates/ElemIterateNextIteration.java
index 3ceaa4ad..23a35516 100644
--- a/src/org/apache/xalan/templates/ElemIterateNextIteration.java
+++ b/src/org/apache/xalan/templates/ElemIterateNextIteration.java
@@ -33,31 +33,20 @@ import org.apache.xpath.objects.XObject;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-/**
- * XSLT 3.0 xsl:next-iteration element.
- *    
-   <xsl:next-iteration>
-      <!-- Content: (xsl:with-param*) -->
-   </xsl:next-iteration>
-         
-   @author Mukul Gandhi <mu...@apache.org>
- * 
- * @xsl.usage advanced
- */
 /*
  * Implementation of the XSLT 3.0 xsl:next-iteration instruction.
  * 
- * The XSLT xsl:next-iteration element is intended to be used, within 
- * xsl:iterate element.
+ * Ref : https://www.w3.org/TR/xslt-30/#element-iterate
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
  */
 public class ElemIterateNextIteration extends ElemTemplateElement implements ExpressionOwner
 {
     
      private static final long serialVersionUID = -582877657433106548L;
      
-     // revisit.
-     // can we have better way to maintain xsl:next-iteration->xsl:with-param* state, instead of having this with
-     // 'public static' visibility.
      public static List<XslIterateParamWithparamData> fWithparamList = new ArrayList<XslIterateParamWithparamData>();
 
      /**
@@ -164,25 +153,20 @@ public class ElemIterateNextIteration extends ElemTemplateElement implements Exp
        {
            
             XPathContext xpathContext = transformer.getXPathContext();
-  
-            boolean isXslNextIterationDescendantOfXslIterate = false;
             
-            if (isXslNextIterationDescendantOfXslIterate(this)) {
-                isXslNextIterationDescendantOfXslIterate = true;       
-            }
-            else {
-                throw new TransformerException("XTSE3120 : an xsl:next-iteration instruction doesn't "
-                                                                + "have xsl:iterate instruction as ancestor.", 
-                                                                                       xpathContext.getSAXLocator());  
+            if (!isXslNextIterationDescendantOfXslIterate(this)) {
+                throw new TransformerException("XTSE3120 : An xsl:next-iteration instruction doesn't "
+                                                                                + "have xsl:iterate instruction as an ancestor.", 
+                                                                                      xpathContext.getSAXLocator()); 
             }
             
-            if (isXslNextIterationDescendantOfXslIterate && isXslInstructionInTailPositionOfSequenceConstructor(this)) {
+            if (isXslInstructionInTailPositionOfSequenceConstructor(this)) {
                 elemIterateNextIterationProcessing(transformer);
             }
             else {
                 throw new TransformerException("XTSE3120 : an xsl:next-iteration instruction is not in a "
-                                                                + "tail position within the sequence constructor of currently "
-                                                                + "active xsl:iterate instruction.", xpathContext.getSAXLocator());   
+                                                                                           + "tail position within the sequence constructor of currently "
+                                                                                           + "active xsl:iterate instruction.", xpathContext.getSAXLocator());   
             }
        }
        
@@ -193,14 +177,14 @@ public class ElemIterateNextIteration extends ElemTemplateElement implements Exp
         * 
         * @xsl.usage advanced
         */
-        public void elemIterateNextIterationProcessing(TransformerImpl transformer) throws 
-                                                                               TransformerException {
+        private void elemIterateNextIterationProcessing(TransformerImpl transformer) throws 
+                                                                                 TransformerException {
             
             XPathContext xctxt = transformer.getXPathContext();
             
             int contextNode = xctxt.getContextNode();
             
-            // clear the, xsl:next-iteration->xsl:with-param* list storage before
+            // Clear the, xsl:next-iteration->xsl:with-param* list storage before
             // evaluating this xsl:next-iteration element.
             fWithparamList.clear();
             
@@ -227,7 +211,7 @@ public class ElemIterateNextIteration extends ElemTemplateElement implements Exp
             
             if ((ElemIterate.fXslIterateParamWithparamDataList).size() != fWithparamList.size()) {
                 throw new TransformerException("XTSE0580 : within xsl:iterate, the number of xsl:param elements are not equal to "
-                                                               + "number of xsl:next-iteration's xsl:with-param elements.", xctxt.getSAXLocator());     
+                                                                + "number of xsl:next-iteration's xsl:with-param elements.", xctxt.getSAXLocator());     
             }
             else {
                for (int idx = 0; idx < (ElemIterate.fXslIterateParamWithparamDataList).size(); idx ++) {
@@ -235,23 +219,100 @@ public class ElemIterateNextIteration extends ElemTemplateElement implements Exp
                    XslIterateParamWithparamData withParamData = fWithparamList.get(idx);
                    if (!(paramData.getNameVal()).equals(withParamData.getNameVal())) {
                        throw new TransformerException("XTSE3130 : within xsl:iterate, xsl:param and xsl:with-param names at position " + 
-                                                                                              (idx + 1) + " are not same.", xctxt.getSAXLocator());        
+                                                                                                  (idx + 1) + " are not same.", xctxt.getSAXLocator());        
                    }
                }
             }
             
+            // Update all of xsl:iterate's xsl:param values, using the corresponding
+            // xsl:next-iteration's xsl:with-param values. The code within 'for' loop below,
+            // updates each of the xsl:iterate->xsl:param's values for xsl:iterate's second and 
+            // greater iterations. For xsl:iterate's first iteration, xsl:param's get their
+            // values from the xsl:param instructions themselves.
             VariableStack varStack = xctxt.getVarStack();
             for (int idx = 0; idx < fWithparamList.size(); idx++) {
                 XslIterateParamWithparamData withParamData = fWithparamList.get(idx);
+                                                
+                QName xslParamQName = withParamData.getNameVal();                
+                ElemParam elemParam = getElemParamForQName(xslParamQName);
                 XPath withParamSelectVal = withParamData.getSelectVal();                               
-                XObject evalResult = withParamSelectVal.execute(xctxt, contextNode, this);
-                // update value of current xsl:next-iteration's current xsl:param 
-                // 'parameter'. when xsl:iterate's new iteration is entered, this
-                // parameter shall have this new value.
-                varStack.setLocalVariable(idx, evalResult);
+                XObject withParamVal = withParamSelectVal.execute(xctxt, contextNode, this);
+                varStack.setLocalVariable(elemParam.getIndex(), withParamVal);
             }
         }
         
+        /*
+         * For the currently active xsl:next-iteration instruction, find reference to
+         * its xsl:iterate->xsl:param element for a given xsl:iterate->xsl:param's name.
+         * 
+         * We find this xsl:param element reference, by xsl element traversal on
+         * preceding-sibling and ancestor axes directions starting from the current
+         * xsl:next-iteration instruction.
+         * 
+         * This method shall always find, an eligible non-null xsl:iterate->xsl:param 
+         * element reference for a given xsl:iterate->xsl:param's name.
+         */
+        private ElemParam getElemParamForQName(QName xslParamQName) {
+           ElemParam elemParam = null;
+           
+           // First, we search for the desired xsl:param element on the preceding-sibling 
+           // axis direction.
+           ElemTemplateElement prevSibling = (ElemTemplateElement)getPreviousSibling();
+           while (prevSibling != null) {
+              if (prevSibling instanceof ElemParam) {
+                 ElemParam elemParamTemp = (ElemParam)prevSibling;
+                 if ((elemParamTemp.getName()).equals(xslParamQName)) {
+                    elemParam = elemParamTemp;
+                    break; 
+                 }
+                 else {
+                    prevSibling = (ElemTemplateElement)(prevSibling.getPreviousSibling()); 
+                 }
+              }
+              else {
+                 prevSibling = (ElemTemplateElement)(prevSibling.getPreviousSibling()); 
+              }
+           }
+           
+           // The desired xsl:param element was not found, on the preceding-sibling axis
+           // direction. Now, we attempt a new search for desired xsl:param element 
+           // on the ancestor axis direction. 
+           if (elemParam == null) {
+              ElemTemplateElement parentElem = getParentElem();
+              while (parentElem != null) {
+                 if (parentElem instanceof ElemIterate) {
+                    ElemTemplateElement elemIterateChild = (ElemTemplateElement)(parentElem.getFirstChild());
+                    boolean isToBreakFromCheck = false;
+                    while (elemIterateChild != null) {
+                        if (elemIterateChild instanceof ElemParam) {
+                           ElemParam elemParamTemp = (ElemParam)elemIterateChild;
+                           if ((elemParamTemp.getName()).equals(xslParamQName)) {
+                               elemParam = elemParamTemp;
+                               isToBreakFromCheck = true;
+                               break;
+                           }
+                           else {
+                              elemIterateChild = elemIterateChild.getNextSiblingElem();
+                           }
+                        }
+                        else {
+                           elemIterateChild = elemIterateChild.getNextSiblingElem(); 
+                        }
+                    }
+                    
+                    if (isToBreakFromCheck) {
+                       break; 
+                    }
+                 }
+                 else {
+                    parentElem = parentElem.getParentElem();
+                 }
+              }
+           }
+           
+           return elemParam;
+        }
+        
         /*
          * Determine whether, an xsl:next-iteration instruction has xsl:iterate instruction 
          * as ancestor. 
diff --git a/src/org/apache/xalan/templates/ElemIterateOnCompletion.java b/src/org/apache/xalan/templates/ElemIterateOnCompletion.java
index 1e51ed95..781d7bf0 100644
--- a/src/org/apache/xalan/templates/ElemIterateOnCompletion.java
+++ b/src/org/apache/xalan/templates/ElemIterateOnCompletion.java
@@ -20,7 +20,6 @@ package org.apache.xalan.templates;
 import javax.xml.transform.TransformerException;
 
 import org.apache.xalan.transformer.TransformerImpl;
-import org.apache.xalan.xslt.util.XslTransformSharedDatastore;
 import org.apache.xml.serializer.SerializationHandler;
 import org.apache.xpath.Expression;
 import org.apache.xpath.ExpressionOwner;
@@ -30,22 +29,14 @@ import org.xml.sax.SAXException;
 
 import com.sun.org.apache.xml.internal.dtm.DTM;
 
-/**
- * XSLT 3.0 xsl:on-completion element.
- * 
-   <xsl:on-completion select? = expression>
-      <!-- Content: sequence-constructor -->
-   </xsl:on-completion>
-         
-   @author Mukul Gandhi <mu...@apache.org>
- * 
- * @xsl.usage advanced
- */
 /*
  * Implementation of the XSLT 3.0 xsl:on-completion instruction.
  * 
- * The XSLT xsl:on-completion element is intended to be used, within 
- * xsl:iterate element.
+ * Ref : https://www.w3.org/TR/xslt-30/#element-iterate
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
  */
 public class ElemIterateOnCompletion extends ElemTemplateElement implements ExpressionOwner
 {
@@ -167,16 +158,15 @@ public class ElemIterateOnCompletion extends ElemTemplateElement implements Expr
        * 
        * @xsl.usage advanced
        */
-       public void transformXslOncompletionInstruction(TransformerImpl transformer) throws 
-                                                                               TransformerException {
+       private void transformXslOncompletionInstruction(TransformerImpl transformer) 
+                                                                                  throws TransformerException {
                                                                   
-           if ((XslTransformSharedDatastore.isXslIterateOnCompletionActive).booleanValue()) {
-               final XPathContext originalXctxt = transformer.getXPathContext();
-               
+           if (transformer.isXslIterateOnCompletionActive()) {               
                XPathContext xctxt = transformer.getXPathContext();
                
-               // during evaluation of xsl:on-completion, the context item is absent.
-               // we make following two changes to XPath context to ensure this.
+               // During evaluation of xsl:on-completion instruction, the XPath context item
+               // is absent. We make following two changes to an active XPath context to
+               // ensure this.
                xctxt.pushCurrentNode(DTM.NULL);
                xctxt.pushCurrentExpressionNode(DTM.NULL);
                
@@ -185,9 +175,11 @@ public class ElemIterateOnCompletion extends ElemTemplateElement implements Expr
                    
                    try {
                        m_selectExpression.executeCharsToContentHandler(xctxt, rth);
-                   } catch (TransformerException ex) {
+                   } 
+                   catch (TransformerException ex) {
                        throw ex;
-                   } catch (SAXException ex) {
+                   } 
+                   catch (SAXException ex) {
                        throw new TransformerException(ex);
                    }
                }
@@ -199,9 +191,6 @@ public class ElemIterateOnCompletion extends ElemTemplateElement implements Expr
                       elemTemplate.execute(transformer);
                    } 
                }
-               
-               // restore the XPath original context, on current XSLT transformer object
-               transformer.setXPathContext(originalXctxt);
            }                      
        }
       
diff --git a/src/org/apache/xalan/templates/ElemParam.java b/src/org/apache/xalan/templates/ElemParam.java
index bf4033ca..d9273360 100644
--- a/src/org/apache/xalan/templates/ElemParam.java
+++ b/src/org/apache/xalan/templates/ElemParam.java
@@ -42,9 +42,15 @@ public class ElemParam extends ElemVariable
   static final long serialVersionUID = -1131781475589006431L;
   
   int m_qnameID;
+  
+  /**
+   * This class field, supports evaluation of stylesheet 
+   * xsl:iterate->xsl:param elements.
+   */
+  private int xslIterateIterationIdx = -1;
 
   /**
-   * Constructor ElemParam
+   * Constructor ElemParam.
    *
    */
   public ElemParam(){}
@@ -117,27 +123,27 @@ public class ElemParam extends ElemVariable
     
     SourceLocator srcLocator = xctx.getSAXLocator();
     
-    String asAttrVal = getAs();
+    boolean isChildElemOfXslElemIterate = false;
+    if (getParentElem() instanceof ElemIterate) {
+       isChildElemOfXslElemIterate = true; 
+    }
     
-    if(!vars.isLocalSet(m_index)) {
-        // The caller of this stylesheet callable component, didn't provide the 
-        // parameter value via xsl:with-param instruction.
-        
-        // We'll determine the parameter's value by evaluating either the parameter's
-        // 'select' attribute, or the contained sequence constructor within xsl:param 
-        // element.
+    if (!vars.isLocalSet(m_index) || (isChildElemOfXslElemIterate && (xslIterateIterationIdx == 0))) {
+        // The caller of an stylesheet callable component (associated with this xsl:param element), 
+        // didn't provide xsl:param's value via xsl:with-param instruction.
         
         int sourceNode = transformer.getXPathContext().getCurrentNode();
         
         try {
            XObject var = getValue(transformer, sourceNode);
-           if (var == null) {
+           if (var != null) {
+              transformer.getXPathContext().getVarStack().setLocalVariable(m_index, var);    
+           }
+           else {              
               throw new TransformerException("XTTE0590 : The value to parameter " + m_qname.toString() + " cannot be assigned. "
                                                                              + "Either an input content for parameter is not available within "
-                                                                             + "stylesheet context, or parameter's value cannot be cast to an expected type.", srcLocator);  
+                                                                             + "stylesheet context, or parameter's value cannot be cast to an expected type.", srcLocator);
            }
-           
-           transformer.getXPathContext().getVarStack().setLocalVariable(m_index, var);
         }
         catch (TransformerException ex) {
             throw new TransformerException("XTTE0590 : The value to parameter " + m_qname.toString() + " cannot be assigned. "
@@ -146,12 +152,13 @@ public class ElemParam extends ElemVariable
         }
     }
     else {
-        // The caller of this stylesheet callable component, has provided the 
-        // parameter's value via xsl:with-param instruction.
+        // The caller of an stylesheet callable component (associated with this xsl:param element), 
+        // has provided xsl:param's value via xsl:with-param instruction.
         
-        // If the xsl:param instruction has 'as' attribute, we'll check below
-        // whether the parameter's value conforms to the sequence type specified by
+        // If the xsl:param instruction has an 'as' attribute, we check below
+        // whether xsl:param's value conforms to the sequence type specified by
         // xsl:param's 'as' attribute.
+        String asAttrVal = getAs();
         
         if (asAttrVal != null) {
           try {
@@ -172,9 +179,15 @@ public class ElemParam extends ElemVariable
        }
     }
     
+    // Reset this class field
+    xslIterateIterationIdx = -1;
     
     if (transformer.getDebug())
       transformer.getTraceManager().fireTraceEndEvent(this);
   }
   
+  public void setXslIterateIterationIdx(int iterationIdx) {
+     xslIterateIterationIdx = iterationIdx;   
+  }
+  
 }
diff --git a/src/org/apache/xalan/transformer/TransformerImpl.java b/src/org/apache/xalan/transformer/TransformerImpl.java
index 7c35fdd8..75e585a8 100644
--- a/src/org/apache/xalan/transformer/TransformerImpl.java
+++ b/src/org/apache/xalan/transformer/TransformerImpl.java
@@ -363,6 +363,16 @@ public class TransformerImpl extends Transformer
 
   /** NEEDSDOC Field m_shouldReset          */
   private boolean m_shouldReset = true;
+  
+  /**
+   * A class field, to support xsl:iterate instruction evaluation.
+   */
+  private boolean isXslIterateBreakEvaluated = false;
+  
+  /**
+   * A class field, to support xsl:iterate instruction evaluation.
+   */
+  private boolean isXslIterateOnCompletionActive = false;
 
   /**
    * NEEDSDOC Method setShouldReset 
@@ -3789,5 +3799,21 @@ public class TransformerImpl extends Transformer
         return m_source_location;
     }
 
+    public boolean isXslIterateBreakEvaluated() {
+        return isXslIterateBreakEvaluated;
+    }
+
+    public void setXslIterateBreakEvaluated(boolean isXslIterateBreakEvaluated) {
+        this.isXslIterateBreakEvaluated = isXslIterateBreakEvaluated;
+    }
+
+    public boolean isXslIterateOnCompletionActive() {
+        return isXslIterateOnCompletionActive;
+    }
+
+    public void setXslIterateOnCompletionActive(boolean isXslIterateOnCompletionActive) {
+        this.isXslIterateOnCompletionActive = isXslIterateOnCompletionActive;
+    }
+
 }  // end TransformerImpl class
 
diff --git a/src/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java b/src/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java
index c6c67fac..5ac34555 100644
--- a/src/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java
+++ b/src/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java
@@ -27,11 +27,5 @@ public class XslTransformSharedDatastore {
     
     // XSLT document's uri, used for error reporting
     public static String xslSystemId;
-    
-    // To support xsl:iterate instruction evaluation
-    public static Boolean isXslIterateBreakEvaluated = Boolean.FALSE;
-    
-    // To support xsl:iterate instruction evaluation
-    public static Boolean isXslIterateOnCompletionActive = Boolean.FALSE;
 
 }
diff --git a/tests/org/apache/xalan/xslt3/XslIterateTests.java b/tests/org/apache/xalan/xslt3/XslIterateTests.java
index 761bba01..61faffdc 100644
--- a/tests/org/apache/xalan/xslt3/XslIterateTests.java
+++ b/tests/org/apache/xalan/xslt3/XslIterateTests.java
@@ -290,5 +290,45 @@ public class XslIterateTests extends XslTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslIterateTest25() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test23.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test23.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test23.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslIterateTest26() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test24.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test24.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test24.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslIterateTest27() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test25.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test25.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test25.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslIterateTest28() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_g.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test26.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test26.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
 
 }
diff --git a/tests/xsl_iterate/gold/test23.out b/tests/xsl_iterate/gold/test23.out
new file mode 100644
index 00000000..439348bf
--- /dev/null
+++ b/tests/xsl_iterate/gold/test23.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <factorial num="5">120</factorial>
+  <factorial num="6">720</factorial>
+</result>
diff --git a/tests/xsl_iterate/gold/test24.out b/tests/xsl_iterate/gold/test24.out
new file mode 100644
index 00000000..bed9f2e2
--- /dev/null
+++ b/tests/xsl_iterate/gold/test24.out
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <factorial num="1">1</factorial>
+  <factorial num="2">2</factorial>
+  <factorial num="3">6</factorial>
+  <factorial num="4">24</factorial>
+  <factorial num="5">120</factorial>
+  <factorial num="6">720</factorial>
+  <factorial num="7">5040</factorial>
+</result>
diff --git a/tests/xsl_iterate/gold/test25.out b/tests/xsl_iterate/gold/test25.out
new file mode 100644
index 00000000..439348bf
--- /dev/null
+++ b/tests/xsl_iterate/gold/test25.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <factorial num="5">120</factorial>
+  <factorial num="6">720</factorial>
+</result>
diff --git a/tests/xsl_iterate/gold/test26.out b/tests/xsl_iterate/gold/test26.out
new file mode 100644
index 00000000..bed9f2e2
--- /dev/null
+++ b/tests/xsl_iterate/gold/test26.out
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <factorial num="1">1</factorial>
+  <factorial num="2">2</factorial>
+  <factorial num="3">6</factorial>
+  <factorial num="4">24</factorial>
+  <factorial num="5">120</factorial>
+  <factorial num="6">720</factorial>
+  <factorial num="7">5040</factorial>
+</result>
diff --git a/tests/xsl_iterate/test1_g.xml b/tests/xsl_iterate/test1_g.xml
new file mode 100644
index 00000000..7931220e
--- /dev/null
+++ b/tests/xsl_iterate/test1_g.xml
@@ -0,0 +1,4 @@
+<info>
+  <from>1</from>
+  <to>7</to>
+</info>
\ No newline at end of file
diff --git a/tests/xsl_iterate/test23.xsl b/tests/xsl_iterate/test23.xsl
new file mode 100644
index 00000000..33414d0a
--- /dev/null
+++ b/tests/xsl_iterate/test23.xsl
@@ -0,0 +1,64 @@
+<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 XSLT stylesheet test case, to test xsl:iterate instruction. -->                
+                
+  <xsl:output method="xml" indent="yes"/>
+  
+  <xsl:template match="/">     
+     <result>
+        <!-- Evaluate factorial of a positive integer value. -->
+        <xsl:variable name="inpNum" select="5" as="xs:integer"/>        
+        <xsl:iterate select="2 to $inpNum">
+	       <xsl:param name="result" select="1" as="xs:integer"/>
+	       <xsl:on-completion>
+	          <factorial num="{$inpNum}">
+	   	         <xsl:value-of select="$result"/>
+     	      </factorial>
+	       </xsl:on-completion>
+	       <xsl:variable name="currVal" select="."/>
+	       <xsl:next-iteration>
+	          <xsl:with-param name="result" select="$result * $currVal" as="xs:integer"/>
+	       </xsl:next-iteration>
+        </xsl:iterate>
+
+        <!-- Evaluate factorial of another positive integer value. -->
+        <xsl:variable name="inpNum" select="6" as="xs:integer"/>         
+	    <xsl:iterate select="2 to $inpNum">
+           <xsl:param name="result" select="1" as="xs:integer"/>
+	       <xsl:on-completion>
+              <factorial num="{$inpNum}">
+		         <xsl:value-of select="$result"/>
+	          </factorial>
+	       </xsl:on-completion>
+	       <xsl:variable name="currVal" select="."/>
+	       <xsl:next-iteration>
+	          <xsl:with-param name="result" select="$result * $currVal" as="xs:integer"/>
+           </xsl:next-iteration>
+        </xsl:iterate>
+     </result>
+  </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>
\ No newline at end of file
diff --git a/tests/xsl_iterate/test24.xsl b/tests/xsl_iterate/test24.xsl
new file mode 100644
index 00000000..25a3f2f0
--- /dev/null
+++ b/tests/xsl_iterate/test24.xsl
@@ -0,0 +1,72 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                xmlns:fn0="http://fn0"
+                exclude-result-prefixes="xs fn0"
+                version="3.0">
+                
+  <!-- Author: mukulg@apache.org -->
+  
+  <!-- An XSLT stylesheet test case, to test xsl:iterate instruction. -->                
+                
+  <xsl:output method="xml" indent="yes"/>
+  
+  <xsl:template match="/">     
+     <result>
+        <!-- Evaluate factorial of various positive integer values,
+             provided by xsl:for-each instruction.
+        -->
+        <xsl:for-each select="1 to 7">
+          <xsl:variable name="num" select="." as="xs:integer"/>
+          <xsl:copy-of select="fn0:factorial($num)"/>
+        </xsl:for-each>
+     </result>
+  </xsl:template>
+  
+  <!-- A stylesheet function, to evaluate factorial of a positive 
+       integer value. 
+  -->
+  <xsl:function name="fn0:factorial" as="element(factorial)">
+     <xsl:param name="inpNum" as="xs:integer"/>
+
+     <xsl:choose>
+        <xsl:when test="$inpNum = 1">
+          <factorial num="{$inpNum}">
+	         <xsl:value-of select="1"/>
+     	  </factorial>
+        </xsl:when>
+        <xsl:otherwise>
+           <xsl:iterate select="2 to $inpNum">
+              <xsl:param name="result" select="1" as="xs:integer"/>
+              <xsl:on-completion>
+	             <factorial num="{$inpNum}">
+	                <xsl:value-of select="$result"/>
+	     	     </factorial>
+	          </xsl:on-completion>
+              <xsl:variable name="currVal" select="."/>
+              <xsl:next-iteration>
+     	         <xsl:with-param name="result" select="$result * $currVal" as="xs:integer"/>
+              </xsl:next-iteration>
+           </xsl:iterate>
+        </xsl:otherwise>
+     </xsl:choose>
+  </xsl:function>
+  
+  <!--
+      * 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>
\ No newline at end of file
diff --git a/tests/xsl_iterate/test25.xsl b/tests/xsl_iterate/test25.xsl
new file mode 100644
index 00000000..b29c3b9f
--- /dev/null
+++ b/tests/xsl_iterate/test25.xsl
@@ -0,0 +1,69 @@
+<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 XSLT stylesheet test case, to test xsl:iterate instruction. -->                
+                
+  <xsl:output method="xml" indent="yes"/>
+  
+  <xsl:template match="/">     
+     <result>
+        <!-- Evaluate factorial of a positive integer value, by invoking a 
+             stylesheet named template. 
+        -->
+        <xsl:variable name="inpNum" select="5" as="xs:integer"/>
+        <xsl:call-template name="factorial">
+           <xsl:with-param name="inpNum" select="$inpNum" as="xs:integer"/>
+        </xsl:call-template>
+        
+        <!-- Evaluate factorial of another positive integer value, by invoking a 
+             stylesheet named template. 
+        -->
+	    <xsl:variable name="inpNum" select="6" as="xs:integer"/>
+	    <xsl:call-template name="factorial">
+	       <xsl:with-param name="inpNum" select="$inpNum" as="xs:integer"/>
+        </xsl:call-template>
+     </result>
+  </xsl:template>
+  
+  <!-- A stylesheet named template, to evaluate factorial of a positive 
+       integer value. 
+  -->
+  <xsl:template name="factorial" as="element(factorial)">
+     <xsl:param name="inpNum" as="xs:integer"/>
+     <xsl:iterate select="2 to $inpNum">
+       <xsl:param name="result" select="1" as="xs:integer"/>       
+       <xsl:on-completion>
+       	  <factorial num="{$inpNum}">
+       	     <xsl:value-of select="$result"/>
+       	  </factorial>
+       </xsl:on-completion>
+       <xsl:variable name="currVal" select="."/>
+       <xsl:next-iteration>
+  	      <xsl:with-param name="result" select="$result * $currVal" as="xs:integer"/>
+       </xsl:next-iteration>
+     </xsl:iterate>
+  </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>
\ No newline at end of file
diff --git a/tests/xsl_iterate/test26.xsl b/tests/xsl_iterate/test26.xsl
new file mode 100644
index 00000000..ca721a8d
--- /dev/null
+++ b/tests/xsl_iterate/test26.xsl
@@ -0,0 +1,75 @@
+<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 -->
+  
+  <!-- use with test1_g.xml -->
+  
+  <!-- An XSLT stylesheet test case, to test xsl:iterate instruction. -->                 
+                
+  <xsl:output method="xml" indent="yes"/>
+  
+  <xsl:template match="/info">     
+     <result>
+        <!-- Evaluate factorial of various positive integer values,
+             provided by xsl:for-each instruction.
+        -->
+        <xsl:for-each select="xs:integer(from) to xs:integer(to)">
+           <xsl:variable name="inpNum" select="."/>
+           <xsl:call-template name="factorial">
+              <xsl:with-param name="inpNum" select="$inpNum" as="xs:integer"/>
+           </xsl:call-template>
+	    </xsl:for-each>
+     </result>
+  </xsl:template>
+  
+  <!-- A stylesheet named template, to evaluate factorial of a positive 
+       integer value. 
+  -->
+  <xsl:template name="factorial" as="element(factorial)">
+     <xsl:param name="inpNum" as="xs:integer"/>
+     
+     <xsl:choose>
+        <xsl:when test="$inpNum = 1">
+           <factorial num="{$inpNum}">
+     	      <xsl:value-of select="1"/>
+           </factorial>
+        </xsl:when>
+        <xsl:otherwise>
+           <xsl:iterate select="2 to $inpNum">
+              <xsl:param name="result" select="1" as="xs:integer"/>              
+              <xsl:on-completion>
+	             <factorial num="{$inpNum}">
+	                <xsl:value-of select="$result"/>
+	             </factorial>
+              </xsl:on-completion>
+              <xsl:variable name="currVal" select="."/>
+              <xsl:next-iteration>
+          	      <xsl:with-param name="result" select="$result * $currVal"/>
+              </xsl:next-iteration>
+           </xsl:iterate>
+        </xsl:otherwise>
+     </xsl:choose>
+  </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>
\ No newline at end of file


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