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/07 16:10:37 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing implementation of xpath 3.1 simple map operator '!', and few new related working test cases as well. other related minor changes to 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 2e44212d committing implementation of xpath 3.1 simple map operator '!', and few new related working test cases as well. other related minor changes to xalanj implementation, on this branch.
     new d8b17601 Merge pull request #45 from mukulga/xalan-j_xslt3.0_mukul
2e44212d is described below

commit 2e44212dd663e2e1552637edae051fda55f2971b
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Mon Aug 7 21:35:06 2023 +0530

    committing implementation of xpath 3.1 simple map operator '!', and few new related working test cases as well. other related minor changes to xalanj implementation, on this branch.
---
 src/org/apache/xalan/templates/ElemValueOf.java    |   4 +-
 src/org/apache/xalan/templates/ElemVariable.java   |   6 +
 src/org/apache/xpath/compiler/Compiler.java        | 112 +++++++++++++----
 src/org/apache/xpath/compiler/Lexer.java           |   2 +-
 src/org/apache/xpath/compiler/OpCodes.java         |   9 +-
 src/org/apache/xpath/compiler/XPathParser.java     |  35 ++++--
 src/org/apache/xpath/composite/ForExpr.java        |   4 +-
 src/org/apache/xpath/functions/FuncStringJoin.java |  12 ++
 src/org/apache/xpath/functions/FuncSum.java        |  61 ++++++----
 src/org/apache/xpath/operations/Operation.java     |  19 +++
 .../apache/xpath/operations/SimpleMapOperator.java | 124 +++++++++++++++++++
 tests/SimpleMapOperatorTests/company_2.xml         |  33 ++++++
 tests/SimpleMapOperatorTests/gold/test1.out        |   1 +
 tests/SimpleMapOperatorTests/gold/test2.out        |   1 +
 tests/SimpleMapOperatorTests/gold/test3.out        |   5 +
 tests/SimpleMapOperatorTests/gold/test4.out        |   6 +
 tests/SimpleMapOperatorTests/gold/test5.out        |   1 +
 tests/SimpleMapOperatorTests/gold/test6.out        |   1 +
 tests/SimpleMapOperatorTests/gold/test7.out        |   9 ++
 .../test6.xsl => SimpleMapOperatorTests/test1.xsl} |  19 +--
 tests/SimpleMapOperatorTests/test1_a.xml           |  17 +++
 tests/SimpleMapOperatorTests/test1_b.xml           |   9 ++
 tests/SimpleMapOperatorTests/test1_c.xml           |   9 ++
 tests/SimpleMapOperatorTests/test1_d.xml           |   9 ++
 .../test6.xsl => SimpleMapOperatorTests/test2.xsl} |  24 ++--
 .../test6.xsl => SimpleMapOperatorTests/test3.xsl} |  25 ++--
 .../test6.xsl => SimpleMapOperatorTests/test4.xsl} |  31 +++--
 .../test6.xsl => SimpleMapOperatorTests/test5.xsl} |  20 ++--
 .../test6.xsl                                      |  16 ++-
 .../test7.xsl                                      |  16 ++-
 .../test6.xsl => SimpleMapOperatorTests/test8.xsl} |  18 ++-
 tests/inline_function_expr/test6.xsl               |   2 +-
 tests/inline_function_expr/test7.xsl               |   2 +-
 .../xalan/xpath3/SimpleMapOperatorTests.java       | 132 +++++++++++++++++++++
 tests/org/apache/xalan/xslt3/AllXsl3Tests.java     |   3 +-
 35 files changed, 677 insertions(+), 120 deletions(-)

diff --git a/src/org/apache/xalan/templates/ElemValueOf.java b/src/org/apache/xalan/templates/ElemValueOf.java
index 76c74f6a..e6818c81 100644
--- a/src/org/apache/xalan/templates/ElemValueOf.java
+++ b/src/org/apache/xalan/templates/ElemValueOf.java
@@ -43,6 +43,7 @@ import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XString;
 import org.apache.xpath.operations.Operation;
 import org.apache.xpath.operations.Range;
+import org.apache.xpath.operations.SimpleMapOperator;
 import org.apache.xpath.operations.StrConcat;
 import org.apache.xpath.operations.Variable;
 import org.apache.xpath.xs.types.XSAnyType;
@@ -352,7 +353,8 @@ public class ElemValueOf extends ElemTemplateElement {
                      Operation opn = (Operation)expr;
                      
                      XObject evalResult = null;
-                     if ((opn instanceof Range) || (opn instanceof StrConcat)) {
+                     if ((opn instanceof Range) || (opn instanceof StrConcat) || 
+                                                                       (opn instanceof SimpleMapOperator)) {
                         evalResult = opn.execute(xctxt);                        
                      }
                      else {
diff --git a/src/org/apache/xalan/templates/ElemVariable.java b/src/org/apache/xalan/templates/ElemVariable.java
index ef811e18..87403c4a 100644
--- a/src/org/apache/xalan/templates/ElemVariable.java
+++ b/src/org/apache/xalan/templates/ElemVariable.java
@@ -46,6 +46,7 @@ import org.apache.xpath.objects.XRTreeFrag;
 import org.apache.xpath.objects.XRTreeFragSelectWrapper;
 import org.apache.xpath.objects.XString;
 import org.apache.xpath.operations.Operation;
+import org.apache.xpath.operations.SimpleMapOperator;
 import org.apache.xpath.xs.types.XSAnyType;
 import org.apache.xpath.xs.types.XSNumericType;
 import org.w3c.dom.NodeList;
@@ -334,6 +335,11 @@ public class ElemVariable extends ElemTemplateElement
                 return evalResult; 
             }
         }
+        else if (selectExpression instanceof SimpleMapOperator) {
+            XObject evalResult = selectExpression.execute(xctxt);
+            
+            return evalResult;
+        }
         else if (selectExpression instanceof Operation) {
             Operation opn = (Operation)selectExpression;
             XObject leftOperand = XSConstructorFunctionUtil.processFuncExtFunctionOrXPathOpn(
diff --git a/src/org/apache/xpath/compiler/Compiler.java b/src/org/apache/xpath/compiler/Compiler.java
index 307361ae..03465d72 100644
--- a/src/org/apache/xpath/compiler/Compiler.java
+++ b/src/org/apache/xpath/compiler/Compiler.java
@@ -59,6 +59,7 @@ import org.apache.xpath.operations.Operation;
 import org.apache.xpath.operations.Or;
 import org.apache.xpath.operations.Plus;
 import org.apache.xpath.operations.Range;
+import org.apache.xpath.operations.SimpleMapOperator;
 import org.apache.xpath.operations.StrConcat;
 import org.apache.xpath.operations.UnaryOperation;
 import org.apache.xpath.operations.Variable;
@@ -169,6 +170,8 @@ public class Compiler extends OpMap
       expr = nodeComparisonPrecede(opPos); break;
     case OpCodes.OP_NC_FOLLOWS :
       expr = nodeComparisonFollows(opPos); break;
+    case OpCodes.OP_SIMPLE_MAP_OPERATOR :
+      expr = simpleMapOperator(opPos); break;
     case OpCodes.OP_LTE :
       expr = lte(opPos); break;
     case OpCodes.OP_LT :
@@ -343,7 +346,13 @@ public class Compiler extends OpMap
   }
   
   /**
-   * Compile an XPath 3.1 value comparison 'eq' operation. 
+   * Compile an XPath 3.1 value comparison "eq" operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.VcEquals} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression vcEquals(int opPos) throws TransformerException
   {
@@ -351,7 +360,13 @@ public class Compiler extends OpMap
   }
   
   /**
-   * Compile an XPath 3.1 value comparison 'ne' operation. 
+   * Compile an XPath 3.1 value comparison "ne" operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.VcNotEquals} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression vcNotEquals(int opPos) throws TransformerException
   {
@@ -387,8 +402,13 @@ public class Compiler extends OpMap
   }
   
   /**
-   * Compile an XPath 3.1 value comparison 'lt' operation.
-   *  
+   * Compile an XPath 3.1 value comparison "lt" operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.VcLt} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression vcLt(int opPos) throws TransformerException
   {
@@ -396,8 +416,13 @@ public class Compiler extends OpMap
   }
   
   /**
-   * Compile an XPath 3.1 value comparison 'gt' operation.
-   *  
+   * Compile an XPath 3.1 value comparison "gt" operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.VcGt} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression vcGt(int opPos) throws TransformerException
   {
@@ -405,8 +430,13 @@ public class Compiler extends OpMap
   }
   
   /**
-   * Compile an XPath 3.1 value comparison 'le' operation.
-   *  
+   * Compile an XPath 3.1 value comparison "le" operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.VcLe} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression vcLe(int opPos) throws TransformerException
   {
@@ -414,8 +444,13 @@ public class Compiler extends OpMap
   }
   
   /**
-   * Compile an XPath 3.1 value comparison 'ge' operation.
-   *  
+   * Compile an XPath 3.1 value comparison "ge" operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.VcGe} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression vcGe(int opPos) throws TransformerException
   {
@@ -423,8 +458,13 @@ public class Compiler extends OpMap
   }
   
   /**
-   * Compile an XPath 3.1 node comparison 'is' operation.
-   *  
+   * Compile an XPath 3.1 node comparison "is" operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.NodeComparisonIs} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression nodeComparisonIs(int opPos) throws TransformerException
   {
@@ -432,8 +472,13 @@ public class Compiler extends OpMap
   }
   
   /**
-   * Compile an XPath 3.1 node comparison '<<' operation.
-   *  
+   * Compile an XPath 3.1 node comparison "<<" operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.NodeComparisonPrecede} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression nodeComparisonPrecede(int opPos) throws TransformerException
   {
@@ -441,13 +486,32 @@ public class Compiler extends OpMap
   }
   
   /**
-   * Compile an XPath 3.1 node comparison '>>' operation.
-   *  
+   * Compile an XPath 3.1 node comparison ">>" operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.NodeComparisonFollows} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression nodeComparisonFollows(int opPos) throws TransformerException
   {
     return compileOperation(new NodeComparisonFollows(), opPos);
   }
+  
+  /**
+   * Compile an XPath 3.1 simple map '!' operation.
+   * 
+   * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.SimpleMapOperator} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
+   */
+  protected Expression simpleMapOperator(int opPos) throws TransformerException
+  {
+    return compileOperation(new SimpleMapOperator(), opPos);
+  }
 
   /**
    * Compile a '>=' operation.
@@ -491,20 +555,28 @@ public class Compiler extends OpMap
     return compileOperation(new Plus(), opPos);
   }
   
-  /*
-   * Compile an XPath 3.1 "to" operation.
+  /**
+   * Compile an XPath 3.1 range "to" operation.
    * 
    * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.Range} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression range(int opPos) throws TransformerException
   {
     return compileOperation(new Range(), opPos);   
   }
   
-  /*
-   * Compile an XPath 3.1 "||" operation.
+  /**
+   * Compile an XPath 3.1 string concatenation "||" operation.
    * 
    * @param opPos The current position in the m_opMap array.
+   * 
+   * @return reference to {@link org.apache.xpath.operations.StrConcat} instance.
+   * 
+   * @throws TransformerException if a error occurs creating the Expression.
    */
   protected Expression strConcat(int opPos) throws TransformerException
   {
diff --git a/src/org/apache/xpath/compiler/Lexer.java b/src/org/apache/xpath/compiler/Lexer.java
index 008854a1..55eba0db 100644
--- a/src/org/apache/xpath/compiler/Lexer.java
+++ b/src/org/apache/xpath/compiler/Lexer.java
@@ -269,7 +269,7 @@ class Lexer
       case ',' :      
       case '\\' :  // Unused at the moment
       case '^' :   // Unused at the moment
-      case '!' :   // Unused at the moment
+      case '!' :   // added for XPath 3.1
       case '$' :
       case '<' :
       case '>' :
diff --git a/src/org/apache/xpath/compiler/OpCodes.java b/src/org/apache/xpath/compiler/OpCodes.java
index 5f9391d9..0aeb90bd 100644
--- a/src/org/apache/xpath/compiler/OpCodes.java
+++ b/src/org/apache/xpath/compiler/OpCodes.java
@@ -717,8 +717,15 @@ public class OpCodes
    * @xsl.usage advanced
    */
   public static final int OP_NC_FOLLOWS = 71;
+  
+  /**
+   * For XPath 3.1 simple map operator '!'.
+   * 
+   * @xsl.usage advanced
+   */
+  public static final int OP_SIMPLE_MAP_OPERATOR = 72;
 
   /** The next free ID. Please keep this up to date. */
-  private static final int NEXT_FREE_ID = 72;
+  private static final int NEXT_FREE_ID = 73;
   
 }
diff --git a/src/org/apache/xpath/compiler/XPathParser.java b/src/org/apache/xpath/compiler/XPathParser.java
index 9b8c9f5a..2705af45 100644
--- a/src/org/apache/xpath/compiler/XPathParser.java
+++ b/src/org/apache/xpath/compiler/XPathParser.java
@@ -1548,18 +1548,35 @@ public class XPathParser
 
     if (null != m_token)
     {
-      if (tokenIs('!') && lookahead('=', 1))
+      if (tokenIs('!'))
       {
-        nextToken();
-        nextToken();
-        insertOp(addPos, 2, OpCodes.OP_NOTEQUALS);
+        if (lookahead('=', 1)) 
+        {
+           nextToken();
+           nextToken();
+           insertOp(addPos, 2, OpCodes.OP_NOTEQUALS);
 
-        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
+           int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
 
-        addPos = EqualityExpr(addPos);
-        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
-          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
-        addPos += 2;
+           addPos = EqualityExpr(addPos);
+           m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
+             m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
+           addPos += 2;
+        }
+        else 
+        {
+           // support for XPath 3.1 simple map operator '!'
+            
+           nextToken();
+           insertOp(addPos, 2, OpCodes.OP_SIMPLE_MAP_OPERATOR);
+
+           int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
+
+           addPos = EqualityExpr(addPos);
+           m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
+              m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
+           addPos += 2;  
+        }
       }
       else if (tokenIs('='))
       {
diff --git a/src/org/apache/xpath/composite/ForExpr.java b/src/org/apache/xpath/composite/ForExpr.java
index 97ea4b34..b46c7ad6 100644
--- a/src/org/apache/xpath/composite/ForExpr.java
+++ b/src/org/apache/xpath/composite/ForExpr.java
@@ -201,8 +201,8 @@ public class ForExpr extends Expression {
                }
            }
            else {
-              // assuming here that, 'for' expression's variable binding XPath expression 
-              // evaluation, returned a singleton value.
+              // we're assuming here that, 'for' expression's variable binding XPath 
+              // expression evaluation, returned a singleton value.
               xsObjResultSeq.add(xsObj);
            }
            
diff --git a/src/org/apache/xpath/functions/FuncStringJoin.java b/src/org/apache/xpath/functions/FuncStringJoin.java
index c061d66c..7bf201dc 100644
--- a/src/org/apache/xpath/functions/FuncStringJoin.java
+++ b/src/org/apache/xpath/functions/FuncStringJoin.java
@@ -32,6 +32,7 @@ import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XNodeSet;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XString;
+import org.apache.xpath.operations.Operation;
 import org.apache.xpath.operations.Range;
 import org.apache.xpath.operations.Variable;
 import org.apache.xpath.res.XPATHErrorResources;
@@ -118,6 +119,17 @@ public class FuncStringJoin extends Function2Args {
             }                        
         }
     }
+    else if (m_arg0 instanceof Operation) {
+        arg0ResultSeq = new ResultSequence();
+        
+        XObject evalResult = ((Operation)m_arg0).execute(xctxt);
+        if (evalResult instanceof ResultSequence) {
+           ResultSequence resultSeq = (ResultSequence)evalResult;
+           for (int idx = 0; idx < resultSeq.size(); idx++) {
+              arg0ResultSeq.add(resultSeq.item(idx));  
+           }
+        }
+    }
     
     if (arg0ResultSeq == null) {
         throw new javax.xml.transform.TransformerException("The first argument of fn:string-join, "
diff --git a/src/org/apache/xpath/functions/FuncSum.java b/src/org/apache/xpath/functions/FuncSum.java
index 15d3ff5f..b8c0a699 100644
--- a/src/org/apache/xpath/functions/FuncSum.java
+++ b/src/org/apache/xpath/functions/FuncSum.java
@@ -29,6 +29,7 @@ import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XNumber;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XString;
+import org.apache.xpath.operations.SimpleMapOperator;
 import org.apache.xpath.operations.Variable;
 import org.apache.xpath.xs.types.XSAnyType;
 
@@ -58,33 +59,19 @@ public class FuncSum extends FunctionOneArg
        XObject resultObj = xslVariable.execute(xctxt);
        if (resultObj instanceof ResultSequence) {
           ResultSequence resultSeq = (ResultSequence)resultObj;
-          for (int idx = 0; idx < resultSeq.size(); idx++) {
-              XObject xObj = resultSeq.item(idx);
-              String str = xObj.str();
-              if (str != null) {
-                 XString xStr = new XString(str);
-                 sum +=  xStr.toDouble();
-              }
-          }
-       }
+          sum = sumResultSequence(resultSeq);          
+       }       
     }
     else if (m_arg0 instanceof ForExpr) {
        ForExpr forExpr = (ForExpr)m_arg0;
        ResultSequence forExprResult = (ResultSequence)(forExpr.execute(xctxt));
-       for (int idx = 0; idx < forExprResult.size(); idx++) {
-          XObject xObj = forExprResult.item(idx);
-          String str = null;
-          if (xObj instanceof XSAnyType) {
-             str = ((XSAnyType)xObj).stringValue();     
-          }
-          else {
-             str = xObj.str();
-          }
-          if (str != null) {
-             XString xStr = new XString(str);
-             sum +=  xStr.toDouble();
-          }
-       }
+       sum = sumResultSequence(forExprResult);
+    }
+    else if (m_arg0 instanceof SimpleMapOperator) {
+       SimpleMapOperator simpleMapOperator = (SimpleMapOperator)m_arg0;
+       ResultSequence simpleMapOperatorResult = (ResultSequence)(simpleMapOperator.
+                                                                              execute(xctxt));
+       sum = sumResultSequence(simpleMapOperatorResult);
     }
     else {
        int pos;
@@ -104,4 +91,32 @@ public class FuncSum extends FunctionOneArg
 
     return new XNumber(sum);
   }
+  
+  /**
+   * Summation of the values of ResultSequence data items.
+   *  
+   * @param resultSeq  The ResultSequence object instance, whose items
+   *                   need to be added to produce a summation value. 
+   * @return           The summation value with data type double.
+   */
+  private double sumResultSequence(ResultSequence resultSeq) {
+     double sum = 0.0;
+     
+     for (int idx = 0; idx < resultSeq.size(); idx++) {
+        XObject xObj = resultSeq.item(idx);
+        String str = null;
+        if (xObj instanceof XSAnyType) {
+           str = ((XSAnyType)xObj).stringValue();     
+        }
+        else {
+           str = xObj.str();
+        }
+        if (str != null) {
+           XString xStr = new XString(str);
+           sum +=  xStr.toDouble();
+        }
+     }
+     
+     return sum;
+  }
 }
diff --git a/src/org/apache/xpath/operations/Operation.java b/src/org/apache/xpath/operations/Operation.java
index 65f070d8..d4880bc1 100644
--- a/src/org/apache/xpath/operations/Operation.java
+++ b/src/org/apache/xpath/operations/Operation.java
@@ -27,6 +27,7 @@ import org.apache.xpath.Expression;
 import org.apache.xpath.ExpressionOwner;
 import org.apache.xpath.XPathContext;
 import org.apache.xpath.XPathVisitor;
+import org.apache.xpath.axes.SelfIteratorNoPredicate;
 import org.apache.xpath.functions.FuncExtFunction;
 import org.apache.xpath.objects.XObject;
 import org.xml.sax.SAXException;
@@ -129,6 +130,15 @@ public class Operation extends Expression implements ExpressionOwner
               left = m_left.execute(xctxt, true);  
            }
         }
+        else if (m_left instanceof SelfIteratorNoPredicate) {
+           XObject xpath3ContextItem = xctxt.getXPath3ContextItem();
+           if (xpath3ContextItem != null) {
+              left = xpath3ContextItem;     
+           }
+           else {
+              left = m_left.execute(xctxt, true);   
+           }
+        }
         else {
            left = m_left.execute(xctxt, true); 
         }
@@ -143,6 +153,15 @@ public class Operation extends Expression implements ExpressionOwner
               right = m_right.execute(xctxt, true);  
            }
         }
+        else if (m_right instanceof SelfIteratorNoPredicate) {
+            XObject xpath3ContextItem = xctxt.getXPath3ContextItem();
+            if (xpath3ContextItem != null) {
+               right = xpath3ContextItem;     
+            }
+            else {
+               right = m_right.execute(xctxt, true);   
+            }
+        }
         else {
            right = m_right.execute(xctxt, true); 
         }
diff --git a/src/org/apache/xpath/operations/SimpleMapOperator.java b/src/org/apache/xpath/operations/SimpleMapOperator.java
new file mode 100644
index 00000000..77aaec0b
--- /dev/null
+++ b/src/org/apache/xpath/operations/SimpleMapOperator.java
@@ -0,0 +1,124 @@
+/*
+ * 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.operations;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+
+import org.apache.xalan.templates.XSConstructorFunctionUtil;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMIterator;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.functions.FuncExtFunction;
+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.xs.types.XSAnyType;
+import org.xml.sax.SAXException;
+
+/**
+ * The XPath 3.1 simple map '!' operation.
+ * 
+ * Ref : https://www.w3.org/TR/xpath-31/#id-map-operator
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class SimpleMapOperator extends Operation
+{
+    
+   private static final long serialVersionUID = -1467842928587523219L;
+
+   public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
+   {
+       ResultSequence result = new ResultSequence();
+       
+       SourceLocator srcLocator = xctxt.getSAXLocator(); 
+       
+       XObject expr1 = null; 
+               
+       if (m_left instanceof FuncExtFunction) {
+           FuncExtFunction extFunction = (FuncExtFunction)m_left;
+           if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(extFunction.getNamespace())) {
+               try {
+                   expr1 = XSConstructorFunctionUtil.processFuncExtFunctionOrXPathOpn(xctxt, m_left);
+               }
+               catch (TransformerException ex) {
+                   throw ex; 
+               }
+               catch (SAXException ex) {
+                   throw new TransformerException(ex.getMessage(), srcLocator);
+               } 
+           }
+           else {
+              expr1 = m_left.execute(xctxt, true);  
+           }
+       }
+       else {
+           expr1 = m_left.execute(xctxt, true); 
+       }
+       
+       if (expr1 instanceof XNodeSet) {
+           XNodeSet xsObjNodeSet = (XNodeSet)expr1;
+           DTMIterator dtmIter = xsObjNodeSet.iterRaw();
+           
+           int contextNode;
+           
+           while ((contextNode = dtmIter.nextNode()) != DTM.NULL) {
+              xctxt.pushCurrentNode(contextNode);
+              XObject xsObj = m_right.execute(xctxt, contextNode);
+              result.add(xsObj);
+              xctxt.popCurrentNode();              
+           } 
+       }
+       else if (expr1 instanceof ResultSequence) {
+           ResultSequence rSeq = (ResultSequence)expr1;
+           for (int idx = 0; idx < rSeq.size(); idx++) {
+              XObject xObj = rSeq.item(idx);
+              if ((xObj instanceof XSAnyType) || (xObj instanceof XBoolean) || 
+                  (xObj instanceof XNumber) || (xObj instanceof XString)) {
+                  xctxt.setXPath3ContextItem(xObj);
+                  XObject xsObj1 = m_right.execute(xctxt, DTM.NULL);
+                  result.add(xsObj1);
+                  xctxt.setXPath3ContextItem(null);                  
+              }
+              else if (xObj instanceof XNodeSet) {
+                  int contextNode = ((XNodeSet)xObj).getCurrentNode();
+                  XObject xsObj = m_right.execute(xctxt, contextNode);
+                  result.add(xsObj);
+              }
+           }
+       }
+       else {
+           // we're assuming here that, the XObject object instance expr1
+           // represents a singleton value.
+           xctxt.setXPath3ContextItem(expr1);
+           XObject xsObj = m_right.execute(xctxt, DTM.NULL);
+           result.add(xsObj);
+           xctxt.setXPath3ContextItem(null);
+       }
+       
+       return result; 
+   }
+
+}
diff --git a/tests/SimpleMapOperatorTests/company_2.xml b/tests/SimpleMapOperatorTests/company_2.xml
new file mode 100644
index 00000000..a5b5bc92
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/company_2.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<company>
+  <office location="Boston">
+    <employee>
+      <first_name>John</first_name>
+      <last_name>Smith</last_name>
+      <age>25</age>
+    </employee>
+    <employee>
+      <first_name>John</first_name>
+      <last_name>Jones</last_name>
+      <age>30</age>
+    </employee>
+  </office>
+  <office location="Vienna">
+    <employee>
+      <first_name>Mary</first_name>
+      <last_name>Brown</last_name>
+      <age>30</age>
+    </employee>
+    <employee>
+      <first_name>Peter</first_name>
+      <last_name>Davis</last_name>
+      <age>34</age>
+    </employee>
+    <employee>
+      <first_name>Mark</first_name>
+      <last_name>Mason</last_name>
+      <age>44</age>
+    </employee>
+  </office>
+</company>
+
diff --git a/tests/SimpleMapOperatorTests/gold/test1.out b/tests/SimpleMapOperatorTests/gold/test1.out
new file mode 100644
index 00000000..a8875dd6
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/gold/test1.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>Hi John Hi John Hi Mary Hi Peter Hi Mark</result>
diff --git a/tests/SimpleMapOperatorTests/gold/test2.out b/tests/SimpleMapOperatorTests/gold/test2.out
new file mode 100644
index 00000000..4f1c0386
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/gold/test2.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>temp/c/three</result>
diff --git a/tests/SimpleMapOperatorTests/gold/test3.out b/tests/SimpleMapOperatorTests/gold/test3.out
new file mode 100644
index 00000000..2364b09e
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/gold/test3.out
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <path>temp/a/one</path>
+  <path>temp/b/two</path>
+  <path>temp/c/three</path>
+</result>
diff --git a/tests/SimpleMapOperatorTests/gold/test4.out b/tests/SimpleMapOperatorTests/gold/test4.out
new file mode 100644
index 00000000..6e21c996
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/gold/test4.out
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <val1>*******</val1>
+  <val2>*****</val2>
+  <val3>*******</val3>
+  <val4>*******</val4>
+</result>
diff --git a/tests/SimpleMapOperatorTests/gold/test5.out b/tests/SimpleMapOperatorTests/gold/test5.out
new file mode 100644
index 00000000..37663342
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/gold/test5.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>30</result>
diff --git a/tests/SimpleMapOperatorTests/gold/test6.out b/tests/SimpleMapOperatorTests/gold/test6.out
new file mode 100644
index 00000000..0f565b0e
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/gold/test6.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>140</result>
diff --git a/tests/SimpleMapOperatorTests/gold/test7.out b/tests/SimpleMapOperatorTests/gold/test7.out
new file mode 100644
index 00000000..faa1397e
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/gold/test7.out
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <mesg>xslt : HELLO</mesg>
+  <mesg>xslt : GOOD</mesg>
+  <mesg>xslt : BETTER</mesg>
+  <mesg>xslt : BEST</mesg>
+  <mesg>xslt : HI</mesg>
+  <mesg>xslt : THERE</mesg>
+  <mesg>xslt : THAT'S NICE</mesg>
+</result>
diff --git a/tests/inline_function_expr/test6.xsl b/tests/SimpleMapOperatorTests/test1.xsl
similarity index 71%
copy from tests/inline_function_expr/test6.xsl
copy to tests/SimpleMapOperatorTests/test1.xsl
index 0db32d1b..d440d676 100644
--- a/tests/inline_function_expr/test6.xsl
+++ b/tests/SimpleMapOperatorTests/test1.xsl
@@ -4,19 +4,20 @@
                 
    <!-- Author: mukulg@apache.org -->
    
-   <!-- use with test1_b.xml -->
+   <!-- use with company_2.xml -->
    
-   <!-- An XSLT stylesheet to test, an XPath function item "inline function"
-        expression that does transformation of its argument's value and
-        generates XML complex content. -->                   
+   <!-- An XSLT stylesheet, to test XPath 3.1 simple map 
+        operator '!'.
+        
+        This XSLT stylesheet, borrows an XPath '!' expression 
+        example from https://www.altova.com/, with slight
+        modifications. -->                 
 
    <xsl:output method="xml" indent="yes"/>
-   
-   <xsl:variable name="fnItem1" select="function ($nodeSet) { ($nodeSet[1]/p, $nodeSet[2]/p) }"/>
       
-   <xsl:template match="/temp">
-      <result>
-        <xsl:copy-of select="$fnItem1(*)"/>
+   <xsl:template match="/">
+      <result>         
+        <xsl:value-of select="/company/office/employee/first_name ! concat('Hi ', .)"/>                  
       </result>
    </xsl:template>
    
diff --git a/tests/SimpleMapOperatorTests/test1_a.xml b/tests/SimpleMapOperatorTests/test1_a.xml
new file mode 100644
index 00000000..3c46a1d4
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/test1_a.xml
@@ -0,0 +1,17 @@
+<temp>
+  <a>
+    <one>
+      <mesg>hello</mesg>
+    </one>
+  </a>
+  <b>
+    <two>
+      <mesg>there</mesg>
+    </two>
+  </b>
+  <c>
+    <three>
+      <mesg>how are you</mesg>
+    </three>
+  </c>
+</temp>
\ No newline at end of file
diff --git a/tests/SimpleMapOperatorTests/test1_b.xml b/tests/SimpleMapOperatorTests/test1_b.xml
new file mode 100644
index 00000000..562cfca3
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/test1_b.xml
@@ -0,0 +1,9 @@
+<temp>
+  <a>1</a>
+  <a>2</a>
+  <a>3</a>
+  <a>4</a>
+  <a>5</a>
+  <a>6</a>
+  <a>7</a>
+</temp>
\ No newline at end of file
diff --git a/tests/SimpleMapOperatorTests/test1_c.xml b/tests/SimpleMapOperatorTests/test1_c.xml
new file mode 100644
index 00000000..f548059c
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/test1_c.xml
@@ -0,0 +1,9 @@
+<temp>
+  <a val="1"/>
+  <a val="2"/>
+  <a val="3"/>
+  <a val="4"/>
+  <a val="5"/>
+  <a val="6"/>
+  <a val="7"/>
+</temp>
\ No newline at end of file
diff --git a/tests/SimpleMapOperatorTests/test1_d.xml b/tests/SimpleMapOperatorTests/test1_d.xml
new file mode 100644
index 00000000..ea6aad07
--- /dev/null
+++ b/tests/SimpleMapOperatorTests/test1_d.xml
@@ -0,0 +1,9 @@
+<temp>
+  <mesg>hello</mesg>
+  <mesg>good</mesg>
+  <mesg>better</mesg>
+  <mesg>best</mesg>
+  <mesg>hi</mesg>
+  <mesg>there</mesg>
+  <mesg>that's nice</mesg>
+</temp>
\ No newline at end of file
diff --git a/tests/inline_function_expr/test6.xsl b/tests/SimpleMapOperatorTests/test2.xsl
similarity index 59%
copy from tests/inline_function_expr/test6.xsl
copy to tests/SimpleMapOperatorTests/test2.xsl
index 0db32d1b..ff183af1 100644
--- a/tests/inline_function_expr/test6.xsl
+++ b/tests/SimpleMapOperatorTests/test2.xsl
@@ -4,19 +4,27 @@
                 
    <!-- Author: mukulg@apache.org -->
    
-   <!-- use with test1_b.xml -->
+   <!-- use with test1_a.xml -->
    
-   <!-- An XSLT stylesheet to test, an XPath function item "inline function"
-        expression that does transformation of its argument's value and
-        generates XML complex content. -->                   
+   <!-- An XSLT stylesheet, to test XPath 3.1 simple map 
+        operator '!'.
+        
+        The XPath expression having simple map operator '!',
+        as used within this stylesheet example, is borrowed
+        from XPath 3.1 spec, with slight modifications.
+        
+        The XPath expression example illustrated within this stylesheet
+        using the simple map operator '!', returns an XPath path string 
+        containing the names of the XML document ancestor elements of 
+        the given XML element, separated by "/" characters.        
+   -->                
 
    <xsl:output method="xml" indent="yes"/>
-   
-   <xsl:variable name="fnItem1" select="function ($nodeSet) { ($nodeSet[1]/p, $nodeSet[2]/p) }"/>
       
    <xsl:template match="/temp">
-      <result>
-        <xsl:copy-of select="$fnItem1(*)"/>
+      <result>         
+        <xsl:variable name="var1" select="c/three/mesg"/>
+        <xsl:value-of select="string-join($var1/ancestor::*!name(), '/')"/>                  
       </result>
    </xsl:template>
    
diff --git a/tests/inline_function_expr/test6.xsl b/tests/SimpleMapOperatorTests/test3.xsl
similarity index 60%
copy from tests/inline_function_expr/test6.xsl
copy to tests/SimpleMapOperatorTests/test3.xsl
index 0db32d1b..8c063d4d 100644
--- a/tests/inline_function_expr/test6.xsl
+++ b/tests/SimpleMapOperatorTests/test3.xsl
@@ -4,19 +4,28 @@
                 
    <!-- Author: mukulg@apache.org -->
    
-   <!-- use with test1_b.xml -->
+   <!-- use with test1_a.xml -->
    
-   <!-- An XSLT stylesheet to test, an XPath function item "inline function"
-        expression that does transformation of its argument's value and
-        generates XML complex content. -->                   
+   <!-- An XSLT stylesheet, to test XPath 3.1 simple map 
+        operator '!'.
+        
+        The XPath expression having simple map operator '!',
+        as used within this stylesheet example, is borrowed
+        from XPath 3.1 spec.
+        
+        The XPath expression example illustrated within this stylesheet
+        using the simple map operator '!', returns an XPath path string 
+        containing the names of the XML document ancestor elements of 
+        the given XML element, separated by "/" characters.        
+   -->                
 
    <xsl:output method="xml" indent="yes"/>
-   
-   <xsl:variable name="fnItem1" select="function ($nodeSet) { ($nodeSet[1]/p, $nodeSet[2]/p) }"/>
       
-   <xsl:template match="/temp">
+   <xsl:template match="/">
       <result>
-        <xsl:copy-of select="$fnItem1(*)"/>
+        <xsl:for-each select="//mesg">
+           <path><xsl:value-of select="string-join(ancestor::*!name(), '/')"/></path>
+        </xsl:for-each>
       </result>
    </xsl:template>
    
diff --git a/tests/inline_function_expr/test6.xsl b/tests/SimpleMapOperatorTests/test4.xsl
similarity index 51%
copy from tests/inline_function_expr/test6.xsl
copy to tests/SimpleMapOperatorTests/test4.xsl
index 0db32d1b..6b09dde7 100644
--- a/tests/inline_function_expr/test6.xsl
+++ b/tests/SimpleMapOperatorTests/test4.xsl
@@ -4,19 +4,34 @@
                 
    <!-- Author: mukulg@apache.org -->
    
-   <!-- use with test1_b.xml -->
-   
-   <!-- An XSLT stylesheet to test, an XPath function item "inline function"
-        expression that does transformation of its argument's value and
-        generates XML complex content. -->                   
+   <!-- An XSLT stylesheet, to test XPath 3.1 simple map 
+        operator '!'.
+        
+        The XPath expression having simple map operator '!',
+        as used within this stylesheet example, is borrowed
+        from XPath 3.1 spec.       
+   -->                
 
    <xsl:output method="xml" indent="yes"/>
    
-   <xsl:variable name="fnItem1" select="function ($nodeSet) { ($nodeSet[1]/p, $nodeSet[2]/p) }"/>
+   <xsl:variable name="n1" select="5"/>
       
-   <xsl:template match="/temp">
+   <xsl:template match="/">
+      <xsl:variable name="n2" select="7"/>
       <result>
-        <xsl:copy-of select="$fnItem1(*)"/>
+         <!-- returns a string containing 7 asterisks. -->
+         <val1><xsl:value-of select="string-join((1 to 7)!'*')"/></val1>
+         
+         <!-- returns a string containing $n1 asterisks. -->
+         <val2><xsl:value-of select="string-join((1 to $n1)!'*')"/></val2>
+         
+         <!-- returns a string containing $n2 asterisks. -->
+         <val3><xsl:value-of select="string-join((1 to $n2)!'*')"/></val3>
+         
+         <!-- store the result of, simple map operation '!' into a variable,
+              and use the variable's value subsequently. -->
+         <xsl:variable name="asteriskList" select="string-join((1 to $n2)!'*')"/>
+         <val4><xsl:value-of select="$asteriskList"/></val4>         
       </result>
    </xsl:template>
    
diff --git a/tests/inline_function_expr/test6.xsl b/tests/SimpleMapOperatorTests/test5.xsl
similarity index 68%
copy from tests/inline_function_expr/test6.xsl
copy to tests/SimpleMapOperatorTests/test5.xsl
index 0db32d1b..66b62dee 100644
--- a/tests/inline_function_expr/test6.xsl
+++ b/tests/SimpleMapOperatorTests/test5.xsl
@@ -4,19 +4,21 @@
                 
    <!-- Author: mukulg@apache.org -->
    
-   <!-- use with test1_b.xml -->
-   
-   <!-- An XSLT stylesheet to test, an XPath function item "inline function"
-        expression that does transformation of its argument's value and
-        generates XML complex content. -->                   
+   <!-- An XSLT stylesheet, to test XPath 3.1 simple map 
+        operator '!'.
+        
+        The XPath expression having simple map operator '!',
+        as used within this stylesheet example, is borrowed
+        from XPath 3.1 spec, with slight modifications.       
+   -->                 
 
    <xsl:output method="xml" indent="yes"/>
-   
-   <xsl:variable name="fnItem1" select="function ($nodeSet) { ($nodeSet[1]/p, $nodeSet[2]/p) }"/>
       
-   <xsl:template match="/temp">
+   <xsl:template match="/">
       <result>
-        <xsl:copy-of select="$fnItem1(*)"/>
+        <xsl:variable name="values" select="(1, 2, 3, 4)"/>
+        <!-- return the sum of the squares of a sequence of numbers. -->         
+        <xsl:value-of select="sum($values!(.*.))"/>
       </result>
    </xsl:template>
    
diff --git a/tests/inline_function_expr/test6.xsl b/tests/SimpleMapOperatorTests/test6.xsl
similarity index 71%
copy from tests/inline_function_expr/test6.xsl
copy to tests/SimpleMapOperatorTests/test6.xsl
index 0db32d1b..c4899232 100644
--- a/tests/inline_function_expr/test6.xsl
+++ b/tests/SimpleMapOperatorTests/test6.xsl
@@ -6,17 +6,21 @@
    
    <!-- use with test1_b.xml -->
    
-   <!-- An XSLT stylesheet to test, an XPath function item "inline function"
-        expression that does transformation of its argument's value and
-        generates XML complex content. -->                   
+   <!-- An XSLT stylesheet, to test XPath 3.1 simple map 
+        operator '!'.
+        
+        The XPath expression having simple map operator '!',
+        as used within this stylesheet example, is borrowed
+        from XPath 3.1 spec, with slight modifications.     
+   -->                
 
    <xsl:output method="xml" indent="yes"/>
-   
-   <xsl:variable name="fnItem1" select="function ($nodeSet) { ($nodeSet[1]/p, $nodeSet[2]/p) }"/>
       
    <xsl:template match="/temp">
       <result>
-        <xsl:copy-of select="$fnItem1(*)"/>
+         <xsl:variable name="values" select="a"/>
+         <!-- return the sum of the squares of a sequence of numbers. -->         
+         <xsl:value-of select="sum($values!(.*.))"/>
       </result>
    </xsl:template>
    
diff --git a/tests/inline_function_expr/test7.xsl b/tests/SimpleMapOperatorTests/test7.xsl
similarity index 71%
copy from tests/inline_function_expr/test7.xsl
copy to tests/SimpleMapOperatorTests/test7.xsl
index 3ee4a5d1..367daf31 100644
--- a/tests/inline_function_expr/test7.xsl
+++ b/tests/SimpleMapOperatorTests/test7.xsl
@@ -6,17 +6,21 @@
    
    <!-- use with test1_c.xml -->
    
-   <!-- An XSLT stylesheet to test, an XPath function item "inline function"
-        expression that does transformation of its argument's value and
-        generates XML complex content. -->                 
+   <!-- An XSLT stylesheet, to test XPath 3.1 simple map 
+        operator '!'.
+        
+        The XPath expression having simple map operator '!',
+        as used within this stylesheet example, is borrowed
+        from XPath 3.1 spec, with slight modifications.   
+   -->                
 
    <xsl:output method="xml" indent="yes"/>
-   
-   <xsl:variable name="fnItem1" select="function ($nodeSet) { for $a in $nodeSet return $a/p }"/>
       
    <xsl:template match="/temp">
       <result>
-        <xsl:copy-of select="$fnItem1(*)"/>
+        <xsl:variable name="values" select="a/@val"/>
+        <!-- return the sum of the squares of a sequence of numbers. -->         
+        <xsl:value-of select="sum($values!(.*.))"/>
       </result>
    </xsl:template>
    
diff --git a/tests/inline_function_expr/test6.xsl b/tests/SimpleMapOperatorTests/test8.xsl
similarity index 63%
copy from tests/inline_function_expr/test6.xsl
copy to tests/SimpleMapOperatorTests/test8.xsl
index 0db32d1b..2d42af55 100644
--- a/tests/inline_function_expr/test6.xsl
+++ b/tests/SimpleMapOperatorTests/test8.xsl
@@ -4,19 +4,25 @@
                 
    <!-- Author: mukulg@apache.org -->
    
-   <!-- use with test1_b.xml -->
+   <!-- use with test1_d.xml -->
    
-   <!-- An XSLT stylesheet to test, an XPath function item "inline function"
-        expression that does transformation of its argument's value and
-        generates XML complex content. -->                   
+   <!-- An XSLT stylesheet, to test XPath 3.1 simple map 
+        operator '!'.       
+   -->                 
 
    <xsl:output method="xml" indent="yes"/>
    
-   <xsl:variable name="fnItem1" select="function ($nodeSet) { ($nodeSet[1]/p, $nodeSet[2]/p) }"/>
+   <xsl:variable name="smallCase" select="'abcdefghijklmnopqrstuvwxyz'"/>
+   <xsl:variable name="upperCase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
       
    <xsl:template match="/temp">
       <result>
-        <xsl:copy-of select="$fnItem1(*)"/>
+        <!-- using two XPath simple map operations ! in sequence, with the
+             second ! processing the output produced by the first !. -->
+        <xsl:variable name="values" select="mesg ! translate(., $smallCase, $upperCase) ! concat('xslt : ', .)"/>         
+        <xsl:for-each select="$values">
+          <mesg><xsl:value-of select="."/></mesg>
+        </xsl:for-each>
       </result>
    </xsl:template>
    
diff --git a/tests/inline_function_expr/test6.xsl b/tests/inline_function_expr/test6.xsl
index 0db32d1b..3134c248 100644
--- a/tests/inline_function_expr/test6.xsl
+++ b/tests/inline_function_expr/test6.xsl
@@ -8,7 +8,7 @@
    
    <!-- An XSLT stylesheet to test, an XPath function item "inline function"
         expression that does transformation of its argument's value and
-        generates XML complex content. -->                   
+        produces XML complex content. -->                   
 
    <xsl:output method="xml" indent="yes"/>
    
diff --git a/tests/inline_function_expr/test7.xsl b/tests/inline_function_expr/test7.xsl
index 3ee4a5d1..20fd05bf 100644
--- a/tests/inline_function_expr/test7.xsl
+++ b/tests/inline_function_expr/test7.xsl
@@ -8,7 +8,7 @@
    
    <!-- An XSLT stylesheet to test, an XPath function item "inline function"
         expression that does transformation of its argument's value and
-        generates XML complex content. -->                 
+        produces XML complex content. -->                 
 
    <xsl:output method="xml" indent="yes"/>
    
diff --git a/tests/org/apache/xalan/xpath3/SimpleMapOperatorTests.java b/tests/org/apache/xalan/xpath3/SimpleMapOperatorTests.java
new file mode 100644
index 00000000..ac4bef1d
--- /dev/null
+++ b/tests/org/apache/xalan/xpath3/SimpleMapOperatorTests.java
@@ -0,0 +1,132 @@
+/*
+ * 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 simple map operator '!' test cases.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class SimpleMapOperatorTests extends XslTransformTestsUtil {        
+    
+    private static final String XSL_TRANSFORM_INPUT_DIRPATH = XSLConstants.XSL_TRANSFORM_INPUT_DIRPATH_PREFIX + 
+                                                                                                    "SimpleMapOperatorTests/";
+    
+    private static final String XSL_TRANSFORM_GOLD_DIRPATH = XSLConstants.XSL_TRANSFORM_GOLD_DIRPATH_PREFIX + 
+                                                                                                    "SimpleMapOperatorTests/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 xslSimpleMapOperatorTest1() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "company_2.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test1.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSimpleMapOperatorTest2() {
+        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 xslSimpleMapOperatorTest3() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_a.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 xslSimpleMapOperatorTest4() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test4.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSimpleMapOperatorTest5() {
+        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 xslSimpleMapOperatorTest6() {
+        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 xslSimpleMapOperatorTest7() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_c.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test7.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test6.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslSimpleMapOperatorTest8() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_d.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test8.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 423892f7..6227f74e 100644
--- a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
+++ b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
@@ -36,6 +36,7 @@ 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.SimpleMapOperatorTests;
 import org.apache.xalan.xpath3.StringConcatExprTests;
 import org.apache.xalan.xpath3.StringTests;
 import org.apache.xalan.xpath3.TrignometricAndExponentialFunctionTests;
@@ -71,7 +72,7 @@ import org.junit.runners.Suite.SuiteClasses;
                 TrignometricAndExponentialFunctionTests.class, BuiltinFunctionsNamespceTests.class,
                 SequenceConstructorTests.class, StringConcatExprTests.class, 
                 XsDurationComponentExtractionFunctionTests.class, XPathArithmeticOnDurationValuesTests.class,
-                NodeComparisonTests.class })
+                NodeComparisonTests.class, SimpleMapOperatorTests.class })
 public class AllXsl3Tests {
 
 }


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