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/06/29 15:10:35 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing implementation of xpath 3.1 function item inline function expressions. also committing implementations of xpath 3.1 higher-order functions fn:for-each and fn:filter, that use inline function expressions as arguments. also committing as well, few related working test cases as well.

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 1ed00b9c committing implementation of xpath 3.1 function item inline function expressions. also committing implementations of xpath 3.1 higher-order functions fn:for-each and fn:filter, that use inline function expressions as arguments. also committing as well, few related working test cases as well.
     new 0456d97e Merge pull request #13 from mukulga/xalan-j_xslt3.0_mukul
1ed00b9c is described below

commit 1ed00b9c3cb2e34eba6c061301342cbd4e56d2ba
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Thu Jun 29 20:29:25 2023 +0530

    committing implementation of xpath 3.1 function item inline function expressions. also committing implementations of xpath 3.1 higher-order functions fn:for-each and fn:filter, that use inline function expressions as arguments. also committing as well, few related working test cases as well.
---
 src/org/apache/xalan/templates/ElemCopyOf.java    |  60 +++++-
 src/org/apache/xpath/XPathContext.java            |  14 ++
 src/org/apache/xpath/compiler/Compiler.java       |   7 +
 src/org/apache/xpath/compiler/FunctionTable.java  |  16 +-
 src/org/apache/xpath/compiler/Keywords.java       |   8 +-
 src/org/apache/xpath/compiler/OpCodes.java        |   4 +-
 src/org/apache/xpath/compiler/XPathParser.java    |  92 ++++++++-
 src/org/apache/xpath/functions/FuncConcat.java    |   2 +-
 src/org/apache/xpath/functions/FuncFilter.java    | 237 ++++++++++++++++++++++
 src/org/apache/xpath/functions/FuncForEach.java   | 212 +++++++++++++++++++
 src/org/apache/xpath/objects/InlineFunction.java  |  77 +++++++
 src/org/apache/xpath/objects/ResultSequence.java  |   9 +-
 src/org/apache/xpath/objects/XObject.java         |   3 +
 src/org/apache/xpath/operations/Mult.java         |  22 +-
 src/org/apache/xpath/operations/Variable.java     |  13 ++
 src/org/apache/xpath/res/XPATHErrorResources.java |  21 +-
 src/org/apache/xpath/xs/types/XSInteger.java      |   4 +
 tests/fn_filter/gold/test1.out                    |   4 +
 tests/fn_filter/gold/test2.out                    |   1 +
 tests/fn_filter/gold/test3.out                    |   9 +
 tests/fn_filter/test1.xsl                         |  36 ++++
 tests/fn_filter/test1_a.xml                       |  10 +
 tests/fn_filter/test1_b.xml                       |  13 ++
 tests/fn_filter/test2.xsl                         |  37 ++++
 tests/fn_filter/test3.xsl                         |  38 ++++
 tests/fn_foreach/gold/test1.out                   |   1 +
 tests/fn_foreach/gold/test2.out                   |   9 +
 tests/fn_foreach/gold/test3.out                   |  14 ++
 tests/fn_foreach/gold/test4.out                   |   9 +
 tests/fn_foreach/gold/test5.out                   |  20 ++
 tests/fn_foreach/gold/test6.out                   |   7 +
 tests/fn_foreach/gold/test7.out                   |   7 +
 tests/fn_foreach/gold/test8.out                   |   7 +
 tests/fn_foreach/test1.xsl                        |  35 ++++
 tests/fn_foreach/test1_a.xml                      |  10 +
 tests/fn_foreach/test1_b.xml                      |  13 ++
 tests/fn_foreach/test2.xsl                        |  39 ++++
 tests/fn_foreach/test3.xsl                        |  41 ++++
 tests/fn_foreach/test4.xsl                        |  45 ++++
 tests/fn_foreach/test5.xsl                        |  53 +++++
 tests/fn_foreach/test6.xsl                        |  52 +++++
 tests/fn_foreach/test7.xsl                        |  52 +++++
 tests/fn_foreach/test8.xsl                        |  52 +++++
 tests/org/apache/xalan/xpath3/FnFilterTests.java  |  80 ++++++++
 tests/org/apache/xalan/xpath3/FnForEachTests.java | 130 ++++++++++++
 tests/org/apache/xalan/xslt3/AllXsl3Tests.java    |   4 +-
 46 files changed, 1612 insertions(+), 17 deletions(-)

diff --git a/src/org/apache/xalan/templates/ElemCopyOf.java b/src/org/apache/xalan/templates/ElemCopyOf.java
index 5fadba64..6acb612a 100644
--- a/src/org/apache/xalan/templates/ElemCopyOf.java
+++ b/src/org/apache/xalan/templates/ElemCopyOf.java
@@ -32,15 +32,21 @@ import org.apache.xalan.serialize.SerializerUtils;
 import org.apache.xml.serializer.SerializationHandler;
 import org.apache.xpath.XPath;
 import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XObject;
 
-/**
- * Implement xsl:copy-of.
- * <pre>
- * <!ELEMENT xsl:copy-of EMPTY>
- * <!ATTLIST xsl:copy-of select %expr; #REQUIRED>
- * </pre>
- * @see <a href="http://www.w3.org/TR/xslt#copy-of">copy-of in XSLT Specification</a>
+/*
+ * Implementation of XSLT xsl:copy-of instruction.
+ * 
+ * XSLT 3.0 xsl:copy-of instruction definition,
+ *  
+ * <xsl:copy-of
+          select = expression
+          copy-accumulators? = boolean
+          copy-namespaces? = boolean
+          type? = eqname
+          validation? = "strict" | "lax" | "preserve" | "strip" />
+ * 
  * @xsl.usage advanced
  */
 public class ElemCopyOf extends ElemTemplateElement
@@ -192,6 +198,46 @@ public class ElemCopyOf extends ElemTemplateElement
           SerializerUtils.outputResultTreeFragment(
             handler, value, transformer.getXPathContext());
           break;
+        case XObject.CLASS_RESULT_SEQUENCE :
+          // added for XSLT 3.0
+          ResultSequence resultSequence = (ResultSequence)value;
+          for (int idx = 0; idx < resultSequence.size(); idx++) {
+             XObject sequenceItem = resultSequence.item(idx);
+             
+             if (sequenceItem.getType() == XObject.CLASS_STRING) {
+                 String str = sequenceItem.str();
+                 handler.characters(str.toCharArray(), 0, str.length());
+                 if (idx < (resultSequence.size() - 1)) {
+                     String strSpace = " ";
+                     handler.characters(strSpace.toCharArray(), 0, strSpace.length());
+                 }
+                 continue;
+             }
+             
+             DTMIterator dtmIter = sequenceItem.iter();
+
+             DTMTreeWalker dtmTreeWalker = new TreeWalker2Result(transformer, handler);
+             int nodePos;
+
+             while (DTM.NULL != (nodePos = dtmIter.nextNode())) {
+               DTM dtm = xctxt.getDTMManager().getDTM(nodePos);
+               short t = dtm.getNodeType(nodePos);
+
+               if (t == DTM.DOCUMENT_NODE) {
+                 for (int child = dtm.getFirstChild(nodePos); child != DTM.NULL; 
+                                                                 child = dtm.getNextSibling(child)) {
+                   dtmTreeWalker.traverse(child);
+                 }
+               }
+               else if (t == DTM.ATTRIBUTE_NODE) {
+                 SerializerUtils.addAttribute(handler, nodePos);
+               }
+               else {
+                 dtmTreeWalker.traverse(nodePos);
+               }
+             }
+          }
+          break;
         default :
           
           s = value.str();
diff --git a/src/org/apache/xpath/XPathContext.java b/src/org/apache/xpath/XPathContext.java
index 5ecccfc0..9fba1a4d 100644
--- a/src/org/apache/xpath/XPathContext.java
+++ b/src/org/apache/xpath/XPathContext.java
@@ -49,6 +49,7 @@ import org.apache.xml.utils.IntStack;
 import org.apache.xml.utils.NodeVector;
 import org.apache.xml.utils.ObjectStack;
 import org.apache.xml.utils.PrefixResolver;
+import org.apache.xml.utils.QName;
 import org.apache.xml.utils.SAXSourceLocator;
 import org.apache.xml.utils.XMLString;
 import org.apache.xpath.axes.SubContextList;
@@ -127,6 +128,11 @@ public class XPathContext extends DTMManager // implements ExpressionContext
   private GregorianCalendar m_currentDateTime;
   
   private XSDuration m_timezone;
+  
+  // we use this java.util.Map object, to store for XPath 3.1 function item 
+  // "inline function" the parameter names and their values. we don't use,
+  // XalanJ XPath context's variable stack for this purpose. 
+  private Map<QName, XObject> inlineFunctionVarMap = new HashMap<QName, XObject>();
 	
   /**
    * Though XPathContext context extends 
@@ -1450,5 +1456,13 @@ public class XPathContext extends DTMManager // implements ExpressionContext
  public void setTimezone(XSDuration timezone) {
      this.m_timezone = timezone;
  }
+
+ public Map<QName, XObject> getInlineFunctionVarMap() {
+     return inlineFunctionVarMap;
+ }
+
+ public void setInlineFunctionVarMap(Map<QName, XObject> inlineFunctionVarMap) {
+     this.inlineFunctionVarMap = inlineFunctionVarMap;
+ }
   
 }
diff --git a/src/org/apache/xpath/compiler/Compiler.java b/src/org/apache/xpath/compiler/Compiler.java
index d56e8560..23a520f8 100644
--- a/src/org/apache/xpath/compiler/Compiler.java
+++ b/src/org/apache/xpath/compiler/Compiler.java
@@ -195,6 +195,8 @@ public class Compiler extends OpMap
       expr = compileExtension(opPos); break;
     case OpCodes.OP_FUNCTION :
       expr = compileFunction(opPos); break;
+    case OpCodes.OP_INLINE_FUNCTION :
+      expr = compileInlineFunction(opPos); break;
     case OpCodes.OP_LOCATIONPATH :
       expr = locationPath(opPos); break;
     case OpCodes.OP_PREDICATE :
@@ -1156,6 +1158,11 @@ private static final boolean DEBUG = false;
       return null;
     }
   }
+  
+  Expression compileInlineFunction(int opPos) throws TransformerException
+  {
+      return XPathParser.fInlineFunction;
+  }
 
   // The current id for extension functions.
   private static long s_nextMethodId = 0;
diff --git a/src/org/apache/xpath/compiler/FunctionTable.java b/src/org/apache/xpath/compiler/FunctionTable.java
index e0101823..e9251ee6 100644
--- a/src/org/apache/xpath/compiler/FunctionTable.java
+++ b/src/org/apache/xpath/compiler/FunctionTable.java
@@ -179,6 +179,12 @@ public class FunctionTable
   
   /** The 'index-of()' id. */
   public static final int FUNC_INDEX_OF = 52;
+  
+  /** The 'for-each()' id. */
+  public static final int FUNC_FOR_EACH = 53;
+  
+  /** The 'filter()' id. */
+  public static final int FUNC_FILTER = 54;
 
   // Proprietary
 
@@ -207,7 +213,7 @@ public class FunctionTable
    * Number of built in functions. Be sure to update this as
    * built-in functions are added.
    */
-  private static final int NUM_BUILT_IN_FUNCS = 53;
+  private static final int NUM_BUILT_IN_FUNCS = 55;
 
   /**
    * Number of built-in functions that may be added.
@@ -305,6 +311,10 @@ public class FunctionTable
       org.apache.xpath.functions.FuncImplicitTimezone.class;
     m_functions[FUNC_INDEX_OF] = 
       org.apache.xpath.functions.FuncIndexOf.class;
+    m_functions[FUNC_FOR_EACH] = 
+      org.apache.xpath.functions.FuncForEach.class;
+    m_functions[FUNC_FILTER] = 
+      org.apache.xpath.functions.FuncFilter.class;
   }
 
   static{
@@ -410,6 +420,10 @@ public class FunctionTable
                           new Integer(FunctionTable.FUNC_IMPLICIT_TIMEZONE));
           m_functionID.put(Keywords.FUNC_INDEX_OF,
                           new Integer(FunctionTable.FUNC_INDEX_OF));
+          m_functionID.put(Keywords.FUNC_FOR_EACH,
+                          new Integer(FunctionTable.FUNC_FOR_EACH));
+          m_functionID.put(Keywords.FUNC_FILTER,
+                          new Integer(FunctionTable.FUNC_FILTER));
   }
   
   public FunctionTable(){
diff --git a/src/org/apache/xpath/compiler/Keywords.java b/src/org/apache/xpath/compiler/Keywords.java
index 5bfd7851..9e66c05c 100644
--- a/src/org/apache/xpath/compiler/Keywords.java
+++ b/src/org/apache/xpath/compiler/Keywords.java
@@ -259,13 +259,19 @@ public class Keywords
   
   /** index-of function string. */
   public static final String FUNC_INDEX_OF = "index-of";
+  
+  /** for-each function string. */
+  public static final String FUNC_FOR_EACH = "for-each";
+  
+  /** filter function string. */
+  public static final String FUNC_FILTER = "filter";
 
   // Proprietary, built in functions
 
   /** current function string (Proprietary). */
   public static final String FUNC_DOCLOCATION_STRING = "document-location";
   
-  //XML Schema built-in types constructor functions, configurations
+  // XML Schema built-in types constructor functions, configurations
   
   /** xs:decimal data type string. */
   public static final String FUNC_XS_DECIMAL = "decimal";
diff --git a/src/org/apache/xpath/compiler/OpCodes.java b/src/org/apache/xpath/compiler/OpCodes.java
index 82076356..c8d71dfa 100644
--- a/src/org/apache/xpath/compiler/OpCodes.java
+++ b/src/org/apache/xpath/compiler/OpCodes.java
@@ -675,8 +675,10 @@ public class OpCodes
    * @xsl.usage advanced
    */
   public static final int OP_VC_GE = 60;
+  
+  public static final int OP_INLINE_FUNCTION = 61;
 
   /** The next free ID. Please keep this up to date. */
-  private static final int NEXT_FREE_ID = 61;
+  private static final int NEXT_FREE_ID = 62;
   
 }
diff --git a/src/org/apache/xpath/compiler/XPathParser.java b/src/org/apache/xpath/compiler/XPathParser.java
index ec199d32..867a5813 100644
--- a/src/org/apache/xpath/compiler/XPathParser.java
+++ b/src/org/apache/xpath/compiler/XPathParser.java
@@ -20,6 +20,9 @@
  */
 package org.apache.xpath.compiler;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.xml.transform.ErrorListener;
 import javax.xml.transform.TransformerException;
 
@@ -27,6 +30,7 @@ import org.apache.xalan.res.XSLMessages;
 import org.apache.xml.utils.PrefixResolver;
 import org.apache.xpath.XPathProcessorException;
 import org.apache.xpath.domapi.XPathStylesheetDOM3Exception;
+import org.apache.xpath.objects.InlineFunction;
 import org.apache.xpath.objects.XNumber;
 import org.apache.xpath.objects.XString;
 import org.apache.xpath.res.XPATHErrorResources;
@@ -71,6 +75,8 @@ public class XPathParser
   protected final static int FILTER_MATCH_FAILED     = 0;
   protected final static int FILTER_MATCH_PRIMARY    = 1;
   protected final static int FILTER_MATCH_PREDICATES = 2;
+  
+  static InlineFunction fInlineFunction = null;
 
   /**
    * The parser constructor.
@@ -1494,6 +1500,7 @@ public class XPathParser
    * | Literal
    * | Number
    * | FunctionCall
+   * | FunctionItemExpr
    *
    * @return true if this method successfully matched a PrimaryExpr
    *
@@ -1503,7 +1510,8 @@ public class XPathParser
   protected boolean PrimaryExpr() throws javax.xml.transform.TransformerException
   {
 
-    boolean matchFound;
+    boolean matchFound = false;
+    
     int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
 
     if ((m_tokenChar == '\'') || (m_tokenChar == '"'))
@@ -1550,6 +1558,19 @@ public class XPathParser
 
       matchFound = true;
     }
+    else if (tokenIs("function") && lookahead('(', 1)) {
+      // support for XPath 3.1 function item "inline function" expressions
+      
+      appendOp(2, OpCodes.OP_INLINE_FUNCTION);
+      
+      fInlineFunction = InlineFunctionExpr();
+      
+      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
+              m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
+      
+      matchFound = true;
+         
+    }
     else if (lookahead('(', 1) || (lookahead(':', 1) && lookahead('(', 3)))
     {
       matchFound = FunctionCall();
@@ -1561,6 +1582,75 @@ public class XPathParser
 
     return matchFound;
   }
+  
+  protected InlineFunction InlineFunctionExpr() throws javax.xml.transform.TransformerException {
+      InlineFunction inlineFunction = new InlineFunction();
+      
+      List<String> funcParamNameList = new ArrayList<String>();      
+      String funcBodyXPathExprStr = null;
+      
+      nextToken();
+      
+      consumeExpected('(');
+
+      if (!tokenIs(')')) {
+          while (!tokenIs(')') && m_token != null)
+          {
+              if (tokenIs(','))
+              {
+                  error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_PRECEDING_PARAM, null);
+              }
+    
+              if (m_tokenChar == '$')
+              {
+                  nextToken();
+                  funcParamNameList.add(m_token);
+                  nextToken();
+              }
+    
+              if (!tokenIs(')'))
+              {
+                  consumeExpected(',');
+    
+                  if (tokenIs(')'))
+                  {
+                      error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_FOLLOWING_PARAM, null);                    
+                  }
+              }
+          }    
+      }
+      
+      if (funcParamNameList.size() > 1) {
+          error(XPATHErrorResources.ER_INLINE_FUNCTION_PARAM_CARDINALITY, new Object[] { 
+                                                                Integer.valueOf(funcParamNameList.size()) });   
+      }
+      
+      inlineFunction.setFuncParamNameList(funcParamNameList);
+      
+      consumeExpected(')');
+      
+      consumeExpected('{');
+      
+      StringBuffer funcBodyXPathExprStrBuff = new StringBuffer();
+      
+      if (tokenIs('}')) {
+          consumeExpected('}');    
+      }
+      else {
+         while (!tokenIs('}') && m_token != null)
+         {
+             funcBodyXPathExprStrBuff.append(m_token);
+             nextToken();
+         }         
+         consumeExpected('}');         
+      }
+      
+      funcBodyXPathExprStr = funcBodyXPathExprStrBuff.toString();
+      
+      inlineFunction.setFuncBodyXPathExprStr(funcBodyXPathExprStr);
+      
+      return inlineFunction;
+  }
 
   /**
    *
diff --git a/src/org/apache/xpath/functions/FuncConcat.java b/src/org/apache/xpath/functions/FuncConcat.java
index 63f4fac8..948f4451 100644
--- a/src/org/apache/xpath/functions/FuncConcat.java
+++ b/src/org/apache/xpath/functions/FuncConcat.java
@@ -124,7 +124,7 @@ public class FuncConcat extends FunctionMultiArgs
           }
       }
       else {
-          resultStr = expr.execute(xctxt).str(); 
+          resultStr = expr.execute(xctxt).str();
       }
       
       return resultStr;      
diff --git a/src/org/apache/xpath/functions/FuncFilter.java b/src/org/apache/xpath/functions/FuncFilter.java
new file mode 100644
index 00000000..595f9fd6
--- /dev/null
+++ b/src/org/apache/xpath/functions/FuncFilter.java
@@ -0,0 +1,237 @@
+/*
+ * 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.functions;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+
+import org.apache.xalan.res.XSLMessages;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMIterator;
+import org.apache.xml.utils.QName;
+import org.apache.xpath.Expression;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.axes.LocPathIterator;
+import org.apache.xpath.objects.InlineFunction;
+import org.apache.xpath.objects.ResultSequence;
+import org.apache.xpath.objects.XBoolean;
+import org.apache.xpath.objects.XNodeSet;
+import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XObjectFactory;
+import org.apache.xpath.operations.Variable;
+import org.apache.xpath.res.XPATHErrorResources;
+import org.w3c.dom.Node;
+
+/**
+ * Execute the filter() function.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+/*
+ * fn:filter is one of XPath 3.1's higher-order function
+ * (ref, https://www.w3.org/TR/xpath-functions-31/#higher-order-functions).
+ * 
+ * The XPath function fn:filter has following signature, and definition,
+ * 
+ * fn:filter($seq as item()*, $f as function(item()) as xs:boolean) as item()*
+ * 
+ * The function fn:filter returns those items from the sequence $seq for which the 
+ * supplied function $f returns true.
+ * 
+ * Error conditions,
+   As a consequence of the function signature and the function calling rules, a type 
+   error occurs if the supplied function $f returns anything other than a single 
+   xs:boolean item. There is no conversion to an effective boolean value.
+ */
+public class FuncFilter extends Function2Args {
+
+   private static final long serialVersionUID = 2912594883291006421L;
+   
+   private static final String FUNCTION_NAME = "filter()"; 
+
+  /**
+   * Execute the function. The function must return a valid object.
+   * 
+   * @param xctxt The current execution context.
+   * 
+   * @return A valid XObject.
+   *
+   * @throws javax.xml.transform.TransformerException
+   */
+  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
+  {
+      
+        XObject funcEvaluationResult = null;
+        
+        final int contextNode = xctxt.getCurrentNode();
+        
+        Expression arg0 = getArg0();
+        Expression arg1 = getArg1();                
+        
+        DTMIterator arg0DtmIterator = null;
+        
+        XObject arg0XsObject = null;
+                  
+        if (arg0 instanceof LocPathIterator) {
+            arg0DtmIterator = arg0.asIterator(xctxt, contextNode);               
+        }
+        else {
+            arg0XsObject = arg0.execute(xctxt, contextNode);
+        }
+        
+        ResultSequence resultSeq = new ResultSequence();
+                    
+        if (arg1 instanceof InlineFunction) {            
+            resultSeq = evaluateFnFilter(xctxt, arg0XsObject, arg0DtmIterator, (InlineFunction)arg1); 
+        }
+        else if (arg1 instanceof Variable) {
+            XObject arg1VarValue = arg1.execute(xctxt);
+            if (arg1VarValue instanceof InlineFunction) {
+                resultSeq = evaluateFnFilter(xctxt, arg0XsObject, arg0DtmIterator, (InlineFunction)arg1VarValue);   
+            }
+            else {
+                throw new javax.xml.transform.TransformerException("FORG0006 : The second argument to function call filter(), "
+                                                                                               + "is not a function item.", xctxt.getSAXLocator());    
+            }
+        }
+        else {
+            throw new javax.xml.transform.TransformerException("FORG0006 : The second argument to function call filter(), "
+                                                                                           + "is not a function item.", xctxt.getSAXLocator());               
+        }            
+        
+        funcEvaluationResult = resultSeq;
+        
+        return funcEvaluationResult;
+  }
+
+  /**
+   * Check that the number of arguments passed to this function is correct.
+   *
+   * @param argNum The number of arguments that is being passed to the function.
+   *
+   * @throws WrongNumberArgsException
+   */
+  public void checkNumberArgs(int argNum) throws WrongNumberArgsException
+  {
+     if (argNum != 2) {
+        reportWrongNumberArgs();
+     }
+  }
+
+  /**
+   * Constructs and throws a WrongNumberArgException with the appropriate
+   * message for this function object.
+   *
+   * @throws WrongNumberArgsException
+   */
+  protected void reportWrongNumberArgs() throws WrongNumberArgsException {
+      throw new WrongNumberArgsException(XSLMessages.createXPATHMessage(
+                                              XPATHErrorResources.ER_TWO, null)); //"2"
+  }
+  
+  /*
+   * Evaluate the function call fn:filter.
+   */
+  private ResultSequence evaluateFnFilter(XPathContext xctxt, XObject arg0XsObject, 
+                                               DTMIterator arg0DtmIterator, InlineFunction arg1) 
+                                                                                    throws TransformerException {
+
+        ResultSequence resultSeq = new ResultSequence(); 
+        
+        List<String> funcParamNameList = arg1.getFuncParamNameList();
+        String funcBodyXPathExprStr = arg1.getFuncBodyXPathExprStr();
+        
+        if (funcBodyXPathExprStr == null || "".equals(funcBodyXPathExprStr)) {
+           return resultSeq;
+        }
+        
+        QName varQname = null;
+        
+        if (funcParamNameList.size() == 1) {
+           varQname = new QName(funcParamNameList.get(0));
+        }
+        
+        SourceLocator srcLocator = xctxt.getSAXLocator();
+        
+        XPath xpathInlineFn = new XPath(funcBodyXPathExprStr, srcLocator, null, XPath.SELECT, null);
+        
+        if (arg0XsObject instanceof ResultSequence) {
+           XPathContext xpathContextNew = new XPathContext(false);
+           Map<QName, XObject> inlineFunctionVarMap = xpathContextNew.getInlineFunctionVarMap();
+        
+           ResultSequence inpResultSeq = (ResultSequence)arg0XsObject;
+           for (int idx = 0; idx < inpResultSeq.size(); idx++) {
+               XObject inpSeqItem = inpResultSeq.item(idx);
+               if (varQname != null) {
+                  inlineFunctionVarMap.put(varQname, inpSeqItem);
+               }
+        
+               XObject resultObj = xpathInlineFn.execute(xpathContextNew, DTM.NULL, null);
+               if (resultObj instanceof XBoolean) {
+                   if (((XBoolean)resultObj).bool()) {
+                      resultSeq.add(inpSeqItem);
+                   }
+               }
+               else {
+                   throw new javax.xml.transform.TransformerException("XPTY0004 : The item type of the result of calling "
+                                                                                              + "function filter() is not xs:boolean.", xctxt.getSAXLocator()); 
+               }
+           }
+        
+           inlineFunctionVarMap.clear();
+        }
+        else if (arg0DtmIterator != null) {                  
+           Map<QName, XObject> inlineFunctionVarMap = xctxt.getInlineFunctionVarMap();
+        
+           int dtmNodeHandle;
+           
+           while (DTM.NULL != (dtmNodeHandle = arg0DtmIterator.nextNode())) {
+               DTM dtm = xctxt.getDTM(dtmNodeHandle);
+               Node node = dtm.getNode(dtmNodeHandle);
+               XObject inpSeqItem = XObjectFactory.create(node, xctxt);               
+               if (varQname != null) {
+                  inlineFunctionVarMap.put(varQname, inpSeqItem);
+               }
+        
+               xctxt.pushCurrentNode(dtmNodeHandle);
+               
+               XObject resultObj = xpathInlineFn.execute(xctxt, dtmNodeHandle, null);
+               if (resultObj instanceof XBoolean) {
+                   if (((XBoolean)resultObj).bool()) {                       
+                       resultSeq.add(new XNodeSet(dtmNodeHandle, xctxt));
+                   }
+               }
+               else {
+                   throw new javax.xml.transform.TransformerException("XPTY0004 : The item type of the result of calling "
+                                                                                              + "function filter() is not xs:boolean.", xctxt.getSAXLocator());  
+               }
+           }
+        
+           inlineFunctionVarMap.clear();
+        }
+        
+        return resultSeq;
+   }
+
+}
diff --git a/src/org/apache/xpath/functions/FuncForEach.java b/src/org/apache/xpath/functions/FuncForEach.java
new file mode 100644
index 00000000..113b1335
--- /dev/null
+++ b/src/org/apache/xpath/functions/FuncForEach.java
@@ -0,0 +1,212 @@
+/*
+ * 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.functions;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+
+import org.apache.xalan.res.XSLMessages;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMIterator;
+import org.apache.xml.utils.QName;
+import org.apache.xpath.Expression;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.axes.LocPathIterator;
+import org.apache.xpath.objects.InlineFunction;
+import org.apache.xpath.objects.ResultSequence;
+import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XObjectFactory;
+import org.apache.xpath.operations.Variable;
+import org.apache.xpath.res.XPATHErrorResources;
+import org.w3c.dom.Node;
+
+/**
+ * Execute the for-each() function.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+/*
+ * fn:for-each is one of XPath 3.1's higher-order function
+ * (ref, https://www.w3.org/TR/xpath-functions-31/#higher-order-functions).
+ * 
+ * The XPath function fn:for-each has following signature, and definition,
+ * 
+ * fn:for-each($seq as item()*, $action as function(item()) as item()*) as item()*
+ * 
+ * The function fn:for-each applies the function item $action to every item from 
+ * the sequence $seq in turn, returning the concatenation of the resulting sequences
+ * in order.
+ */
+public class FuncForEach extends Function2Args {
+
+   private static final long serialVersionUID = 2912594883291006421L;
+   
+   private static final String FUNCTION_NAME = "for-each()"; 
+
+  /**
+   * Execute the function. The function must return a valid object.
+   * 
+   * @param xctxt The current execution context.
+   * 
+   * @return A valid XObject.
+   *
+   * @throws javax.xml.transform.TransformerException
+   */
+  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
+  {                      
+      
+        XObject funcEvaluationResult = null;
+        
+        final int contextNode = xctxt.getCurrentNode();
+        
+        Expression arg0 = getArg0();
+        Expression arg1 = getArg1();                
+        
+        DTMIterator arg0DtmIterator = null;
+        
+        XObject arg0XsObject = null;
+                  
+        if (arg0 instanceof LocPathIterator) {
+            arg0DtmIterator = arg0.asIterator(xctxt, contextNode);               
+        }
+        else {
+            arg0XsObject = arg0.execute(xctxt, contextNode);
+        }
+        
+        ResultSequence resultSeq = new ResultSequence();
+                    
+        if (arg1 instanceof InlineFunction) {            
+            resultSeq = evaluateFnForEach(xctxt, arg0XsObject, arg0DtmIterator, (InlineFunction)arg1); 
+        }
+        else if (arg1 instanceof Variable) {
+            XObject arg1VarValue = arg1.execute(xctxt);
+            if (arg1VarValue instanceof InlineFunction) {
+                resultSeq = evaluateFnForEach(xctxt, arg0XsObject, arg0DtmIterator, (InlineFunction)arg1VarValue);   
+            }
+            else {
+                throw new javax.xml.transform.TransformerException("FORG0006 : The second argument to function call for-each(), "
+                                                                                               + "is not a function item.", xctxt.getSAXLocator());    
+            }
+        }
+        else {
+            throw new javax.xml.transform.TransformerException("FORG0006 : The second argument to function call for-each(), "
+                                                                                           + "is not a function item.", xctxt.getSAXLocator());               
+        }            
+        
+        funcEvaluationResult = resultSeq;
+        
+        return funcEvaluationResult;
+  }
+
+  /**
+   * Check that the number of arguments passed to this function is correct.
+   *
+   * @param argNum The number of arguments that is being passed to the function.
+   *
+   * @throws WrongNumberArgsException
+   */
+  public void checkNumberArgs(int argNum) throws WrongNumberArgsException
+  {
+     if (argNum != 2) {
+        reportWrongNumberArgs();
+     }
+  }
+
+  /**
+   * Constructs and throws a WrongNumberArgException with the appropriate
+   * message for this function object.
+   *
+   * @throws WrongNumberArgsException
+   */
+  protected void reportWrongNumberArgs() throws WrongNumberArgsException {
+      throw new WrongNumberArgsException(XSLMessages.createXPATHMessage(
+                                              XPATHErrorResources.ER_TWO, null)); //"2"
+  }
+  
+  /*
+   * Evaluate the function call fn:for-each.
+   */
+  private ResultSequence evaluateFnForEach(XPathContext xctxt, XObject arg0XsObject, 
+                                               DTMIterator arg0DtmIterator, InlineFunction arg1) 
+                                                                                    throws TransformerException {
+
+        ResultSequence resultSeq = new ResultSequence(); 
+        
+        List<String> funcParamNameList = arg1.getFuncParamNameList();
+        String funcBodyXPathExprStr = arg1.getFuncBodyXPathExprStr();
+        
+        if (funcBodyXPathExprStr == null || "".equals(funcBodyXPathExprStr)) {
+           return resultSeq;
+        }
+        
+        QName varQname = null;
+        
+        if (funcParamNameList.size() == 1) {
+           varQname = new QName(funcParamNameList.get(0));
+        }
+        
+        SourceLocator srcLocator = xctxt.getSAXLocator();
+        
+        XPath xpathInlineFn = new XPath(funcBodyXPathExprStr, srcLocator, null, XPath.SELECT, null);
+        
+        if (arg0XsObject instanceof ResultSequence) {
+           XPathContext xpathContextNew = new XPathContext(false);
+           Map<QName, XObject> inlineFunctionVarMap = xpathContextNew.getInlineFunctionVarMap();
+        
+           ResultSequence inpResultSeq = (ResultSequence)arg0XsObject;
+           for (int idx = 0; idx < inpResultSeq.size(); idx++) {
+               XObject inpSeqItem = inpResultSeq.item(idx);
+               if (varQname != null) {
+                  inlineFunctionVarMap.put(varQname, inpSeqItem);
+               }
+        
+               XObject resultObj = xpathInlineFn.execute(xpathContextNew, DTM.NULL, null);
+               resultSeq.add(resultObj);
+           }
+        
+           inlineFunctionVarMap.clear();
+        }
+        else if (arg0DtmIterator != null) {                  
+           Map<QName, XObject> inlineFunctionVarMap = xctxt.getInlineFunctionVarMap();
+        
+           int dtmNodeHandle;
+           while (DTM.NULL != (dtmNodeHandle = arg0DtmIterator.nextNode())) {
+               DTM dtm = xctxt.getDTM(dtmNodeHandle);
+               Node node = dtm.getNode(dtmNodeHandle);
+               XObject xObject = XObjectFactory.create(node, xctxt);
+               if (varQname != null) {
+                  inlineFunctionVarMap.put(varQname, xObject);
+               }
+        
+               XObject resultObj = xpathInlineFn.execute(xctxt, dtmNodeHandle, null);
+               resultSeq.add(resultObj);
+           }
+        
+           inlineFunctionVarMap.clear();
+        }
+        
+        return resultSeq;
+   }
+
+}
diff --git a/src/org/apache/xpath/objects/InlineFunction.java b/src/org/apache/xpath/objects/InlineFunction.java
new file mode 100644
index 00000000..f9cf1c2b
--- /dev/null
+++ b/src/org/apache/xpath/objects/InlineFunction.java
@@ -0,0 +1,77 @@
+/*
+ * 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.objects;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.xpath.ExpressionOwner;
+import org.apache.xpath.XPathVisitor;
+
+/*
+ * The XalanJ xpath parser, creates and populates this object,
+ * as a representation of XPath 3.1 function item "inline function" 
+ * definition within XPath expressions.
+ * 
+ * The XPath 3.1 spec, defines function item "inline function" XPath 
+ * expressions with following grammar,
+
+   InlineFunctionExpr        ::=  "function" "(" ParamList? ")" ("as" SequenceType)? FunctionBody
+
+   ParamList                 ::=   Param ("," Param)*
+
+   Param                     ::=   "$" EQName TypeDeclaration?
+
+   FunctionBody              ::=   EnclosedExpr
+
+   EnclosedExpr              ::=   "{" Expr? "}"
+   
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ *   
+ * @xsl.usage advanced  
+ */
+public class InlineFunction extends XObject {
+
+    private static final long serialVersionUID = 9219253671212483045L;
+    
+    private List<String> funcParamNameList = new ArrayList<String>();
+    
+    private String funcBodyXPathExprStr = null;
+
+    public List<String> getFuncParamNameList() {
+        return funcParamNameList;
+    }
+
+    public void setFuncParamNameList(List<String> funcParamNameList) {
+        this.funcParamNameList = funcParamNameList;
+    }
+
+    public String getFuncBodyXPathExprStr() {
+        return funcBodyXPathExprStr;
+    }
+
+    public void setFuncBodyXPathExprStr(String funcBodyXPathExprStr) {
+        this.funcBodyXPathExprStr = funcBodyXPathExprStr;
+    }
+    
+    public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
+    {
+        // no op
+    }
+    
+}
diff --git a/src/org/apache/xpath/objects/ResultSequence.java b/src/org/apache/xpath/objects/ResultSequence.java
index ab4a8c4f..22f22ca5 100644
--- a/src/org/apache/xpath/objects/ResultSequence.java
+++ b/src/org/apache/xpath/objects/ResultSequence.java
@@ -23,7 +23,7 @@ import java.util.List;
 import org.apache.xpath.xs.types.XSAnyType;
 
 /**
- * This class represents, the XPath 3.1 data model sequences.
+ * This class represents, the XPath 3.1 data model sequence.
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
@@ -33,7 +33,7 @@ public class ResultSequence extends XObject
 {
     static final long serialVersionUID = -5736721866747906182L;
     
-    // the underlying list object, storing items of this result sequence 
+    // the underlying list object, to store items of this result sequence 
     private List<XObject> rsList = new ArrayList<XObject>();
     
     /*
@@ -41,6 +41,11 @@ public class ResultSequence extends XObject
      */
     public ResultSequence() {}
     
+    public int getType()
+    {
+        return CLASS_RESULT_SEQUENCE;
+    }
+    
     public void add(XObject item) {
         rsList.add(item);    
     }
diff --git a/src/org/apache/xpath/objects/XObject.java b/src/org/apache/xpath/objects/XObject.java
index d7f38c8b..de688eeb 100644
--- a/src/org/apache/xpath/objects/XObject.java
+++ b/src/org/apache/xpath/objects/XObject.java
@@ -210,6 +210,9 @@ public class XObject extends Expression implements Serializable, Cloneable
 
   /** Constant for RESULT TREE FRAGMENT object type */
   public static final int CLASS_RTREEFRAG = 5;
+  
+  /** Constant for XPath 3.1 sequence object type */
+  public static final int CLASS_RESULT_SEQUENCE = 6;
 
   /** Represents an unresolved variable type as an integer. */
   public static final int CLASS_UNRESOLVEDVARIABLE = 600;
diff --git a/src/org/apache/xpath/operations/Mult.java b/src/org/apache/xpath/operations/Mult.java
index dd14f85e..39ae15f2 100644
--- a/src/org/apache/xpath/operations/Mult.java
+++ b/src/org/apache/xpath/operations/Mult.java
@@ -23,6 +23,7 @@ package org.apache.xpath.operations;
 import org.apache.xpath.XPathContext;
 import org.apache.xpath.objects.XNumber;
 import org.apache.xpath.objects.XObject;
+import org.apache.xpath.xs.types.XSInteger;
 
 /**
  * The '*' operation expression executer.
@@ -45,7 +46,26 @@ public class Mult extends Operation
   public XObject operate(XObject left, XObject right)
           throws javax.xml.transform.TransformerException
   {
-    return new XNumber(left.num() * right.num());
+      XObject result = null;
+      
+      if ((left instanceof XSInteger) && (right instanceof XSInteger)) {
+          result = ((XSInteger)left).multiply((XSInteger)right);       
+      }
+      else if ((left instanceof XSInteger) && (right instanceof XNumber)) {
+          double lDouble = (((XSInteger)left).intValue()).doubleValue();
+          double rDouble = ((XNumber)right).num();
+          result = new XNumber(lDouble * rDouble);          
+      }
+      else if ((left instanceof XNumber) && (right instanceof XSInteger)) {          
+          double lDouble = ((XNumber)left).num();
+          double rDouble = (((XSInteger)right).intValue()).doubleValue();
+          result = new XNumber(lDouble * rDouble);          
+      }
+      else {
+          result = new XNumber(left.num() * right.num());
+      }
+      
+      return result;
   }
   
   /**
diff --git a/src/org/apache/xpath/operations/Variable.java b/src/org/apache/xpath/operations/Variable.java
index 39e8bf7f..1f247949 100644
--- a/src/org/apache/xpath/operations/Variable.java
+++ b/src/org/apache/xpath/operations/Variable.java
@@ -20,6 +20,8 @@
  */
 package org.apache.xpath.operations;
 
+import java.util.Map;
+
 import javax.xml.transform.TransformerException;
 
 import org.apache.xalan.res.XSLMessages;
@@ -206,6 +208,17 @@ public class Variable extends Expression implements PathComponent
     org.apache.xml.utils.PrefixResolver xprefixResolver = xctxt.getNamespaceContext();
 
     XObject result;
+    
+    Map<QName, XObject> inlineFunctionVarMap = xctxt.getInlineFunctionVarMap();
+    XObject inlineFuncVarValue = inlineFunctionVarMap.get(m_qname);
+    
+    if (inlineFuncVarValue != null) {
+        // dereferencing, XPath 3.1 function item "inline function" 
+        // parameter references within "inline function" body. 
+        result = inlineFuncVarValue;
+        return result;
+    }
+    
     // Is the variable fetched always the same?
     // XObject result = xctxt.getVariable(m_qname);
     if(m_fixUpWasCalled)
diff --git a/src/org/apache/xpath/res/XPATHErrorResources.java b/src/org/apache/xpath/res/XPATHErrorResources.java
index eeed93a3..c28a9094 100644
--- a/src/org/apache/xpath/res/XPATHErrorResources.java
+++ b/src/org/apache/xpath/res/XPATHErrorResources.java
@@ -147,8 +147,14 @@ public class XPATHErrorResources extends ListResourceBundle
 	 "ER_BOOLEAN_ARG_NO_LONGER_OPTIONAL";
   public static final String ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG = 
 	 "ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG";
+  public static final String ER_FOUND_COMMA_BUT_NO_PRECEDING_PARAM = 
+     "ER_FOUND_COMMA_BUT_NO_PRECEDING_PARAM";
   public static final String ER_FOUND_COMMA_BUT_NO_FOLLOWING_ARG = 
 	 "ER_FOUND_COMMA_BUT_NO_FOLLOWING_ARG";
+  public static final String ER_FOUND_COMMA_BUT_NO_FOLLOWING_PARAM = 
+     "ER_FOUND_COMMA_BUT_NO_FOLLOWING_PARAM";
+  public static final String ER_INLINE_FUNCTION_PARAM_CARDINALITY = 
+     "ER_INLINE_FUNCTION_PARAM_CARDINALITY";
   public static final String ER_PREDICATE_ILLEGAL_SYNTAX = 
 	 "ER_PREDICATE_ILLEGAL_SYNTAX";
   public static final String ER_ILLEGAL_AXIS_NAME = "ER_ILLEGAL_AXIS_NAME";
@@ -230,9 +236,11 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
   /** 0 */
   public static final String ER_ZERO = "ER_ZERO";
   /**  0 or 1   */
-  public static final String ER_ZERO_OR_ONE = "ER_ZERO_OR_ONE";
+  public static final String ER_ZERO_OR_ONE = "ER_ZERO_OR_ONE";  
   /** 1 or 2 */
   public static final String ER_ONE_OR_TWO = "ER_ONE_OR_TWO";
+  /** 2 */
+  public static final String ER_TWO = "ER_TWO";
    /**  2 or 3   */
   public static final String ER_TWO_OR_THREE = "ER_TWO_OR_THREE";
   /**  1, 2 or 3   */
@@ -488,9 +496,18 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
 
   { ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG,
       "Found ',' but no preceding argument!"},
+  
+  { ER_FOUND_COMMA_BUT_NO_PRECEDING_PARAM,
+      "Found ',' but no preceding function parameter definition."},
 
   { ER_FOUND_COMMA_BUT_NO_FOLLOWING_ARG,
       "Found ',' but no following argument!"},
+  
+  { ER_FOUND_COMMA_BUT_NO_FOLLOWING_PARAM,
+      "Found ',' but no following function parameter definition."},
+  
+  { ER_INLINE_FUNCTION_PARAM_CARDINALITY,
+      "XPTY0004 : The inline function definition has {0} parameters. Expected 0 or 1."},
 
   { ER_PREDICATE_ILLEGAL_SYNTAX,
       "'..[predicate]' or '.[predicate]' is illegal syntax.  Use 'self::node()[predicate]' instead."},
@@ -645,6 +662,8 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
   { ER_ONE_OR_TWO,
        "1 or 2"},
   
+  { ER_TWO, "2"},
+  
   { ER_TWO_OR_THREE,
        "2 or 3"},
   
diff --git a/src/org/apache/xpath/xs/types/XSInteger.java b/src/org/apache/xpath/xs/types/XSInteger.java
index 8232b066..48b8b420 100644
--- a/src/org/apache/xpath/xs/types/XSInteger.java
+++ b/src/org/apache/xpath/xs/types/XSInteger.java
@@ -140,6 +140,10 @@ public class XSInteger extends XSDecimal {
 	    return (intValue()).compareTo(xsInteger.intValue()) > 0; 
     }
 	
+	public XSInteger multiply(XSInteger xsInteger) {
+	    return new XSInteger((intValue()).multiply(xsInteger.intValue()));   
+	}
+	
 	/*
      * Cast an object of type XSAnyType, to an object of type 
      * java.math.BigInteger.  
diff --git a/tests/fn_filter/gold/test1.out b/tests/fn_filter/gold/test1.out
new file mode 100644
index 00000000..3c56ffb9
--- /dev/null
+++ b/tests/fn_filter/gold/test1.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <one>1 2 3 4 5 6 7 8 9 10</one>
+  <two/>
+</result>
diff --git a/tests/fn_filter/gold/test2.out b/tests/fn_filter/gold/test2.out
new file mode 100644
index 00000000..934a2f81
--- /dev/null
+++ b/tests/fn_filter/gold/test2.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>7 8 9 10 11</result>
diff --git a/tests/fn_filter/gold/test3.out b/tests/fn_filter/gold/test3.out
new file mode 100644
index 00000000..2f966729
--- /dev/null
+++ b/tests/fn_filter/gold/test3.out
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <item weight="8">D</item>
+  <item weight="9">E</item>
+  <item weight="10">F</item>
+  <item weight="11">G</item>
+  <item weight="12">H</item>
+  <item weight="13">I</item>
+  <item weight="14">J</item>
+</result>
diff --git a/tests/fn_filter/test1.xsl b/tests/fn_filter/test1.xsl
new file mode 100644
index 00000000..b9c10630
--- /dev/null
+++ b/tests/fn_filter/test1.xsl
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- Test for the XPath 3.1 fn:filter() function -->                 
+
+   <xsl:output method="xml" indent="yes"/>   
+
+   <xsl:template match="/">
+      <result>
+         <one><xsl:value-of select="filter(1 to 10, function($a) { true() })"/></one>
+         <two><xsl:value-of select="filter(1 to 10, function($a) { false() })"/></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/fn_filter/test1_a.xml b/tests/fn_filter/test1_a.xml
new file mode 100644
index 00000000..e5a0110a
--- /dev/null
+++ b/tests/fn_filter/test1_a.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<elem>
+  <a>5</a>
+  <a>6</a>
+  <a>7</a>
+  <a>8</a>
+  <a>9</a>
+  <a>10</a>
+  <a>11</a>
+</elem>
\ No newline at end of file
diff --git a/tests/fn_filter/test1_b.xml b/tests/fn_filter/test1_b.xml
new file mode 100644
index 00000000..c4fc37e9
--- /dev/null
+++ b/tests/fn_filter/test1_b.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<elem>
+   <item weight="5">A</item>
+   <item weight="6">B</item>
+   <item weight="7">C</item>
+   <item weight="8">D</item>
+   <item weight="9">E</item>
+   <item weight="10">F</item>
+   <item weight="11">G</item>
+   <item weight="12">H</item>
+   <item weight="13">I</item>
+   <item weight="14">J</item>
+</elem>
\ No newline at end of file
diff --git a/tests/fn_filter/test2.xsl b/tests/fn_filter/test2.xsl
new file mode 100644
index 00000000..b87084b5
--- /dev/null
+++ b/tests/fn_filter/test2.xsl
@@ -0,0 +1,37 @@
+<?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 -->
+   
+   <!-- Test for the XPath 3.1 fn:filter() function -->
+   
+   <xsl:output method="xml" indent="yes"/>   
+
+   <xsl:template match="/elem">
+      <result>
+        <xsl:value-of select="filter(a, function($a) { $a &gt; 6 })"/>
+      </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/fn_filter/test3.xsl b/tests/fn_filter/test3.xsl
new file mode 100644
index 00000000..289d5bc7
--- /dev/null
+++ b/tests/fn_filter/test3.xsl
@@ -0,0 +1,38 @@
+<?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 -->
+   
+   <!-- Test for the XPath 3.1 fn:filter() function -->                
+
+   <xsl:output method="xml" indent="yes"/>   
+
+   <xsl:template match="/elem">
+      <result>
+        <xsl:variable name="filteredElems" select="filter(item, function($x) { $x/@weight &gt; 7 })"/>
+        <xsl:copy-of select="$filteredElems"/>
+      </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/fn_foreach/gold/test1.out b/tests/fn_foreach/gold/test1.out
new file mode 100644
index 00000000..8e0ac138
--- /dev/null
+++ b/tests/fn_foreach/gold/test1.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>1 4 9 16 25</result>
diff --git a/tests/fn_foreach/gold/test2.out b/tests/fn_foreach/gold/test2.out
new file mode 100644
index 00000000..15879861
--- /dev/null
+++ b/tests/fn_foreach/gold/test2.out
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <num>8</num>
+  <num>9</num>
+  <num>10</num>
+  <num>11</num>
+  <num>12</num>
+  <num>13</num>
+  <num>14</num>
+</result>
diff --git a/tests/fn_foreach/gold/test3.out b/tests/fn_foreach/gold/test3.out
new file mode 100644
index 00000000..e1735cfa
--- /dev/null
+++ b/tests/fn_foreach/gold/test3.out
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <trfItems>
+    <item>A_5</item>
+    <item>B_6</item>
+    <item>C_7</item>
+    <item>D_8</item>
+    <item>E_9</item>
+    <item>F_10</item>
+    <item>G_11</item>
+    <item>H_12</item>
+    <item>I_13</item>
+    <item>J_14</item>
+  </trfItems>
+</result>
diff --git a/tests/fn_foreach/gold/test4.out b/tests/fn_foreach/gold/test4.out
new file mode 100644
index 00000000..15879861
--- /dev/null
+++ b/tests/fn_foreach/gold/test4.out
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <num>8</num>
+  <num>9</num>
+  <num>10</num>
+  <num>11</num>
+  <num>12</num>
+  <num>13</num>
+  <num>14</num>
+</result>
diff --git a/tests/fn_foreach/gold/test5.out b/tests/fn_foreach/gold/test5.out
new file mode 100644
index 00000000..dbce52d5
--- /dev/null
+++ b/tests/fn_foreach/gold/test5.out
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <result1>
+    <num>8</num>
+    <num>9</num>
+    <num>10</num>
+    <num>11</num>
+    <num>12</num>
+    <num>13</num>
+    <num>14</num>
+  </result1>
+  <result2>
+    <num>8</num>
+    <num>9</num>
+    <num>10</num>
+    <num>11</num>
+    <num>12</num>
+    <num>13</num>
+    <num>14</num>
+  </result2>
+</result>
diff --git a/tests/fn_foreach/gold/test6.out b/tests/fn_foreach/gold/test6.out
new file mode 100644
index 00000000..4ebb723c
--- /dev/null
+++ b/tests/fn_foreach/gold/test6.out
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <num>1</num>
+  <num>4</num>
+  <num>9</num>
+  <num>16</num>
+  <num>25</num>
+</result>
diff --git a/tests/fn_foreach/gold/test7.out b/tests/fn_foreach/gold/test7.out
new file mode 100644
index 00000000..c14bdf18
--- /dev/null
+++ b/tests/fn_foreach/gold/test7.out
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <num>2</num>
+  <num>4</num>
+  <num>6</num>
+  <num>8</num>
+  <num>10</num>
+</result>
diff --git a/tests/fn_foreach/gold/test8.out b/tests/fn_foreach/gold/test8.out
new file mode 100644
index 00000000..2b3f3b27
--- /dev/null
+++ b/tests/fn_foreach/gold/test8.out
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <num>3</num>
+  <num>6</num>
+  <num>9</num>
+  <num>12</num>
+  <num>15</num>
+</result>
diff --git a/tests/fn_foreach/test1.xsl b/tests/fn_foreach/test1.xsl
new file mode 100644
index 00000000..8186af09
--- /dev/null
+++ b/tests/fn_foreach/test1.xsl
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- Test for the XPath 3.1 fn:for-each() function -->                
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/">
+      <result>        
+         <xsl:value-of select="for-each(1 to 5, function($a) { $a * $a })"/>
+      </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/fn_foreach/test1_a.xml b/tests/fn_foreach/test1_a.xml
new file mode 100644
index 00000000..e5a0110a
--- /dev/null
+++ b/tests/fn_foreach/test1_a.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<elem>
+  <a>5</a>
+  <a>6</a>
+  <a>7</a>
+  <a>8</a>
+  <a>9</a>
+  <a>10</a>
+  <a>11</a>
+</elem>
\ No newline at end of file
diff --git a/tests/fn_foreach/test1_b.xml b/tests/fn_foreach/test1_b.xml
new file mode 100644
index 00000000..c4fc37e9
--- /dev/null
+++ b/tests/fn_foreach/test1_b.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<elem>
+   <item weight="5">A</item>
+   <item weight="6">B</item>
+   <item weight="7">C</item>
+   <item weight="8">D</item>
+   <item weight="9">E</item>
+   <item weight="10">F</item>
+   <item weight="11">G</item>
+   <item weight="12">H</item>
+   <item weight="13">I</item>
+   <item weight="14">J</item>
+</elem>
\ No newline at end of file
diff --git a/tests/fn_foreach/test2.xsl b/tests/fn_foreach/test2.xsl
new file mode 100644
index 00000000..57f2fae7
--- /dev/null
+++ b/tests/fn_foreach/test2.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_a.xml -->
+   
+   <!-- Test for the XPath 3.1 fn:for-each() function -->              
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/elem">
+      <result>        
+        <xsl:for-each select="for-each(a, function($x) { $x + 3 })">
+          <num><xsl:value-of select="."/></num>
+        </xsl:for-each>
+      </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/fn_foreach/test3.xsl b/tests/fn_foreach/test3.xsl
new file mode 100644
index 00000000..4354104b
--- /dev/null
+++ b/tests/fn_foreach/test3.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 -->
+   
+   <!-- use with test1_b.xml -->
+   
+   <!-- Test for the XPath 3.1 fn:for-each() function -->
+   
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/elem">
+      <result>
+        <trfItems>
+	       <xsl:for-each select="for-each(item, function($a) { concat(string($a), '_', $a/@weight) })">
+	          <item><xsl:value-of select="."/></item>
+	       </xsl:for-each>
+        </trfItems>
+      </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/fn_foreach/test4.xsl b/tests/fn_foreach/test4.xsl
new file mode 100644
index 00000000..e60afe77
--- /dev/null
+++ b/tests/fn_foreach/test4.xsl
@@ -0,0 +1,45 @@
+<?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 -->
+   
+   <!-- Test for the XPath 3.1 fn:for-each() function.
+        Within this stylesheet, we use a function item variable
+        reference as an argument to the fn:for-each() function 
+        call. 
+   -->                
+
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:variable name="func1" select="function($x) { $x + 3 }"/>
+
+   <xsl:template match="/elem">
+      <result>        
+        <xsl:for-each select="for-each(a, $func1)">
+          <num><xsl:value-of select="."/></num>
+        </xsl:for-each>
+      </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/fn_foreach/test5.xsl b/tests/fn_foreach/test5.xsl
new file mode 100644
index 00000000..db56a071
--- /dev/null
+++ b/tests/fn_foreach/test5.xsl
@@ -0,0 +1,53 @@
+<?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 -->
+   
+   <!-- Test for the XPath 3.1 fn:for-each() function.
+        Within this stylesheet, we use a function item variable
+        reference as an argument to the fn:for-each() function 
+        call. We use the, same function item variable reference,
+        on more than one fn:for-each() function call.   
+   -->
+   
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:variable name="func1" select="function($x) { $x + 3 }"/>
+
+   <xsl:template match="/elem">
+      <result>
+        <result1>        
+           <xsl:for-each select="for-each(a, $func1)">
+              <num><xsl:value-of select="."/></num>
+           </xsl:for-each>
+        </result1>
+        <result2>        
+	       <xsl:for-each select="for-each(a, $func1)">
+	          <num><xsl:value-of select="."/></num>
+	       </xsl:for-each>
+        </result2>
+      </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/fn_foreach/test6.xsl b/tests/fn_foreach/test6.xsl
new file mode 100644
index 00000000..dd14494d
--- /dev/null
+++ b/tests/fn_foreach/test6.xsl
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- Test for the XPath 3.1 fn:for-each() function -->
+   
+   <!-- This XSLT stylesheet tests, passing an XPath function
+        item as a template parameter argument. -->                
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/">
+      <result>
+        <xsl:call-template name="Template1">
+           <xsl:with-param name="funcDefn" select="function($x) { $x * $x }"/>
+           <xsl:with-param name="idx1" select="1"/>
+           <xsl:with-param name="idx2" select="5"/>
+        </xsl:call-template>
+      </result>
+   </xsl:template>
+   
+   <xsl:template name="Template1">
+      <xsl:param name="funcDefn"/>
+      <xsl:param name="idx1"/>
+      <xsl:param name="idx2"/>
+   
+      <xsl:for-each select="for-each($idx1 to $idx2, $funcDefn)">
+         <num><xsl:value-of select="."/></num>
+      </xsl:for-each>
+   </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/fn_foreach/test7.xsl b/tests/fn_foreach/test7.xsl
new file mode 100644
index 00000000..60eeccb6
--- /dev/null
+++ b/tests/fn_foreach/test7.xsl
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- Test for the XPath 3.1 fn:for-each() function -->
+   
+   <!-- This XSLT stylesheet tests, passing an XPath function
+        item as a template parameter argument. -->                  
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/">
+      <result>
+        <xsl:call-template name="Template1">
+           <xsl:with-param name="funcDefn" select="function($x) { $x * 2 }"/>
+           <xsl:with-param name="idx1" select="1"/>
+           <xsl:with-param name="idx2" select="5"/>
+        </xsl:call-template>
+      </result>
+   </xsl:template>
+   
+   <xsl:template name="Template1">
+      <xsl:param name="funcDefn"/>
+      <xsl:param name="idx1"/>
+      <xsl:param name="idx2"/>
+   
+      <xsl:for-each select="for-each($idx1 to $idx2, $funcDefn)">
+         <num><xsl:value-of select="."/></num>
+      </xsl:for-each>
+   </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/fn_foreach/test8.xsl b/tests/fn_foreach/test8.xsl
new file mode 100644
index 00000000..de555b47
--- /dev/null
+++ b/tests/fn_foreach/test8.xsl
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- Test for the XPath 3.1 fn:for-each() function -->
+   
+   <!-- This XSLT stylesheet tests, passing an XPath function
+        item as a template parameter argument. -->                  
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/">
+      <result>
+        <xsl:call-template name="Template1">
+           <xsl:with-param name="funcDefn" select="function($x) { 3 * $x }"/>
+           <xsl:with-param name="idx1" select="1"/>
+           <xsl:with-param name="idx2" select="5"/>
+        </xsl:call-template>
+      </result>
+   </xsl:template>
+   
+   <xsl:template name="Template1">
+      <xsl:param name="funcDefn"/>
+      <xsl:param name="idx1"/>
+      <xsl:param name="idx2"/>
+   
+      <xsl:for-each select="for-each($idx1 to $idx2, $funcDefn)">
+         <num><xsl:value-of select="."/></num>
+      </xsl:for-each>
+   </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/org/apache/xalan/xpath3/FnFilterTests.java b/tests/org/apache/xalan/xpath3/FnFilterTests.java
new file mode 100644
index 00000000..12546eb3
--- /dev/null
+++ b/tests/org/apache/xalan/xpath3/FnFilterTests.java
@@ -0,0 +1,80 @@
+/*
+ * 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 function fn:filter test cases.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FnFilterTests extends XslTransformTestsUtil {        
+    
+    private static final String XSL_TRANSFORM_INPUT_DIRPATH = XSLConstants.XSL_TRANSFORM_INPUT_DIRPATH_PREFIX + "fn_filter/";
+    
+    private static final String XSL_TRANSFORM_GOLD_DIRPATH = XSLConstants.XSL_TRANSFORM_GOLD_DIRPATH_PREFIX + "fn_filter/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 xslFnFilterTest1() {
+        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 xslFnFilterTest2() {
+        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 xslFnFilterTest3() {
+        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);
+    }
+
+}
diff --git a/tests/org/apache/xalan/xpath3/FnForEachTests.java b/tests/org/apache/xalan/xpath3/FnForEachTests.java
new file mode 100644
index 00000000..07bf68fb
--- /dev/null
+++ b/tests/org/apache/xalan/xpath3/FnForEachTests.java
@@ -0,0 +1,130 @@
+/*
+ * 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 function fn:for-each test cases.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FnForEachTests extends XslTransformTestsUtil {        
+    
+    private static final String XSL_TRANSFORM_INPUT_DIRPATH = XSLConstants.XSL_TRANSFORM_INPUT_DIRPATH_PREFIX + "fn_foreach/";
+    
+    private static final String XSL_TRANSFORM_GOLD_DIRPATH = XSLConstants.XSL_TRANSFORM_GOLD_DIRPATH_PREFIX + "fn_foreach/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 xslFnForEachTest1() {
+        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 xslFnForEachTest2() {
+        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 xslFnForEachTest3() {
+        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 xslFnForEachTest4() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_a.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 xslFnForEachTest5() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_a.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test5.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test5.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslFnForEachTest6() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test6.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test6.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test6.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslFnForEachTest7() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test7.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test7.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test7.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslFnForEachTest8() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test8.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test8.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test8.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 cf777bba..26604646 100644
--- a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
+++ b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
@@ -17,6 +17,8 @@
 package org.apache.xalan.xslt3;
 
 import org.apache.xalan.xpath3.FnAbsTests;
+import org.apache.xalan.xpath3.FnFilterTests;
+import org.apache.xalan.xpath3.FnForEachTests;
 import org.apache.xalan.xpath3.FnIndexOfTests;
 import org.apache.xalan.xpath3.FnStringJoinTests;
 import org.apache.xalan.xpath3.FnTokenizeTests;
@@ -49,7 +51,7 @@ import org.junit.runners.Suite.SuiteClasses;
                 FnAbsTests.class, StringTests.class, XsConstructorFunctions.class, 
                 FnIndexOfTests.class, SequenceTests.class, RangeExprTests.class, 
                 W3c_xslt30_IterateTests.class, W3c_xslt30_AxesTests.class, XslIterateTests.class,
-                ValueComparisonTests.class })
+                ValueComparisonTests.class, FnForEachTests.class, FnFilterTests.class })
 public class AllXsl3Tests {
 
 }


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