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/08/17 17:02:39 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing few implementation enhancements to, few of xslt 3.0 language feature implementations. committing few related working test cases as well. minor improvements to, codebase comments as well within xalanj implementation on this branch.

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 ac280f5f committing few implementation enhancements to, few of xslt 3.0 language feature implementations. committing few related working test cases as well. minor improvements to, codebase comments as well within xalanj implementation on this branch.
     new 43cb0a7c Merge pull request #53 from mukulga/xalan-j_xslt3.0_mukul
ac280f5f is described below

commit ac280f5fe49e1a3c56cb839f66739b7a27f425de
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Thu Aug 17 22:27:38 2023 +0530

    committing few implementation enhancements to, few of xslt 3.0 language feature implementations. committing few related working test cases as well. minor improvements to, codebase comments as well within xalanj implementation on this branch.
---
 src/org/apache/xalan/templates/ElemForEach.java    |  8 ++-
 .../apache/xalan/templates/ElemForEachGroup.java   | 84 ++++++++++++++++------
 src/org/apache/xalan/templates/ElemIterate.java    | 23 +++---
 .../xalan/templates/ElemTemplateElement.java       | 26 +++----
 src/org/apache/xpath/composite/QuantifiedExpr.java | 26 +++----
 .../xpath/composite/SimpleSequenceConstructor.java |  4 +-
 .../xalan/xpath3/SequenceConstructorTests.java     | 40 +++++++++++
 tests/sequence_constructor/gold/test10.out         | 30 ++++++++
 tests/sequence_constructor/gold/test11.out         | 50 +++++++++++++
 tests/sequence_constructor/test13.xsl              | 57 +++++++++++++++
 tests/sequence_constructor/test14.xsl              | 57 +++++++++++++++
 tests/sequence_constructor/test15.xsl              | 58 +++++++++++++++
 tests/sequence_constructor/test16.xsl              | 57 +++++++++++++++
 tests/sequence_constructor/test1_f.xml             | 26 +++++++
 14 files changed, 486 insertions(+), 60 deletions(-)

diff --git a/src/org/apache/xalan/templates/ElemForEach.java b/src/org/apache/xalan/templates/ElemForEach.java
index 6d82377a..2195a04f 100644
--- a/src/org/apache/xalan/templates/ElemForEach.java
+++ b/src/org/apache/xalan/templates/ElemForEach.java
@@ -42,6 +42,7 @@ import org.apache.xpath.composite.SimpleSequenceConstructor;
 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;
@@ -608,7 +609,7 @@ public class ElemForEach extends ElemTemplateElement implements ExpressionOwner
     * mentioned within body of current xsl:for-each element.
     */
    private void processResultSequence(TransformerImpl transformer,
-                                      XPathContext xctxt, XObject evalResult) 
+                                                              XPathContext xctxt, XObject evalResult) 
                                                               throws TransformerException {       
        ResultSequence resultSeq = (ResultSequence)evalResult;
        List<XObject> resultSeqItems = resultSeq.getResultSequenceItems();
@@ -616,6 +617,10 @@ public class ElemForEach extends ElemTemplateElement implements ExpressionOwner
        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);
            
            for (ElemTemplateElement elemTemplateElem = this.m_firstChild; elemTemplateElem != null; 
@@ -625,7 +630,6 @@ public class ElemForEach extends ElemTemplateElement implements ExpressionOwner
               elemTemplateElem.execute(transformer);              
            }
            
-           // reset the, XPath context details
            resetXPathContextForXslSequenceProcessing(resultSeqItem, xctxt);
        }
    }
diff --git a/src/org/apache/xalan/templates/ElemForEachGroup.java b/src/org/apache/xalan/templates/ElemForEachGroup.java
index 19c85723..d47571e6 100644
--- a/src/org/apache/xalan/templates/ElemForEachGroup.java
+++ b/src/org/apache/xalan/templates/ElemForEachGroup.java
@@ -35,14 +35,20 @@ import org.apache.xalan.transformer.ForEachGroupXslSortSorter;
 import org.apache.xalan.transformer.TransformerImpl;
 import org.apache.xml.dtm.DTM;
 import org.apache.xml.dtm.DTMIterator;
+import org.apache.xml.utils.NodeVector;
 import org.apache.xpath.Expression;
 import org.apache.xpath.ExpressionOwner;
 import org.apache.xpath.XPath;
 import org.apache.xpath.XPathContext;
+import org.apache.xpath.axes.NodeSequence;
+import org.apache.xpath.composite.SimpleSequenceConstructor;
+import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XBoolean;
+import org.apache.xpath.objects.XNodeSet;
 import org.apache.xpath.objects.XNumber;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XString;
+import org.apache.xpath.operations.Variable;
 
 /**
  *  XSLT 3.0 for-each-group element.
@@ -71,30 +77,17 @@ import org.apache.xpath.objects.XString;
      
     There are following two XSLT 3.0 grouping functions,
     1) fn:current-group()     
-    2) fn:current-grouping-key()     
+    2) fn:current-grouping-key()
+    
+    Ref : https://www.w3.org/TR/xslt-30/#xsl-for-each-group
   
    @author Mukul Gandhi <mu...@apache.org>
   
    @xsl.usage advanced
 */
-
-/* 
-   Implementation of the XSLT 3.0 xsl:for-each-group instruction.
- 
-   The xsl:for-each-group's grouping attributes are as described below (and are further defined
-   within XSLT 3.0 spec),
-   
-   The xsl:for-each-group element can have following grouping attributes : "group-by", "group-adjacent", 
-   "group-starting-with", "group-ending-with". These xsl:for-each-group grouping attributes are 
-   mutually exclusive. i.e one of these is required and two or more of these is an error within 
-   the XSLT stylesheet.
-   
-   The XSLT transformation output result order of the groups, can be explicitly affected by one 
-   or more xsl:sort elements within the xsl:for-each-group element. If xsl:sort elements are not
-   present within xsl:for-each-group element, then the XSLT transformation output result order of 
-   the groups, is according to the default sorted order (also known as order of first appearance),
-   as defined by XSLT 3.0 spec.    
-*/
+/*
+ * Implementation of the XSLT 3.0 xsl:for-each-group instruction. 
+ */
 public class ElemForEachGroup extends ElemTemplateElement 
                                                 implements ExpressionOwner
 {
@@ -405,7 +398,27 @@ public class ElemForEachGroup extends ElemTemplateElement
         }
         
         final int sourceNode = xctxt.getCurrentNode();
-        DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);
+        
+        DTMIterator sourceNodes = null;
+        
+        if (m_selectExpression instanceof Variable) {
+            XObject xObj = ((Variable)m_selectExpression).execute(xctxt);
+            
+            if (xObj instanceof ResultSequence) {                              
+               ResultSequence resultSeq = (ResultSequence)xObj;
+               sourceNodes = getSourceNodesFromResultSequence(resultSeq, xctxt);                
+            }
+        }
+        else if (m_selectExpression instanceof SimpleSequenceConstructor) {
+            XObject xObj = ((SimpleSequenceConstructor)m_selectExpression).execute(xctxt);
+            
+            ResultSequence resultSeq = (ResultSequence)xObj;
+            sourceNodes = getSourceNodesFromResultSequence(resultSeq, xctxt);
+        }
+        
+        if (sourceNodes == null) {        
+           sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);
+        }
                       
         // hashmap to store groups formed for, either 'group-by' or 'group-adjacent' attributes.
         // hashmap's key is the grouping key value, and value of that hashmap item entry is the
@@ -842,5 +855,36 @@ public class ElemForEachGroup extends ElemTemplateElement
      }
     
   }
+  
+  private DTMIterator getSourceNodesFromResultSequence(ResultSequence resultSeq, XPathContext xctxt) 
+                                                                                          throws TransformerException {
+     DTMIterator sourceNodes = null;
+     
+     NodeVector nodeVector = new NodeVector();
+     
+     // we're assuming here that, all items within this 'resultSeq'
+     // object shall be XNodeSet objects.
+     
+     // how to do this 'resultSeq' object processing, when any of its
+     // items are other than XML nodes?
+     // REVISIT
+     for (int idx = 0; idx < resultSeq.size(); idx++) {
+         XObject xObject = resultSeq.item(idx);
+         xObject = ((XNodeSet)xObject).getFresh();
+         DTMIterator dtmIter = xObject.iter();
+         nodeVector.addElement(dtmIter.nextNode()); 
+     }
+   
+     NodeSequence nodeSequence = new NodeSequence(nodeVector);
+     
+     try {
+        sourceNodes = nodeSequence.cloneWithReset();
+     } catch (CloneNotSupportedException ex) {
+        throw new TransformerException("An error occured during XSL grouping with xsl:for-each-group "
+                                                                                            + "element.", xctxt.getSAXLocator());
+     }
+     
+     return sourceNodes; 
+  }
 
 }
diff --git a/src/org/apache/xalan/templates/ElemIterate.java b/src/org/apache/xalan/templates/ElemIterate.java
index 0289a604..62765e9a 100644
--- a/src/org/apache/xalan/templates/ElemIterate.java
+++ b/src/org/apache/xalan/templates/ElemIterate.java
@@ -35,6 +35,7 @@ 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;
@@ -221,8 +222,11 @@ public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
                    for (int idx = 0; idx < resultSeqItems.size(); idx++) {
                        XObject resultSeqItem = resultSeqItems.get(idx);
                        
-                       setXPathContextForXslSequenceProcessing(resultSeqItems.size(), idx, 
-                                                                                                 resultSeqItem, xctxt);
+                       if (resultSeqItem instanceof XNodeSet) {
+                          resultSeqItem = ((XNodeSet)resultSeqItem).getFresh(); 
+                       }
+                       
+                       setXPathContextForXslSequenceProcessing(resultSeqItems.size(), idx, resultSeqItem, xctxt);
                        
                        boolean isBreakFromXslContentLoop = false;
                        
@@ -237,18 +241,14 @@ public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
                                transformer.setCurrentElement(elemTemplate);
                                elemTemplate.execute(transformer);
                            }
-                           else {
-                               // reset the, XPath context details                               
-                               resetXPathContextForXslSequenceProcessing(resultSeqItem, xctxt);
-                               
-                               isBreakFromXslContentLoop = true;
-                               
+                           else {                              
+                               resetXPathContextForXslSequenceProcessing(resultSeqItem, xctxt);                               
+                               isBreakFromXslContentLoop = true;                               
                                break;    
                            }
                        }
                        
-                       if (!isBreakFromXslContentLoop) {
-                          // reset the, XPath context details                           
+                       if (!isBreakFromXslContentLoop) {                         
                           resetXPathContextForXslSequenceProcessing(resultSeqItem, xctxt);
                        }
                        
@@ -275,7 +275,8 @@ public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
                   
                   transformer.setXPathContext(xctxtOriginal);
                 
-                  return;  // return from this xsl:iterate instruction's evaluation                  
+                  // return from this xsl:iterate instruction's evaluation
+                  return;                  
                }
            }
            
diff --git a/src/org/apache/xalan/templates/ElemTemplateElement.java b/src/org/apache/xalan/templates/ElemTemplateElement.java
index 31761926..65647efc 100644
--- a/src/org/apache/xalan/templates/ElemTemplateElement.java
+++ b/src/org/apache/xalan/templates/ElemTemplateElement.java
@@ -1740,7 +1740,7 @@ public class ElemTemplateElement extends UnImplNode
   }
   
   /**
-   * During processing of, xsl:for-each or xsl:iterate instructions, when the input data to be
+   * During processing of, xsl:for-each or xsl:iterate instruction, when the input data to be
    * processed by these instructions is a 'ResultSequence' object, we use this method to set
    * the XPath context information before each sequence item is processed by these instructions.
    * 
@@ -1754,21 +1754,21 @@ public class ElemTemplateElement extends UnImplNode
                                                                   int currentlyProcessingItemIndex, 
                                                                   XObject currentContextItem, 
                                                                   XPathContext xctxt) {
-      if (!(currentContextItem instanceof XNodeSet)) {
-         xctxt.setXPath3ContextSize(inpSequenceLength);
-         xctxt.setXPath3ContextItem(currentContextItem);
-         xctxt.setXPath3ContextPosition(currentlyProcessingItemIndex + 1);
-      }
-      else {
+      if (currentContextItem instanceof XNodeSet) {         
          XNodeSet xNodeSet = (XNodeSet)currentContextItem;
          DTMIterator dtmIter = xNodeSet.iterRaw();
          int contextNode = dtmIter.nextNode();
-         xctxt.pushCurrentNode(contextNode); 
+         xctxt.pushCurrentNode(contextNode);
+      }
+      else {         
+         xctxt.setXPath3ContextSize(inpSequenceLength);
+         xctxt.setXPath3ContextItem(currentContextItem);
+         xctxt.setXPath3ContextPosition(currentlyProcessingItemIndex + 1);
       }
   }
   
   /**
-   * During processing of, xsl:for-each or xsl:iterate instructions, when the input data to be
+   * During processing of, xsl:for-each or xsl:iterate instruction, when the input data to be
    * processed by these instructions is a 'ResultSequence' object, we use this method to reset
    * the XPath context information after each sequence item is processed by these instructions. 
    * 
@@ -1777,14 +1777,14 @@ public class ElemTemplateElement extends UnImplNode
    */
   protected void resetXPathContextForXslSequenceProcessing(XObject currentContextItem, 
                                                                             XPathContext xctxt) {
-     if (!(currentContextItem instanceof XNodeSet)) {
+     if (currentContextItem instanceof XNodeSet) {        
+        xctxt.popCurrentNode();
+     }
+     else {     
         xctxt.setXPath3ContextSize(-1);
         xctxt.setXPath3ContextItem(null);
         xctxt.setXPath3ContextPosition(-1);
      }
-     else {
-        xctxt.popCurrentNode();
-     }
   }
 
 }
diff --git a/src/org/apache/xpath/composite/QuantifiedExpr.java b/src/org/apache/xpath/composite/QuantifiedExpr.java
index 76736246..74d73ce3 100644
--- a/src/org/apache/xpath/composite/QuantifiedExpr.java
+++ b/src/org/apache/xpath/composite/QuantifiedExpr.java
@@ -61,10 +61,10 @@ public class QuantifiedExpr extends Expression {
 
     private static final long serialVersionUID = -3073535420126040669L;
     
-    // constant value, denoting XPath quantified expression "some" 
+    // Constant value, denoting XPath quantified expression 'some'.
     public static final int SOME = 0;
     
-    // constant value, denoting XPath quantified expression "every"
+    // Constant value, denoting XPath quantified expression 'every'.
     public static final int EVERY = 1;
     
     private int fCurrentXPathQuantifier;
@@ -204,7 +204,7 @@ public class QuantifiedExpr extends Expression {
         if (listIter.hasNext()) {           
            ForQuantifiedExprVarBinding quantifiedExprVarBinding = (ForQuantifiedExprVarBinding)listIter.next();            
             
-           // evaluate the current, variable binding xpath expression
+           // Evaluate the current, variable binding xpath expression
            
            String varName = quantifiedExprVarBinding.getVarName();
            String varBindingXPathStr = quantifiedExprVarBinding.getXPathExprStr();                      
@@ -242,9 +242,7 @@ public class QuantifiedExpr extends Expression {
                xsObjResultSeq = (ResultSequence)xsObj;
            }
            else {
-              // assuming here that, quantified expression's variable binding XPath expression 
-              // evaluation, returned a singleton value.
-              xsObjResultSeq.add(xsObj);
+               xsObjResultSeq.add(xsObj);
            }
            
            if (xsObjResultSeq.size() == 0) {
@@ -253,7 +251,7 @@ public class QuantifiedExpr extends Expression {
                return resultSeq;    
            }
            
-           // for each xdm item within sequence object 'xsObjResultSeq' (which is the 
+           // For each xdm item within sequence object 'xsObjResultSeq' (which is the 
            // result of variable binding xpath expression's evaluation), bind the 
            // quantifier expression's binding variable in turn to that item.
            for (int idx = 0; idx < xsObjResultSeq.size(); idx++) {
@@ -262,7 +260,7 @@ public class QuantifiedExpr extends Expression {
                quantifiedExprVarBindingMap.put(new QName(varName), xdmItem);
                
                ResultSequence res = getQuantifiedExpressionEvalResult(listIter, quantifiedExprXpath, xctxt);
-               // append xdm items of sequence 'res', to the final sequence object 'resultSeq'   
+               // Append xdm items of sequence 'res', to the final sequence object 'resultSeq'   
                for (int idx1 = 0; idx1 < res.size(); idx1++) {
                   resultSeq.add(res.item(idx1));    
                }
@@ -273,19 +271,23 @@ public class QuantifiedExpr extends Expression {
            return resultSeq;
         }
         else {
-            // this else clause, actually evaluates the current XPath quantified expression's 
-            // 'satisfies' expression clause.
+            // This else clause, evaluates the XPath quantified expression's 'satisfies' 
+            // clause. The XPath quantified expression's 'satisfies' clause may be evaluated
+            // multiple times depending upon, how may 'some'/'every' expression iterations
+            // are there.
             
             if (fVars != null) {              
                quantifiedExprXpath.fixupVariables(fVars, fGlobalsSize);
             }
             
+            ResultSequence satisfiesClauseEvalResult = new ResultSequence(); 
+            
             XObject quantifiedTestExprValue = quantifiedExprXpath.execute(xctxt, contextNode, 
                                                                                      xctxt.getNamespaceContext());            
             
-            resultSeq.add(new XSBoolean(quantifiedTestExprValue.bool()));
+            satisfiesClauseEvalResult.add(new XSBoolean(quantifiedTestExprValue.bool()));
             
-            return resultSeq; 
+            return satisfiesClauseEvalResult; 
         }
     }
 
diff --git a/src/org/apache/xpath/composite/SimpleSequenceConstructor.java b/src/org/apache/xpath/composite/SimpleSequenceConstructor.java
index d3065cc0..25e73c0c 100644
--- a/src/org/apache/xpath/composite/SimpleSequenceConstructor.java
+++ b/src/org/apache/xpath/composite/SimpleSequenceConstructor.java
@@ -134,7 +134,7 @@ public class SimpleSequenceConstructor extends Expression {
                    String xpathIndexExprStr = xpathExprStr.substring(xpathExprStr.indexOf('[') + 1, 
                                                                                        xpathExprStr.indexOf(']'));
                    
-                   // evaluate the, variable reference XPath expression
+                   // Evaluate the, variable reference XPath expression
                    if (prefixTable != null) {
                       varRefXPathExprStr = XslTransformEvaluationHelper.replaceNsUrisWithPrefixesOnXPathStr(
                                                                                                varRefXPathExprStr, prefixTable);
@@ -144,7 +144,7 @@ public class SimpleSequenceConstructor extends Expression {
                                                                                                       XPath.SELECT, null);
                    XObject varEvalResult = varXPathObj.execute(xctxt, xctxt.getCurrentNode(), xctxt.getNamespaceContext());
                    
-                   // evaluate the, xdm sequence index XPath expression
+                   // Evaluate the, xdm sequence index XPath expression
                    if (prefixTable != null) {
                       xpathIndexExprStr = XslTransformEvaluationHelper.replaceNsUrisWithPrefixesOnXPathStr(
                                                                                                       xpathIndexExprStr, 
diff --git a/tests/org/apache/xalan/xpath3/SequenceConstructorTests.java b/tests/org/apache/xalan/xpath3/SequenceConstructorTests.java
index c6aa5c76..09f6c038 100644
--- a/tests/org/apache/xalan/xpath3/SequenceConstructorTests.java
+++ b/tests/org/apache/xalan/xpath3/SequenceConstructorTests.java
@@ -167,5 +167,45 @@ public class SequenceConstructorTests extends XslTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslSequenceConstructorTest13() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_f.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test13.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test10.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSequenceConstructorTest14() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_f.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test14.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test10.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSequenceConstructorTest15() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_f.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test15.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test11.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSequenceConstructorTest16() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_f.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test16.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test11.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
 
 }
diff --git a/tests/sequence_constructor/gold/test10.out b/tests/sequence_constructor/gold/test10.out
new file mode 100644
index 00000000..f924abf6
--- /dev/null
+++ b/tests/sequence_constructor/gold/test10.out
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?><document>
+  <data1>
+    <person id="2">
+      <name>Joseph</name>
+    </person>
+    <person id="3">
+      <name>Dave</name>
+    </person>
+    <person id="4">
+      <name>Mary</name>
+    </person>
+    <person id="5">
+      <name>Mukul</name>
+    </person>
+  </data1>
+  <data2>
+    <person id="2">
+      <profession>Software Development</profession>
+    </person>
+    <person id="3">
+      <profession>Finance</profession>
+    </person>
+    <person id="4">
+      <profession>IT Support</profession>
+    </person>
+    <person id="5">
+      <profession>Software Development</profession>
+    </person>
+  </data2>
+</document>
diff --git a/tests/sequence_constructor/gold/test11.out b/tests/sequence_constructor/gold/test11.out
new file mode 100644
index 00000000..07fbe891
--- /dev/null
+++ b/tests/sequence_constructor/gold/test11.out
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?><document>
+  <data1>
+    <group grpKey="Software Development">
+      <person id="2">
+    <name>Joseph</name>
+    <profession>Software Development</profession>
+  </person>
+      <person id="5">
+    <name>Mukul</name>
+    <profession>Software Development</profession>
+  </person>
+    </group>
+    <group grpKey="Finance">
+      <person id="3">
+    <name>Dave</name>
+    <profession>Finance</profession>
+  </person>
+    </group>
+    <group grpKey="IT Support">
+      <person id="4">
+    <name>Mary</name>
+    <profession>IT Support</profession>
+  </person>
+    </group>
+  </data1>
+  <data2>
+    <group grpKey="Software Development">
+      <person id="2">
+    <name>Joseph</name>
+    <profession>Software Development</profession>
+  </person>
+      <person id="5">
+    <name>Mukul</name>
+    <profession>Software Development</profession>
+  </person>
+    </group>
+    <group grpKey="Finance">
+      <person id="3">
+    <name>Dave</name>
+    <profession>Finance</profession>
+  </person>
+    </group>
+    <group grpKey="IT Support">
+      <person id="4">
+    <name>Mary</name>
+    <profession>IT Support</profession>
+  </person>
+    </group>
+  </data2>
+</document>
diff --git a/tests/sequence_constructor/test13.xsl b/tests/sequence_constructor/test13.xsl
new file mode 100644
index 00000000..292e3796
--- /dev/null
+++ b/tests/sequence_constructor/test13.xsl
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- use with test1_f.xml -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator, and traversing the sequence using xsl:for-each
+        instruction. 
+   -->                             
+
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:template match="/document">
+      <document>
+         <xsl:variable name="seq1" select="(person[2], person[3], person[4], person[5])"/>        
+         <data1>
+            <xsl:for-each select="$seq1">
+               <xsl:element name="{name()}">
+                  <xsl:copy-of select="@id"/>
+                  <xsl:copy-of select="name"/>
+               </xsl:element>
+            </xsl:for-each>
+         </data1>
+         <data2>
+            <!-- traverse the same xdm sequence, again -->
+	        <xsl:for-each select="$seq1">
+	           <xsl:element name="{name()}">
+                  <xsl:copy-of select="@id"/>
+                  <xsl:copy-of select="profession"/>
+               </xsl:element>        
+            </xsl:for-each>
+         </data2>
+      </document>
+   </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/sequence_constructor/test14.xsl b/tests/sequence_constructor/test14.xsl
new file mode 100644
index 00000000..411511ae
--- /dev/null
+++ b/tests/sequence_constructor/test14.xsl
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- use with test1_f.xml -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator, and traversing the sequence using xsl:iterate
+        instruction. 
+   -->                              
+
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:template match="/document">
+      <document>
+         <xsl:variable name="seq1" select="(person[2], person[3], person[4], person[5])"/>        
+         <data1>
+            <xsl:iterate select="$seq1">
+               <xsl:element name="{name()}">
+                  <xsl:copy-of select="@id"/>
+                  <xsl:copy-of select="name"/>
+               </xsl:element>
+            </xsl:iterate>
+         </data1>
+         <data2>
+            <!-- traverse the same xdm sequence, again -->
+	        <xsl:iterate select="$seq1">
+	           <xsl:element name="{name()}">
+                  <xsl:copy-of select="@id"/>
+                  <xsl:copy-of select="profession"/>
+               </xsl:element>        
+            </xsl:iterate>
+         </data2>
+      </document>
+   </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/sequence_constructor/test15.xsl b/tests/sequence_constructor/test15.xsl
new file mode 100644
index 00000000..157f87fe
--- /dev/null
+++ b/tests/sequence_constructor/test15.xsl
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- use with test1_f.xml -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator.
+        
+        This stylesheet, also performs XML data grouping on the sequence
+        formed, using xsl:for-each-group instruction. 
+   -->                              
+
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:template match="/document">
+      <document>
+         <xsl:variable name="seq1" select="(person[2], person[3], person[4], person[5])"/>        
+         <data1>
+            <xsl:for-each-group select="$seq1" group-by="profession">
+               <group grpKey="{current-grouping-key()}">
+                  <xsl:copy-of select="current-group()"/>
+               </group>
+            </xsl:for-each-group>
+         </data1>
+         <data2>
+            <!-- perform the XML data grouping again, on same sequence 
+                 variable reference. -->
+	        <xsl:for-each-group select="$seq1" group-by="profession">
+	           <group grpKey="{current-grouping-key()}">
+	              <xsl:copy-of select="current-group()"/>
+	           </group>
+            </xsl:for-each-group>
+        </data2>
+      </document>
+   </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/sequence_constructor/test16.xsl b/tests/sequence_constructor/test16.xsl
new file mode 100644
index 00000000..6db1e461
--- /dev/null
+++ b/tests/sequence_constructor/test16.xsl
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- use with test1_f.xml -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator.
+        
+        This stylesheet, also performs XML data grouping on the sequence
+        formed, using xsl:for-each-group instruction. 
+   -->                             
+
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:template match="/document">
+      <document>       
+         <data1>
+            <xsl:for-each-group select="(person[2], person[3], person[4], person[5])" group-by="profession">
+               <group grpKey="{current-grouping-key()}">
+                  <xsl:copy-of select="current-group()"/>
+               </group>
+            </xsl:for-each-group>
+         </data1>
+         <data2>
+            <!-- perform the XML data grouping again, on an xdm sequence having same collection
+                 of node references as before. -->
+	        <xsl:for-each-group select="(person[2], person[3], person[4], person[5])" group-by="profession">
+	           <group grpKey="{current-grouping-key()}">
+	              <xsl:copy-of select="current-group()"/>
+	           </group>
+            </xsl:for-each-group>
+         </data2>
+      </document>
+   </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/sequence_constructor/test1_f.xml b/tests/sequence_constructor/test1_f.xml
new file mode 100644
index 00000000..918c9962
--- /dev/null
+++ b/tests/sequence_constructor/test1_f.xml
@@ -0,0 +1,26 @@
+<document>
+  <person id="1">
+    <name>Michael</name>
+    <profession>Software Development</profession>
+  </person>
+  <person id="2">
+    <name>Joseph</name>
+    <profession>Software Development</profession>
+  </person>
+  <person id="3">
+    <name>Dave</name>
+    <profession>Finance</profession>
+  </person>
+  <person id="4">
+    <name>Mary</name>
+    <profession>IT Support</profession>
+  </person>
+  <person id="5">
+    <name>Mukul</name>
+    <profession>Software Development</profession>
+  </person>
+  <person id="6">
+    <name>Gary</name>
+    <profession>Software Development</profession>
+  </person>
+</document>
\ 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