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/07/21 16:33:58 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing implementation of xpath 3.1 sequence constructor, with comma operator and begin/end parenthesis pairs. also committing few related xalanj xslt 3.0 implementation codebase changes. committing few new related test cases as well, for xpath 3.1 sequence constructor expressions.

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 6b6b23db committing implementation of xpath 3.1 sequence constructor, with comma operator and begin/end parenthesis pairs. also committing few related xalanj xslt 3.0 implementation codebase changes. committing few new related test cases as well, for xpath 3.1 sequence constructor expressions.
     new 4ef48045 Merge pull request #34 from mukulga/xalan-j_xslt3.0_mukul
6b6b23db is described below

commit 6b6b23dbb603ff80606dcef1026586cf24409acc
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Fri Jul 21 21:58:07 2023 +0530

    committing implementation of xpath 3.1 sequence constructor, with comma operator and begin/end parenthesis pairs. also committing few related xalanj xslt 3.0 implementation codebase changes. committing few new related test cases as well, for xpath 3.1 sequence constructor expressions.
---
 src/org/apache/xalan/templates/ElemIterate.java    |  14 +-
 .../apache/xalan/templates/ElemIterateBreak.java   |   4 +-
 .../xalan/templates/ElemIterateOnCompletion.java   |   4 +-
 src/org/apache/xalan/xslt/Process.java             |   4 +-
 .../xalan/xslt/util/XPathSequenceHelper.java       |  53 +++++++
 ...store.java => XslTransformSharedDatastore.java} |  12 +-
 src/org/apache/xml/utils/DefaultErrorHandler.java  |   4 +-
 src/org/apache/xpath/compiler/Compiler.java        |   7 +
 src/org/apache/xpath/compiler/OpCodes.java         |   4 +-
 src/org/apache/xpath/compiler/XPathParser.java     | 164 +++++++++++++++++++--
 src/org/apache/xpath/composite/ForExpr.java        |  22 ++-
 .../xpath/composite/SimpleSequenceConstructor.java | 144 ++++++++++++++++++
 src/org/apache/xpath/objects/XNodeSet.java         |  59 +++++++-
 .../xalan/xpath3/SequenceConstructorTests.java     | 121 +++++++++++++++
 tests/org/apache/xalan/xslt3/AllXsl3Tests.java     |   4 +-
 tests/sequence_constructor/gold/test1.out          |   4 +
 tests/sequence_constructor/gold/test2.out          |  11 ++
 tests/sequence_constructor/gold/test3.out          |  14 ++
 tests/sequence_constructor/gold/test4.out          |  10 ++
 tests/sequence_constructor/gold/test5.out          |   1 +
 tests/sequence_constructor/gold/test6.out          |   1 +
 tests/sequence_constructor/gold/test7.out          |   1 +
 tests/sequence_constructor/test1.xsl               |  42 ++++++
 tests/sequence_constructor/test1_a.xml             |  20 +++
 tests/sequence_constructor/test1_b.xml             |  24 +++
 tests/sequence_constructor/test2.xsl               |  47 ++++++
 tests/sequence_constructor/test3.xsl               |  39 +++++
 tests/sequence_constructor/test4.xsl               |  40 +++++
 tests/sequence_constructor/test5.xsl               |  41 ++++++
 tests/sequence_constructor/test6.xsl               |  44 ++++++
 tests/sequence_constructor/test7.xsl               |  44 ++++++
 31 files changed, 951 insertions(+), 52 deletions(-)

diff --git a/src/org/apache/xalan/templates/ElemIterate.java b/src/org/apache/xalan/templates/ElemIterate.java
index 95e55710..5b23c8e9 100644
--- a/src/org/apache/xalan/templates/ElemIterate.java
+++ b/src/org/apache/xalan/templates/ElemIterate.java
@@ -23,7 +23,7 @@ import java.util.List;
 import javax.xml.transform.TransformerException;
 
 import org.apache.xalan.transformer.TransformerImpl;
-import org.apache.xalan.xslt.util.XslTransformationGlobalSharedDatastore;
+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;
@@ -250,7 +250,7 @@ public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
                            xslOnCompletionTemplate = (ElemIterateOnCompletion)elemTemplate;     
                        }
                        
-                       if (!(XslTransformationGlobalSharedDatastore.isXslIterateBreakEvaluated).booleanValue()) {
+                       if (!(XslTransformSharedDatastore.isXslIterateBreakEvaluated).booleanValue()) {
                            xctxt.setSAXLocator(elemTemplate);
                            transformer.setCurrentElement(elemTemplate);
                            elemTemplate.execute(transformer);
@@ -260,21 +260,21 @@ public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
                        }                                              
                    }                                      
                    
-                   if ((XslTransformationGlobalSharedDatastore.isXslIterateBreakEvaluated).booleanValue()) {                       
+                   if ((XslTransformSharedDatastore.isXslIterateBreakEvaluated).booleanValue()) {                       
                        break;   
                    }
                }
                
-               if ((xslOnCompletionTemplate != null) && !(XslTransformationGlobalSharedDatastore.
+               if ((xslOnCompletionTemplate != null) && !(XslTransformSharedDatastore.
                                                                                 isXslIterateBreakEvaluated).booleanValue()) {
-                    XslTransformationGlobalSharedDatastore.isXslIterateOnCompletionActive = Boolean.TRUE;
+                    XslTransformSharedDatastore.isXslIterateOnCompletionActive = Boolean.TRUE;
                     xctxt.setSAXLocator(xslOnCompletionTemplate);
                     transformer.setCurrentElement(xslOnCompletionTemplate);
                     xslOnCompletionTemplate.execute(transformer);
-                    XslTransformationGlobalSharedDatastore.isXslIterateOnCompletionActive = Boolean.FALSE;
+                    XslTransformSharedDatastore.isXslIterateOnCompletionActive = Boolean.FALSE;
                }
                
-               XslTransformationGlobalSharedDatastore.isXslIterateBreakEvaluated = Boolean.FALSE; 
+               XslTransformSharedDatastore.isXslIterateBreakEvaluated = Boolean.FALSE; 
            }
            finally {
               xctxt.popSAXLocator();
diff --git a/src/org/apache/xalan/templates/ElemIterateBreak.java b/src/org/apache/xalan/templates/ElemIterateBreak.java
index 7842b3fc..c2df8afc 100644
--- a/src/org/apache/xalan/templates/ElemIterateBreak.java
+++ b/src/org/apache/xalan/templates/ElemIterateBreak.java
@@ -20,7 +20,7 @@ package org.apache.xalan.templates;
 import javax.xml.transform.TransformerException;
 
 import org.apache.xalan.transformer.TransformerImpl;
-import org.apache.xalan.xslt.util.XslTransformationGlobalSharedDatastore;
+import org.apache.xalan.xslt.util.XslTransformSharedDatastore;
 import org.apache.xml.serializer.SerializationHandler;
 import org.apache.xpath.Expression;
 import org.apache.xpath.ExpressionOwner;
@@ -169,7 +169,7 @@ public class ElemIterateBreak extends ElemTemplateElement implements ExpressionO
                       
             if (isXslBreakDescendantOfXslIterate && isXslInstructionInTailPositionOfSequenceConstructor(this)) {              
                 transformXslBreakInstruction(transformer);
-                XslTransformationGlobalSharedDatastore.isXslIterateBreakEvaluated = Boolean.TRUE;
+                XslTransformSharedDatastore.isXslIterateBreakEvaluated = Boolean.TRUE;
             }
             else {
                 throw new TransformerException("XTSE3120 : an xsl:break instruction is not in a "
diff --git a/src/org/apache/xalan/templates/ElemIterateOnCompletion.java b/src/org/apache/xalan/templates/ElemIterateOnCompletion.java
index 5f0acf4e..1e51ed95 100644
--- a/src/org/apache/xalan/templates/ElemIterateOnCompletion.java
+++ b/src/org/apache/xalan/templates/ElemIterateOnCompletion.java
@@ -20,7 +20,7 @@ package org.apache.xalan.templates;
 import javax.xml.transform.TransformerException;
 
 import org.apache.xalan.transformer.TransformerImpl;
-import org.apache.xalan.xslt.util.XslTransformationGlobalSharedDatastore;
+import org.apache.xalan.xslt.util.XslTransformSharedDatastore;
 import org.apache.xml.serializer.SerializationHandler;
 import org.apache.xpath.Expression;
 import org.apache.xpath.ExpressionOwner;
@@ -170,7 +170,7 @@ public class ElemIterateOnCompletion extends ElemTemplateElement implements Expr
        public void transformXslOncompletionInstruction(TransformerImpl transformer) throws 
                                                                                TransformerException {
                                                                   
-           if ((XslTransformationGlobalSharedDatastore.isXslIterateOnCompletionActive).booleanValue()) {
+           if ((XslTransformSharedDatastore.isXslIterateOnCompletionActive).booleanValue()) {
                final XPathContext originalXctxt = transformer.getXPathContext();
                
                XPathContext xctxt = transformer.getXPathContext();
diff --git a/src/org/apache/xalan/xslt/Process.java b/src/org/apache/xalan/xslt/Process.java
index af1a5806..1265259d 100644
--- a/src/org/apache/xalan/xslt/Process.java
+++ b/src/org/apache/xalan/xslt/Process.java
@@ -56,7 +56,7 @@ import org.apache.xalan.res.XSLTErrorResources;
 import org.apache.xalan.trace.PrintTraceListener;
 import org.apache.xalan.trace.TraceManager;
 import org.apache.xalan.transformer.XalanProperties;
-import org.apache.xalan.xslt.util.XslTransformationGlobalSharedDatastore;
+import org.apache.xalan.xslt.util.XslTransformSharedDatastore;
 import org.apache.xml.utils.DefaultErrorHandler;
 import org.apache.xml.utils.SystemIDResolver;
 import org.w3c.dom.Document;
@@ -750,7 +750,7 @@ public class Process
           else
           {
             // System.out.println("Calling newTemplates: "+xslFileName);
-            XslTransformationGlobalSharedDatastore.xslSystemId = SystemIDResolver.
+            XslTransformSharedDatastore.xslSystemId = SystemIDResolver.
                                                                         getAbsoluteURI(xslFileName); 
             stylesheet = tfactory.newTemplates(new StreamSource(xslFileName));
             // System.out.println("Done calling newTemplates: "+xslFileName);
diff --git a/src/org/apache/xalan/xslt/util/XPathSequenceHelper.java b/src/org/apache/xalan/xslt/util/XPathSequenceHelper.java
new file mode 100644
index 00000000..3b905398
--- /dev/null
+++ b/src/org/apache/xalan/xslt/util/XPathSequenceHelper.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.xalan.xslt.util;
+
+import org.apache.xpath.objects.ResultSequence;
+import org.apache.xpath.objects.XObject;
+
+/**
+ * This class, has few utility methods, to help process the XPath 
+ * data model sequences.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class XPathSequenceHelper {
+    
+    /**
+     * Given an XDM input sequence, expand that sequence to produce a new sequence
+     * none of whose items are sequence with cardinality greater than one.
+     * 
+     * The caller of this method, needs to pass an XDM sequence to be expanded
+     * as an argument, and another argument reference to get the result from this 
+     * method.
+     */
+    public static void expandResultSequence(ResultSequence seqToBeExpanded, 
+                                                                  ResultSequence finalResultSeq) {               
+        for (int idx = 0; idx < seqToBeExpanded.size(); idx++) {
+          XObject xObject = seqToBeExpanded.item(idx);
+          if (xObject instanceof ResultSequence) {
+             expandResultSequence((ResultSequence)xObject, finalResultSeq); 
+          }
+          else {
+             finalResultSeq.add(xObject);
+          }
+       }
+    }
+
+}
diff --git a/src/org/apache/xalan/xslt/util/XslTransformationGlobalSharedDatastore.java b/src/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java
similarity index 79%
rename from src/org/apache/xalan/xslt/util/XslTransformationGlobalSharedDatastore.java
rename to src/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java
index d45b3514..c6c67fac 100644
--- a/src/org/apache/xalan/xslt/util/XslTransformationGlobalSharedDatastore.java
+++ b/src/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java
@@ -17,23 +17,21 @@
 package org.apache.xalan.xslt.util;
 
 /**
+ * This class, has few XalanJ, XSLT stylesheet transformation wide variables.
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
  * @xsl.usage advanced
  */
-/*
- * This class, stores few XSLT document transformation wide variables.
- */
-public class XslTransformationGlobalSharedDatastore {
+public class XslTransformSharedDatastore {
     
-    // XSLT document's uri used for error reporting
+    // XSLT document's uri, used for error reporting
     public static String xslSystemId;
     
-    // to support xsl:iterate instruction evaluation
+    // To support xsl:iterate instruction evaluation
     public static Boolean isXslIterateBreakEvaluated = Boolean.FALSE;
     
-    // to support xsl:iterate instruction evaluation
+    // To support xsl:iterate instruction evaluation
     public static Boolean isXslIterateOnCompletionActive = Boolean.FALSE;
 
 }
diff --git a/src/org/apache/xml/utils/DefaultErrorHandler.java b/src/org/apache/xml/utils/DefaultErrorHandler.java
index 666d7a25..c28f4d57 100644
--- a/src/org/apache/xml/utils/DefaultErrorHandler.java
+++ b/src/org/apache/xml/utils/DefaultErrorHandler.java
@@ -27,7 +27,7 @@ import javax.xml.transform.ErrorListener;
 import javax.xml.transform.SourceLocator;
 import javax.xml.transform.TransformerException;
 
-import org.apache.xalan.xslt.util.XslTransformationGlobalSharedDatastore;
+import org.apache.xalan.xslt.util.XslTransformSharedDatastore;
 import org.apache.xml.res.XMLErrorResources;
 import org.apache.xml.res.XMLMessages;
 
@@ -336,7 +336,7 @@ public class DefaultErrorHandler implements ErrorHandler, ErrorListener
         SourceLocator causeLocator = ((TransformerException)cause).getLocator();
         if(null != causeLocator) {
           if (causeLocator.getSystemId() == null) {
-              xslSystemId = XslTransformationGlobalSharedDatastore.xslSystemId;    
+              xslSystemId = XslTransformSharedDatastore.xslSystemId;    
           }
           locator = causeLocator;
         }
diff --git a/src/org/apache/xpath/compiler/Compiler.java b/src/org/apache/xpath/compiler/Compiler.java
index 67035d35..32eafeff 100644
--- a/src/org/apache/xpath/compiler/Compiler.java
+++ b/src/org/apache/xpath/compiler/Compiler.java
@@ -137,6 +137,8 @@ public class Compiler extends OpMap
       expr = quantifiedExpr(opPos); break;
     case OpCodes.OP_IF_EXPR :
       expr = ifExpr(opPos); break;
+    case OpCodes.OP_SEQUENCE_CONSTRUCTOR_EXPR :
+      expr = sequenceConstructorExpr(opPos); break;
     case OpCodes.OP_OR :
       expr = or(opPos); break;
     case OpCodes.OP_AND :
@@ -1198,6 +1200,11 @@ private static final boolean DEBUG = false;
   {
       return XPathParser.fIfExpr;
   }
+  
+  Expression sequenceConstructorExpr(int opPos) throws TransformerException
+  {
+      return XPathParser.fSimpleSequenceConstructor;
+  }
 
   // The current id for extension functions.
   private static long s_nextMethodId = 0;
diff --git a/src/org/apache/xpath/compiler/OpCodes.java b/src/org/apache/xpath/compiler/OpCodes.java
index cabf00d4..0e96a2aa 100644
--- a/src/org/apache/xpath/compiler/OpCodes.java
+++ b/src/org/apache/xpath/compiler/OpCodes.java
@@ -687,8 +687,10 @@ public class OpCodes
   public static final int OP_QUANTIFIED_EXPR = 65;
   
   public static final int OP_IF_EXPR = 66;
+  
+  public static final int OP_SEQUENCE_CONSTRUCTOR_EXPR = 67;
 
   /** The next free ID. Please keep this up to date. */
-  private static final int NEXT_FREE_ID = 67;
+  private static final int NEXT_FREE_ID = 68;
   
 }
diff --git a/src/org/apache/xpath/compiler/XPathParser.java b/src/org/apache/xpath/compiler/XPathParser.java
index 5df2f127..e92a618c 100644
--- a/src/org/apache/xpath/compiler/XPathParser.java
+++ b/src/org/apache/xpath/compiler/XPathParser.java
@@ -23,6 +23,7 @@ package org.apache.xpath.compiler;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Stack;
 
 import javax.xml.transform.ErrorListener;
 import javax.xml.transform.TransformerException;
@@ -36,6 +37,7 @@ import org.apache.xpath.composite.IfExpr;
 import org.apache.xpath.composite.LetExpr;
 import org.apache.xpath.composite.LetExprVarBinding;
 import org.apache.xpath.composite.QuantifiedExpr;
+import org.apache.xpath.composite.SimpleSequenceConstructor;
 import org.apache.xpath.domapi.XPathStylesheetDOM3Exception;
 import org.apache.xpath.functions.DynamicFunctionCall;
 import org.apache.xpath.objects.InlineFunction;
@@ -102,6 +104,8 @@ public class XPathParser
   
   private boolean fIsXpathPredicateParsingActive = false;
   
+  private boolean fIsBeginParse = false;
+  
   static InlineFunction fInlineFunction = null;
   
   static DynamicFunctionCall fDynamicFunctionCall = null;
@@ -114,6 +118,8 @@ public class XPathParser
   
   static IfExpr fIfExpr = null;
   
+  static SimpleSequenceConstructor fSimpleSequenceConstructor = null;
+  
   /**
    * The parser constructor.
    */
@@ -168,7 +174,10 @@ public class XPathParser
 	try {
 
       nextToken();
-      ExprSingle();
+      
+      fIsBeginParse = true;
+      
+      Expr();
 
       if (null != m_token)
       {
@@ -638,7 +647,7 @@ public class XPathParser
       return (funcBodyXPathExprStrBuff.toString()).trim();
   }
   
-  private boolean isXpathDynamicFuncCallParseAhead(List<String> argDetailsStrPartsList, 
+  private boolean isXPathDynamicFuncCallParseAhead(List<String> argDetailsStrPartsList, 
                                                                                   String delim) {
       boolean isXpathDynamicFuncCallParseAhead = false;
 
@@ -683,6 +692,39 @@ public class XPathParser
 
       return isXpathDynamicFuncCallParseAhead; 
   }
+  
+  /**
+   * Check whether a, string has balanced parentheses pairs 
+   * '(' and ')'.
+   */
+  private boolean isStrHasBalancedParentheses(String str) {
+     
+     boolean isStrHasBalancedParentheses = true;
+     
+     Stack<Character> charStack = new Stack<Character>();
+     
+     int strLen = str.length();
+     
+     for(int idx = 0; idx < strLen; idx++) {
+         char ch = str.charAt(idx);
+         if (ch == '(') {
+            charStack.push(ch); 
+         }
+         else if (ch == ')'){
+            if (charStack.isEmpty() || (charStack.pop() != '(')) {
+               // unbalanced parentheses
+               isStrHasBalancedParentheses = false;
+               break;
+            }   
+         }
+     }
+     
+     if (!charStack.isEmpty()) {
+        isStrHasBalancedParentheses = false;
+     }
+     
+     return isStrHasBalancedParentheses; 
+  }
 
   /**
    * Notify the user of an assertion error, and probably throw an
@@ -894,11 +936,103 @@ public class XPathParser
   }
 
   // ============= EXPRESSIONS FUNCTIONS =================
+  
+  /**
+   * Expr   ::=   ExprSingle ("," ExprSingle)*
+   * 
+   * We follow within this method, the XPath parsing with two pass approach,
+   *   1) The first pass, determines whether XPath 3.1's sequence 
+   *      constructor parsing needs to be used (with sequence items delimited 
+   *      by ',' operator), or to use the XPath parser's usual process using
+   *      '(' OpCodes.OP_GROUP ')'.
+   *   2) The second pass, is XPath parsing as usual, using the result
+   *      determined during step 1) above.
+   * 
+   * @throws javax.xml.transform.TransformerException
+   */
+  protected void Expr() throws javax.xml.transform.TransformerException
+  {
+      if (fIsBeginParse && tokenIs("(")) {
+          nextToken();                  
+          
+          List<String> sequenceConstructorXPathParts = new ArrayList<String>();
+          
+          while (m_token != null)
+          {
+              List<String> seqItemXPathStrPartsList = new ArrayList<String>();
+              
+              while (!tokenIs(",") && m_token != null) {
+                 if (getTokenRelative(0) != null) {
+                    seqItemXPathStrPartsList.add(m_token);
+                 }
+                 nextToken();
+              }
+              
+              String seqItemXPathExprStr = getXPathStrFromComponentParts(seqItemXPathStrPartsList);              
+              if (seqItemXPathExprStr.endsWith(")")) {
+                  seqItemXPathExprStr = seqItemXPathExprStr.substring(0, 
+                                                                 seqItemXPathExprStr.length());    
+              }
+              
+              sequenceConstructorXPathParts.add(seqItemXPathExprStr);
+              
+              if (m_token != null) {
+                 nextToken();   
+              }
+          }
+          
+          boolean isXPathExprOkToProceed = true;
+          
+          // Check that each, string within the list 'sequenceConstructorXPathParts' 
+          // has balanced parentheses pairs '(' and ')'.
+          for (int idx = 0; idx < sequenceConstructorXPathParts.size(); idx++) {
+             String seqItemXPathExprStr = sequenceConstructorXPathParts.get(idx);
+             boolean isStrHasBalancedParentheses = isStrHasBalancedParentheses(seqItemXPathExprStr);
+             if (!isStrHasBalancedParentheses) {
+                isXPathExprOkToProceed = false;
+                break;
+             }
+          }
+          
+          // To check, whether an xdm sequence with at-least two items could be constructed.
+          if (!(isXPathExprOkToProceed && (sequenceConstructorXPathParts.size() > 1))) {
+             isXPathExprOkToProceed = false;    
+          }
+          
+          // Upto here within this method, we've only analyzed the XPath input
+          // string by traversing its sequence of tokens. Based on this result,
+          // we choose from one of the two options below to continue with this
+          // XPath expression parse.          
+          if (isXPathExprOkToProceed) {              
+              int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
+              
+              nextToken();
+              
+              insertOp(opPos, 2, OpCodes.OP_SEQUENCE_CONSTRUCTOR_EXPR);
+              
+              fSimpleSequenceConstructor = new SimpleSequenceConstructor();              
+              fSimpleSequenceConstructor.setSequenceConstructorXPathParts(
+                                                             sequenceConstructorXPathParts);
+              
+              m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
+                                             m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
+             
+          }
+          else {
+             // Reset the XPath parse position to beginning of XPath expression string,
+             // and start the XPath expression parse again.             
+             m_queueMark = 0;
+             nextToken();
+             ExprSingle();
+          }
+      }
+      else {
+         ExprSingle();    
+      }
+  }
 
   /**
    *
-   * Expr   ::=  ExprSingle ("," ExprSingle)*
-   * 
    * ExprSingle  ::=  ForExpr
    *       | LetExpr
    *       | QuantifiedExpr
@@ -909,6 +1043,8 @@ public class XPathParser
    */
   protected void ExprSingle() throws javax.xml.transform.TransformerException
   {
+      fIsBeginParse = false;
+      
       if (tokenIs("for")) {
          // to check, whether XPath 'for' expression is a sub expression of another 
          // XPath expression (for e.g, a 'for' expression could be a function 
@@ -1738,7 +1874,7 @@ public class XPathParser
     int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
 
     appendOp(2, OpCodes.OP_STRING);
-    ExprSingle();
+    Expr();
 
     m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
       m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
@@ -1758,7 +1894,7 @@ public class XPathParser
     int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
 
     appendOp(2, OpCodes.OP_BOOL);
-    ExprSingle();
+    Expr();
 
     int opLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos;
 
@@ -1784,7 +1920,7 @@ public class XPathParser
     int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
 
     appendOp(2, OpCodes.OP_NUMBER);
-    ExprSingle();
+    Expr();
 
     m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
       m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
@@ -2017,7 +2153,7 @@ public class XPathParser
        String delimSuffix = (Long.valueOf(currentTimeMills)).toString();
        String delim = "t0_" + delimSuffix;
        
-       while (m_token != null && isXpathDynamicFuncCallParseAhead(
+       while (m_token != null && isXPathDynamicFuncCallParseAhead(
                                                       argDetailsStrPartsList, delim))
        {
           // no op here
@@ -2071,10 +2207,10 @@ public class XPathParser
     else if (m_tokenChar == '(')
     {
       nextToken();
-      appendOp(2, OpCodes.OP_GROUP);
-      ExprSingle();
-      consumeExpected(')');
-
+      appendOp(2, OpCodes.OP_GROUP);     
+      Expr();
+      consumeExpected(')');      
+      
       m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
         m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
 
@@ -2200,7 +2336,7 @@ public class XPathParser
     int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
 
     appendOp(2, OpCodes.OP_ARGUMENT);
-    ExprSingle();
+    Expr();
 
     m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
       m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
@@ -2762,7 +2898,7 @@ public class XPathParser
     int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
 
     appendOp(2, OpCodes.OP_PREDICATE);
-    ExprSingle();
+    Expr();
 
     // Terminate for safety.
     m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
diff --git a/src/org/apache/xpath/composite/ForExpr.java b/src/org/apache/xpath/composite/ForExpr.java
index 39582d03..ea2fbdbe 100644
--- a/src/org/apache/xpath/composite/ForExpr.java
+++ b/src/org/apache/xpath/composite/ForExpr.java
@@ -25,6 +25,7 @@ import java.util.Vector;
 import javax.xml.transform.SourceLocator;
 import javax.xml.transform.TransformerException;
 
+import org.apache.xalan.xslt.util.XPathSequenceHelper;
 import org.apache.xml.dtm.DTM;
 import org.apache.xml.dtm.DTMIterator;
 import org.apache.xml.utils.QName;
@@ -75,17 +76,23 @@ public class ForExpr extends Expression {
     
     @Override
     public XObject execute(XPathContext xctxt) throws TransformerException {
-       ResultSequence resultSeq = new ResultSequence();
+       ResultSequence finalResultSeq = new ResultSequence();
        
        SourceLocator srcLocator = xctxt.getSAXLocator();
        
        XPath returnExprXpath = new XPath(fReturnExprXPathStr, srcLocator, null, XPath.SELECT, null);
        
-       resultSeq = getForExpressionEvalResult(fForExprVarBindingList.listIterator(), 
-                                                                            returnExprXpath, xctxt);
+       ResultSequence resultSeq = getForExpressionEvalResult(fForExprVarBindingList.listIterator(), 
+                                                                            returnExprXpath, xctxt);       
+       
+       // An xdm sequence object 'resultSeq', may have items that are themselves sequence 
+       // objects. We need to expand such nested sequence objects, to get a final sequence
+       // none of whose items are sequence with cardinality greater than one.   
+       XPathSequenceHelper.expandResultSequence(resultSeq, finalResultSeq);
+               
        m_xpathVarList.clear();
        
-       return resultSeq;
+       return finalResultSeq; 
     }
 
     @Override
@@ -161,8 +168,11 @@ public class ForExpr extends Expression {
                   xsObjResultSeq.add(singletonXPathNode);
                }
            }
-           else if (xsObj instanceof ResultSequence) {               
-               xsObjResultSeq = (ResultSequence)xsObj;
+           else if (xsObj instanceof ResultSequence) {
+               ResultSequence rSeq = (ResultSequence)xsObj;
+               for (int idx = 0; idx < rSeq.size(); idx++) {
+                   xsObjResultSeq.add(rSeq.item(idx)); 
+               }
            }
            else {
               // assuming here that, 'for' expression's variable binding XPath expression 
diff --git a/src/org/apache/xpath/composite/SimpleSequenceConstructor.java b/src/org/apache/xpath/composite/SimpleSequenceConstructor.java
new file mode 100644
index 00000000..b2dddbef
--- /dev/null
+++ b/src/org/apache/xpath/composite/SimpleSequenceConstructor.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+package org.apache.xpath.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMIterator;
+import org.apache.xml.dtm.DTMManager;
+import org.apache.xpath.Expression;
+import org.apache.xpath.ExpressionOwner;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.XPathVisitor;
+import org.apache.xpath.objects.ResultSequence;
+import org.apache.xpath.objects.XNodeSet;
+import org.apache.xpath.objects.XObject;
+
+/*
+ * The XalanJ XPath parser, creates and populates an object of this class, 
+ * to help produce an XDM sequence, from an XPath expression using the
+ * comma operator.
+ * 
+ * Ref : https://www.w3.org/TR/xpath-31/#construct_seq
+ *       
+ *       The XPath grammar fragment, for such a sequence constructor
+ *       is following,
+ *       
+ *       Expr    ::=   ExprSingle ("," ExprSingle)*
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class SimpleSequenceConstructor extends Expression {
+
+    private static final long serialVersionUID = -5141131877741250613L;
+    
+    private List<String> sequenceConstructorXPathParts = new ArrayList<String>();
+    
+    // the following two fields of this class, are used during 
+    // XPath.fixupVariables(..) action as performed within object of 
+    // this class.    
+    private Vector fVars;    
+    private int fGlobalsSize;
+    
+    @Override
+    public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) {
+       // no op
+    }
+
+    @Override
+    public XObject execute(XPathContext xctxt) throws TransformerException {
+        
+        ResultSequence resultSeq = new ResultSequence();
+        
+        SourceLocator srcLocator = xctxt.getSAXLocator();
+        
+        int contextNode = xctxt.getContextNode();
+        
+        // We evaluate below all the, XPath expression parts within the list 
+        // 'sequenceConstructorXPathParts', and concatenate the sequences resulting
+        // from each of them, to get the final result sequence that is returned by
+        // this method.
+        for (int idx = 0; idx < sequenceConstructorXPathParts.size(); idx++) {
+           String xpathExprStr = sequenceConstructorXPathParts.get(idx);
+           
+           XPath xpathObj = new XPath(xpathExprStr, srcLocator, null, XPath.SELECT, null);
+           if (fVars != null) {
+               xpathObj.fixupVariables(fVars, fGlobalsSize);
+           }
+
+           XObject xPathExprPartResult = xpathObj.execute(xctxt, contextNode, null);
+           
+           if (xPathExprPartResult instanceof XNodeSet) {
+               DTMManager dtmMgr = (DTMManager)xctxt;
+               
+               XNodeSet xNodeSet = (XNodeSet)xPathExprPartResult;
+               DTMIterator sourceNodes = xNodeSet.iter();
+               
+               int nextNodeDtmHandle;
+               
+               while ((nextNodeDtmHandle = sourceNodes.nextNode()) != DTM.NULL) {
+                  XNodeSet xNodeSetItem = new XNodeSet(nextNodeDtmHandle, dtmMgr);
+                  resultSeq.add(xNodeSetItem);
+               }               
+            }
+            else if (xPathExprPartResult instanceof ResultSequence) {
+               ResultSequence inpResultSeq = (ResultSequence)xPathExprPartResult; 
+               for (int idx1 = 0; idx1 < inpResultSeq.size(); idx1++) {
+                  XObject xObj = inpResultSeq.item(idx1);
+                  resultSeq.add(xObj);                 
+               }
+            }
+            else {
+               // We're assuming here that, an input value is an xdm singleton 
+               // item.
+               resultSeq.add(xPathExprPartResult);               
+            }
+        }
+        
+        return resultSeq;
+    }
+
+    @Override
+    public void fixupVariables(Vector vars, int globalsSize) {
+        fVars = (Vector)(vars.clone());
+        fGlobalsSize = globalsSize;
+    }
+
+    @Override
+    public boolean deepEquals(Expression expr) {
+        return false;
+    }
+
+    public List<String> getSequenceConstructorXPathParts() {
+        return sequenceConstructorXPathParts;
+    }
+
+    public void setSequenceConstructorXPathParts(List<String> 
+                                                        sequenceConstructorXpathParts) {
+        this.sequenceConstructorXPathParts = sequenceConstructorXpathParts;
+    }
+
+}
diff --git a/src/org/apache/xpath/objects/XNodeSet.java b/src/org/apache/xpath/objects/XNodeSet.java
index fd6a3aa8..31801770 100644
--- a/src/org/apache/xpath/objects/XNodeSet.java
+++ b/src/org/apache/xpath/objects/XNodeSet.java
@@ -29,7 +29,7 @@ import org.apache.xml.dtm.DTMManager;
 import org.apache.xml.utils.XMLString;
 import org.apache.xpath.NodeSetDTM;
 import org.apache.xpath.axes.NodeSequence;
-
+import org.apache.xpath.xs.types.XSUntyped;
 import org.w3c.dom.NodeList;
 import org.w3c.dom.traversal.NodeIterator;
 
@@ -560,6 +560,30 @@ public class XNodeSet extends NodeSequence
       list1.reset();
       list2.reset();
     }
+    else if (XObject.CLASS_RESULT_SEQUENCE == type) {        
+        ResultSequence rSeq = (ResultSequence)obj2;
+        
+        DTMIterator list1 = iterRaw();        
+        int node1;
+        while (DTM.NULL != (node1 = list1.nextNode()))
+        {
+            XMLString s1 = getStringFromNode(node1);
+            
+            for (int idx = 0; idx < rSeq.size(); idx++) {
+               XObject xObj = rSeq.item(idx);               
+               XMLString s2 = new XString(xObj.str());
+               if (comparator.compareStrings(s1, s2))
+               {
+                   result = true;
+                   break;
+               }
+            }
+            
+            if (result) {
+               break;  
+            }
+        }        
+    }
     else if (XObject.CLASS_BOOLEAN == type)
     {
 
@@ -583,21 +607,21 @@ public class XNodeSet extends NodeSequence
       // node in the node-set such that the result of performing the 
       // comparison on the number to be compared and on the result of 
       // converting the string-value of that node to a number using 
-      // the number function is true. 
+      // the number function is true.      
       DTMIterator list1 = iterRaw();
       double num2 = obj2.num();
       int node;
 
       while (DTM.NULL != (node = list1.nextNode()))
       {
-        double num1 = getNumberFromNode(node);
+          double num1 = getNumberFromNode(node);
 
-        if (comparator.compareNumbers(num1, num2))
-        {
-          result = true;
+          if (comparator.compareNumbers(num1, num2))
+          {
+              result = true;
 
-          break;
-        }
+              break;
+          }
       }
       list1.reset();
     }
@@ -645,6 +669,25 @@ public class XNodeSet extends NodeSequence
       }
       list1.reset();
     }
+    else if (obj2 instanceof XSUntyped) {
+       XSUntyped obj2Val = (XSUntyped)obj2;
+       
+       XMLString s2 = new XString(obj2Val.stringValue());
+       DTMIterator list1 = iterRaw();
+       int node;
+
+       while (DTM.NULL != (node = list1.nextNode()))
+       {
+         XMLString s1 = getStringFromNode(node);
+         if (comparator.compareStrings(s1, s2))
+         {
+           result = true;
+
+           break;
+         }
+       }
+       list1.reset();       
+    }
     else
     {
       result = comparator.compareNumbers(this.num(), obj2.num());
diff --git a/tests/org/apache/xalan/xpath3/SequenceConstructorTests.java b/tests/org/apache/xalan/xpath3/SequenceConstructorTests.java
new file mode 100644
index 00000000..fae367e0
--- /dev/null
+++ b/tests/org/apache/xalan/xpath3/SequenceConstructorTests.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+package org.apache.xalan.xpath3;
+
+import org.apache.xalan.util.XslTransformTestsUtil;
+import org.apache.xalan.xslt3.XSLConstants;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * XPath 3.1 test cases, to test the construction of xdm sequences using 
+ * XPath comma operator.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class SequenceConstructorTests extends XslTransformTestsUtil {        
+    
+    private static final String XSL_TRANSFORM_INPUT_DIRPATH = XSLConstants.XSL_TRANSFORM_INPUT_DIRPATH_PREFIX + "sequence_constructor/";
+    
+    private static final String XSL_TRANSFORM_GOLD_DIRPATH = XSLConstants.XSL_TRANSFORM_GOLD_DIRPATH_PREFIX + "sequence_constructor/gold/";
+
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+        // no op
+    }
+
+    @AfterClass
+    public static void tearDownAfterClass() throws Exception {        
+        xmlDocumentBuilderFactory = null;
+        xmlDocumentBuilder = null;
+        xslTransformerFactory = null;
+    }
+
+    @Test
+    public void xslSequenceConstructorTest1() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test1.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSequenceConstructorTest2() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_a.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test2.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test2.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSequenceConstructorTest3() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_b.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test3.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test3.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSequenceConstructorTest4() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_b.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test4.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSequenceConstructorTest5() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test5.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test5.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test5.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSequenceConstructorTest6() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_b.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test6.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test6.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSequenceConstructorTest7() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_b.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test7.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test7.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+
+}
diff --git a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
index 613d438c..ee410e42 100644
--- a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
+++ b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
@@ -32,6 +32,7 @@ import org.apache.xalan.xpath3.InlineFunctionItemExprTests;
 import org.apache.xalan.xpath3.LetExprTests;
 import org.apache.xalan.xpath3.QuantifiedExprTests;
 import org.apache.xalan.xpath3.RangeExprTests;
+import org.apache.xalan.xpath3.SequenceConstructorTests;
 import org.apache.xalan.xpath3.SequenceTests;
 import org.apache.xalan.xpath3.StringTests;
 import org.apache.xalan.xpath3.TrignometricAndExponentialFunctionTests;
@@ -63,7 +64,8 @@ import org.junit.runners.Suite.SuiteClasses;
                 ValueComparisonTests.class, InlineFunctionItemExprTests.class, FnForEachTests.class, 
                 FnFilterTests.class, DynamicFunctionCallTests.class, IfExprTests.class, 
                 ForExprTests.class, LetExprTests.class, FnDistinctValuesTests.class,
-                TrignometricAndExponentialFunctionTests.class, BuiltinFunctionsNamespceTests.class })
+                TrignometricAndExponentialFunctionTests.class, BuiltinFunctionsNamespceTests.class,
+                SequenceConstructorTests.class })
 public class AllXsl3Tests {
 
 }
diff --git a/tests/sequence_constructor/gold/test1.out b/tests/sequence_constructor/gold/test1.out
new file mode 100644
index 00000000..50e29567
--- /dev/null
+++ b/tests/sequence_constructor/gold/test1.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <one>10 1 2 3 4</one>
+  <two>10 1 2 3 4</two>
+</result>
diff --git a/tests/sequence_constructor/gold/test2.out b/tests/sequence_constructor/gold/test2.out
new file mode 100644
index 00000000..e6f831a7
--- /dev/null
+++ b/tests/sequence_constructor/gold/test2.out
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <author>Stevens</author>
+  <title>TCP/IP Illustrated</title>
+  <title>Advanced Programming in the Unix Environment</title>
+  <author>Abiteboul</author>
+  <title>Data on the Web</title>
+  <author>Buneman</author>
+  <title>Data on the Web</title>
+  <author>Suciu</author>
+  <title>Data on the Web</title>
+</result>
diff --git a/tests/sequence_constructor/gold/test3.out b/tests/sequence_constructor/gold/test3.out
new file mode 100644
index 00000000..0375fbc5
--- /dev/null
+++ b/tests/sequence_constructor/gold/test3.out
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <part id="2">
+    <name>B</name>
+    <price>3</price>
+  </part>
+  <part id="3">
+    <name>C</name>
+    <price>10</price>
+  </part>
+  <part id="5">
+    <name>E</name>
+    <price>10</price>
+  </part>
+</result>
diff --git a/tests/sequence_constructor/gold/test4.out b/tests/sequence_constructor/gold/test4.out
new file mode 100644
index 00000000..4d155fe6
--- /dev/null
+++ b/tests/sequence_constructor/gold/test4.out
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <part id="2">
+    <name>B</name>
+    <price>3</price>
+  </part>
+  <part id="3">
+    <name>C</name>
+    <price>10</price>
+  </part>
+</result>
diff --git a/tests/sequence_constructor/gold/test5.out b/tests/sequence_constructor/gold/test5.out
new file mode 100644
index 00000000..6b5f5a31
--- /dev/null
+++ b/tests/sequence_constructor/gold/test5.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>1 2 5 10</result>
diff --git a/tests/sequence_constructor/gold/test6.out b/tests/sequence_constructor/gold/test6.out
new file mode 100644
index 00000000..31219fba
--- /dev/null
+++ b/tests/sequence_constructor/gold/test6.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>1,A,3,C</result>
diff --git a/tests/sequence_constructor/gold/test7.out b/tests/sequence_constructor/gold/test7.out
new file mode 100644
index 00000000..69e1ad54
--- /dev/null
+++ b/tests/sequence_constructor/gold/test7.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>hello 1 2 A 1</result>
diff --git a/tests/sequence_constructor/test1.xsl b/tests/sequence_constructor/test1.xsl
new file mode 100644
index 00000000..a2ff84ca
--- /dev/null
+++ b/tests/sequence_constructor/test1.xsl
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence
+        construction using comma operator, and opening and closing
+        parentheses as boundary characters of the sequence construction
+        XPath expression string.
+        
+        The XPath expression strings, that're illustrated within this
+        XSLT stylesheet are borrowed from XPath 3.1 spec. -->                
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/">
+      <result>
+        <one><xsl:value-of select="(10, 1, 2, 3, 4)"/></one>
+        <two><xsl:value-of select="(10, 1 to 4)"/></two>
+      </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/sequence_constructor/test1_a.xml b/tests/sequence_constructor/test1_a.xml
new file mode 100644
index 00000000..5fb3adde
--- /dev/null
+++ b/tests/sequence_constructor/test1_a.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<bib>
+  <book>
+    <title>TCP/IP Illustrated</title>
+    <author>Stevens</author>
+    <publisher>Addison-Wesley</publisher>
+  </book>
+  <book>
+    <title>Advanced Programming in the Unix Environment</title>
+    <author>Stevens</author>
+    <publisher>Addison-Wesley</publisher>
+  </book>
+  <book>
+    <title>Data on the Web</title>
+    <author>Abiteboul</author>
+    <author>Buneman</author>
+    <author>Suciu</author>
+  </book>
+</bib>
+ 
\ No newline at end of file
diff --git a/tests/sequence_constructor/test1_b.xml b/tests/sequence_constructor/test1_b.xml
new file mode 100644
index 00000000..7cce0812
--- /dev/null
+++ b/tests/sequence_constructor/test1_b.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<items>
+  <part id="1">
+    <name>A</name>
+    <price>2</price>
+  </part>
+  <part id="2">
+    <name>B</name>
+    <price>3</price>
+  </part>
+  <part id="3">
+    <name>C</name>
+    <price>10</price>
+  </part>
+  <part id="4">
+    <name>D</name>
+    <price>7</price>
+  </part>
+  <part id="5">
+    <name>E</name>
+    <price>10</price>
+  </part>
+</items>
+ 
\ No newline at end of file
diff --git a/tests/sequence_constructor/test2.xsl b/tests/sequence_constructor/test2.xsl
new file mode 100644
index 00000000..392f564d
--- /dev/null
+++ b/tests/sequence_constructor/test2.xsl
@@ -0,0 +1,47 @@
+<?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_a.xml -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator.
+        
+        The XSLT stylesheet example transforms an XML input document into a list
+        in which each author's name appears only once, followed by a list of 
+        titles of books written by that author. This example assumes that the 
+        context item is the bib element in an XML input document.
+        
+        The XPath expression strings, that're illustrated within this
+        XSLT stylesheet are borrowed from XPath 3.1 spec. -->                
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/bib">
+      <result>
+        <xsl:copy-of select="for $a in distinct-values(book/author)
+                                                          return ((book/author[. = $a])[1], book[author = $a]/title)"/>
+      </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/sequence_constructor/test3.xsl b/tests/sequence_constructor/test3.xsl
new file mode 100644
index 00000000..cfc6913f
--- /dev/null
+++ b/tests/sequence_constructor/test3.xsl
@@ -0,0 +1,39 @@
+<?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_b.xml -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator. -->                
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/items">
+      <result>
+        <xsl:variable name="parts" select="(part[@id = 2], part[@id = 3], part[@id = 5])"/>
+        <xsl:copy-of select="$parts"/>
+      </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/sequence_constructor/test4.xsl b/tests/sequence_constructor/test4.xsl
new file mode 100644
index 00000000..0a02b806
--- /dev/null
+++ b/tests/sequence_constructor/test4.xsl
@@ -0,0 +1,40 @@
+<?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_b.xml -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator. -->                
+
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:variable name="partIds" select="(2, 3)"/>
+
+   <xsl:template match="/items">
+      <result>
+         <xsl:copy-of select="part[@id = $partIds]"/>
+      </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/sequence_constructor/test5.xsl b/tests/sequence_constructor/test5.xsl
new file mode 100644
index 00000000..b7ae9220
--- /dev/null
+++ b/tests/sequence_constructor/test5.xsl
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator.
+        
+        This stylesheet example demonstrates, using a combination of XPath
+        atomic values and function calls within the sequence constructor. -->                 
+
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:variable name="seq1" select="(1, 2, string-length('hello'), abs(-10))"/>
+
+   <xsl:template match="/">
+      <result>
+         <xsl:copy-of select="$seq1"/>
+      </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/sequence_constructor/test6.xsl b/tests/sequence_constructor/test6.xsl
new file mode 100644
index 00000000..fdc3ba32
--- /dev/null
+++ b/tests/sequence_constructor/test6.xsl
@@ -0,0 +1,44 @@
+<?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_b.xml -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator.
+        
+        This stylesheet example, uses a combination of function calls, XML element 
+        and attribute references, within an XPath sequence constructor 
+        expression. -->                
+
+   <xsl:output method="xml" indent="yes"/>      
+
+   <xsl:template match="/items">
+      <xsl:variable name="seq1" select="(string(part[1]/@id), string(part[1]/name), 
+                                                                 string(part[3]/@id), string(part[3]/name))"/>
+      <result>
+         <xsl:value-of select="string-join($seq1, ',')"/>
+      </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/sequence_constructor/test7.xsl b/tests/sequence_constructor/test7.xsl
new file mode 100644
index 00000000..0b5ace49
--- /dev/null
+++ b/tests/sequence_constructor/test7.xsl
@@ -0,0 +1,44 @@
+<?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_b.xml -->
+   
+   <!-- An XSLT stylesheet test, to test the XPath 3.1 sequence construction
+        using comma operator.
+        
+        This stylesheet example, uses a combination of variable references,
+        literals, XML element and attribute references within an XPath sequence 
+        constructor expression. -->                
+
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:variable name="mesg" select="'hello'"/>
+
+   <xsl:template match="/items">
+      <result>
+        <xsl:value-of select="($mesg, 1, 2, part[1]/name, part[1]/@id)"/>
+      </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


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