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 2024/05/29 13:34:42 UTC

(xalan-java) branch xalan-j_xslt3.0 updated: implementation of xpath3.1 array:remove function, bug fix for jira issue XALANJ-2738, addition and improvements to test cases and various other code improvements

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 c7fdf07c implementation of xpath3.1 array:remove function, bug fix for jira issue XALANJ-2738, addition and improvements to test cases and various other code improvements
c7fdf07c is described below

commit c7fdf07c1240eca86d5481950379c1246edbfaa6
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Wed May 29 19:04:28 2024 +0530

    implementation of xpath3.1 array:remove function, bug fix for jira issue XALANJ-2738, addition and improvements to test cases and various other code improvements
---
 src/org/apache/xalan/templates/ElemValueOf.java    |   7 -
 src/org/apache/xpath/compiler/FunctionTable.java   |  32 +--
 src/org/apache/xpath/compiler/XPathParserImpl.java |  91 +++++---
 src/org/apache/xpath/composite/MapConstructor.java | 106 ++++++---
 .../xpath/functions/DynamicFunctionCall.java       |   6 +
 src/org/apache/xpath/functions/FuncParseJson.java  |  14 +-
 .../xpath/functions/array/FuncArrayAppend.java     |   2 +-
 .../apache/xpath/functions/array/FuncArrayGet.java |   6 +-
 .../apache/xpath/functions/array/FuncArrayPut.java |   2 +-
 .../xpath/functions/array/FuncArrayRemove.java     | 236 +++++++++++++++++++++
 .../xpath/functions/array/FuncArraySize.java       |   2 +-
 .../apache/xpath/functions/array/FuncSubarray.java |   2 +-
 .../xpath/functions/map/FuncMapContains.java       |   5 +
 .../apache/xpath/functions/map/FuncMapEntry.java   |  11 +
 src/org/apache/xpath/functions/map/FuncMapGet.java |  27 +--
 src/org/apache/xpath/functions/map/FuncMapPut.java |  21 +-
 tests/fn_parse_json/gold/xalanj_2738.out           |   3 +
 .../parse-json-test1.xsl}                          |  49 ++---
 tests/fn_parse_json/xml-sample-with-json-data1.xml |   3 +
 .../org/apache/xalan/xpath3/FnParseJsonTests.java  |  10 +
 tests/org/apache/xalan/xpath3/XPathArrayTests.java |  10 +
 tests/xpath_array/gold/test8.out                   |   7 +
 tests/xpath_array/test8.xsl                        |  57 +++++
 tests/xpath_maps/gold/test12.out                   |  13 +-
 tests/xpath_maps/gold/test13.out                   |   5 +-
 tests/xpath_maps/gold/test14.out                   |   5 +-
 tests/xpath_maps/gold/test3.out                    |  17 +-
 tests/xpath_maps/gold/test9.out                    |  23 +-
 tests/xpath_maps/test12.xsl                        |  14 +-
 tests/xpath_maps/test13.xsl                        |   9 +-
 tests/xpath_maps/test14.xsl                        |  12 +-
 tests/xpath_maps/test3.xsl                         |  18 +-
 tests/xpath_maps/test9.xsl                         |  16 +-
 33 files changed, 570 insertions(+), 271 deletions(-)

diff --git a/src/org/apache/xalan/templates/ElemValueOf.java b/src/org/apache/xalan/templates/ElemValueOf.java
index 1797260a..44d18019 100644
--- a/src/org/apache/xalan/templates/ElemValueOf.java
+++ b/src/org/apache/xalan/templates/ElemValueOf.java
@@ -371,13 +371,6 @@ public class ElemValueOf extends ElemTemplateElement {
                   else if (expr instanceof Variable) {
                       XObject evalResult = ((Variable)expr).execute(xctxt);
                       String strValue = null;
-                      /*if (evalResult instanceof XSAnyType) {
-                          strValue = ((XSAnyType)evalResult).stringValue();
-                      }
-                      else {
-                          strValue = evalResult.str();
-                      }
-                      (new XString(strValue)).dispatchCharactersEvents(rth);*/
                       
                       if (evalResult instanceof XSAnyType) {
                           strValue = ((XSAnyType)evalResult).stringValue();    
diff --git a/src/org/apache/xpath/compiler/FunctionTable.java b/src/org/apache/xpath/compiler/FunctionTable.java
index 2ef6f68b..0433ea4e 100644
--- a/src/org/apache/xpath/compiler/FunctionTable.java
+++ b/src/org/apache/xpath/compiler/FunctionTable.java
@@ -27,7 +27,6 @@ import java.util.List;
 import javax.xml.transform.TransformerException;
 
 import org.apache.xpath.functions.Function;
-import org.apache.xpath.functions.array.FuncSubarray;
 
 /**
  * The function table for XPath 3.1.
@@ -801,6 +800,7 @@ public class FunctionTable
     m_functions[FUNC_ARRAY_PUT] = org.apache.xpath.functions.array.FuncArrayPut.class;
     m_functions[FUNC_ARRAY_APPEND] = org.apache.xpath.functions.array.FuncArrayAppend.class;
     m_functions[FUNC_ARRAY_SUBARRAY] = org.apache.xpath.functions.array.FuncSubarray.class;
+    m_functions[FUNC_ARRAY_REMOVE] = org.apache.xpath.functions.array.FuncArrayRemove.class;
     
     // XPath 3.1 built-in functions configurations for the map 
     // functions namespace http://www.w3.org/2005/xpath-functions/map    
@@ -1070,20 +1070,7 @@ public class FunctionTable
          m_functionID.put(Keywords.FUNC_BASE_URI,
                          new Integer(FunctionTable.FUNC_BASE_URI));
          m_functionID.put(Keywords.FUNC_DOCUMENT_URI,
-                         new Integer(FunctionTable.FUNC_DOCUMENT_URI));         
-         
-         // XPath 3.1 functions configurations for the math functions 
-         // namespace http://www.w3.org/2005/xpath-functions/array
-         m_functionID.put(Keywords.FUNC_ARRAY_SIZE,
-                          new Integer(FunctionTable.FUNC_ARRAY_SIZE));
-         m_functionID.put(Keywords.FUNC_ARRAY_GET,
-                          new Integer(FunctionTable.FUNC_ARRAY_GET));
-         m_functionID.put(Keywords.FUNC_ARRAY_PUT,
-                          new Integer(FunctionTable.FUNC_ARRAY_PUT));
-         m_functionID.put(Keywords.FUNC_ARRAY_APPEND,
-                          new Integer(FunctionTable.FUNC_ARRAY_APPEND));
-         m_functionID.put(Keywords.FUNC_ARRAY_SUBARRAY,
-                          new Integer(FunctionTable.FUNC_ARRAY_SUBARRAY));
+                         new Integer(FunctionTable.FUNC_DOCUMENT_URI));
          
          // XPath 3.1 functions configurations for the map functions 
          // namespace http://www.w3.org/2005/xpath-functions/map
@@ -1100,6 +1087,21 @@ public class FunctionTable
          m_functionID.put(Keywords.FUNC_MAP_ENTRY,
                          new Integer(FunctionTable.FUNC_MAP_ENTRY));
          
+         // XPath 3.1 functions configurations for the array functions 
+         // namespace http://www.w3.org/2005/xpath-functions/array
+         m_functionID.put(Keywords.FUNC_ARRAY_SIZE,
+                          new Integer(FunctionTable.FUNC_ARRAY_SIZE));
+         m_functionID.put(Keywords.FUNC_ARRAY_GET,
+                          new Integer(FunctionTable.FUNC_ARRAY_GET));
+         m_functionID.put(Keywords.FUNC_ARRAY_PUT,
+                          new Integer(FunctionTable.FUNC_ARRAY_PUT));
+         m_functionID.put(Keywords.FUNC_ARRAY_APPEND,
+                          new Integer(FunctionTable.FUNC_ARRAY_APPEND));
+         m_functionID.put(Keywords.FUNC_ARRAY_SUBARRAY,
+                          new Integer(FunctionTable.FUNC_ARRAY_SUBARRAY));
+         m_functionID.put(Keywords.FUNC_ARRAY_REMOVE,
+                          new Integer(FunctionTable.FUNC_ARRAY_REMOVE));
+         
          m_functionID.put(Keywords.FUNC_NAME_STRING,
                           new Integer(FunctionTable.FUNC_NAME));
          
diff --git a/src/org/apache/xpath/compiler/XPathParserImpl.java b/src/org/apache/xpath/compiler/XPathParserImpl.java
index 9007df23..64575722 100644
--- a/src/org/apache/xpath/compiler/XPathParserImpl.java
+++ b/src/org/apache/xpath/compiler/XPathParserImpl.java
@@ -66,7 +66,7 @@ import org.apache.xpath.res.XPATHErrorResources;
  *      (please also refer to section 'A XPath 3.1 Grammar', within
  *       this document)
  * 
- * @author Scott Boag,
+ * @author Scott Boag
  * @author Myriam Midy
  * @author Joseph Kesselman, Ilene Seelemann, Yash Talwar, 
  *         Henry Zongaro, Christine Li
@@ -1049,24 +1049,13 @@ public class XPathParserImpl
     	   if ("contains".equals(key)) {
       		  id = FunctionTable.FUNC_CONTAINS;  
       	   }
+    	   else if ("remove".equals(key)) {
+       		  id = FunctionTable.FUNC_REMOVE;  
+       	   }
     	   else {
     		  id = m_functionTable.getFunctionID(key); 
     	   }
-    	}
-    	else if ((FunctionTable.XPATH_BUILT_IN_ARRAY_FUNCS_NS_URI).equals(nsUri)) {
-    	   if ("size".equals(key)) {
-        	  id = FunctionTable.FUNC_ARRAY_SIZE;   
-           }
-    	   else if ("get".equals(key)) {
-    		  id = FunctionTable.FUNC_ARRAY_GET; 
-    	   }
-    	   else if ("put".equals(key)) {
-     		  id = FunctionTable.FUNC_ARRAY_PUT; 
-     	   }
-    	   else {
-    		  id = m_functionTable.getFunctionID(key); 
-    	   }
-    	}
+    	}    	
     	else if ((FunctionTable.XPATH_BUILT_IN_MAP_FUNCS_NS_URI).equals(nsUri)) {
     	   if ("size".equals(key)) {
           	  id = FunctionTable.FUNC_MAP_SIZE;   
@@ -1080,10 +1069,33 @@ public class XPathParserImpl
     	   else if ("contains".equals(key)) {
     		  id = FunctionTable.FUNC_MAP_CONTAINS;  
     	   }
-    	   else {
-     		  id = m_functionTable.getFunctionID(key); 
+    	   else if ("keys".equals(key)) {
+     		  id = FunctionTable.FUNC_MAP_KEYS;  
      	   }
+    	   else if ("entry".equals(key)) {
+      		  id = FunctionTable.FUNC_MAP_ENTRY;  
+      	   }
     	}
+    	else if ((FunctionTable.XPATH_BUILT_IN_ARRAY_FUNCS_NS_URI).equals(nsUri)) {
+     	   if ("size".equals(key)) {
+         	  id = FunctionTable.FUNC_ARRAY_SIZE;   
+           }
+     	   else if ("get".equals(key)) {
+     		  id = FunctionTable.FUNC_ARRAY_GET; 
+     	   }
+     	   else if ("put".equals(key)) {
+      		  id = FunctionTable.FUNC_ARRAY_PUT; 
+      	   }
+     	   else if ("append".equals(key)) {
+       		  id = FunctionTable.FUNC_ARRAY_APPEND; 
+       	   }
+     	   else if ("subarray".equals(key)) {
+       		  id = FunctionTable.FUNC_ARRAY_SUBARRAY; 
+       	   }
+     	   else if ("remove".equals(key)) {
+       		  id = FunctionTable.FUNC_ARRAY_REMOVE; 
+       	   }
+     	}
     	else {
     	   id = m_functionTable.getFunctionID(key);
     	}
@@ -1175,7 +1187,7 @@ public class XPathParserImpl
           
           List<String> sequenceConstructorXPathParts = new ArrayList<String>();
           
-          if (tokenIs(')') && (getTokenRelative(0) == null)) {
+          if (!isSquareArrayConstructor && tokenIs(')') && (getTokenRelative(0) == null)) {
               // handles the case, where the XPath expression is ()
               
               int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@@ -1191,18 +1203,30 @@ public class XPathParserImpl
                                                                     sequenceConstructorXPathParts);
               
               m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 
-                                                  m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
+            		                                 m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
               
               return;
           }          
-          else if (tokenIs(']') && (getTokenRelative(0) == null)) {
+          else if (isSquareArrayConstructor && tokenIs(']') && (getTokenRelative(0) == null)) {
              // handles the case, where the XPath expression is []
         	 
-        	 // TO DO
+             int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
+              
+             nextToken();                            
+              
+             insertOp(opPos, 2, OpCodes.OP_SQUARE_ARRAY_CONSTRUCTOR_EXPR);
+             
+             fSquareArrayConstructor = new SquareArrayConstructor();
+             
+             // TO DO
+             
+             m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, 
+                                                    m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
+
+             return;             
           }
           
-          while (m_token != null)
-          {                            
+          while (m_token != null) {                            
               if (tokenIs("function")) {
                  // XPath expression parse from here, till the token '}' shall get 
                  // an 'inline function expression' string. The XPath expression
@@ -1247,7 +1271,8 @@ public class XPathParserImpl
                  
                  if (seqItemXPathStrPartsList.size() > 0) {
                     String seqItemXPathExprStr = getXPathStrFromComponentParts(seqItemXPathStrPartsList);
-                    if (seqItemXPathExprStr.endsWith(")")) {
+                    boolean xpathExprEndsWithParen = !isSquareArrayConstructor ? seqItemXPathExprStr.endsWith(")") : seqItemXPathExprStr.endsWith("]");
+                    if (xpathExprEndsWithParen) {
                         seqItemXPathExprStr = seqItemXPathExprStr.substring(0, 
                                                                        seqItemXPathExprStr.length());    
                     }
@@ -1266,7 +1291,9 @@ public class XPathParserImpl
           // has balanced parentheses pairs '(' and ')'.
           for (int idx = 0; idx < sequenceConstructorXPathParts.size(); idx++) {
              String seqItemXPathExprStr = sequenceConstructorXPathParts.get(idx);
-             boolean isStrHasBalancedParentheses = isStrHasBalancedParentheses(seqItemXPathExprStr, '(', ')');
+             char lParenChar = !isSquareArrayConstructor ? '(' : '[';
+             char rParenChar = !isSquareArrayConstructor ? ')' : ']';
+             boolean isStrHasBalancedParentheses = isStrHasBalancedParentheses(seqItemXPathExprStr, lParenChar, rParenChar);
              if (!isStrHasBalancedParentheses) {
                 isXPathExprOkToProceed = false;
                 break;
@@ -1274,9 +1301,9 @@ public class XPathParserImpl
           }
           
           // To check, whether an xdm sequence with at-least two items could be constructed
-          if (!(isXPathExprOkToProceed && (sequenceConstructorXPathParts.size() > 1))) {
-             isXPathExprOkToProceed = false;    
-          }
+	      if (!isSquareArrayConstructor && !(isXPathExprOkToProceed && (sequenceConstructorXPathParts.size() > 1))) {
+	         isXPathExprOkToProceed = false;    
+	      }
           
           // Upto here within this method, we've analyzed an given XPath input string 
           // completely by traversing its sequence of XPath tokens. We can now choose from one of 
@@ -3197,13 +3224,13 @@ public class XPathParserImpl
           funcTok = -1;
           error(XPATHErrorResources.ER_COULDNOT_FIND_FUNCTION,
                 new Object[] {"{" + FunctionTable.XPATH_BUILT_IN_FUNCS_NS_URI + "}" + m_token + "()"});  
-      }
-      else if ((FunctionTable.XPATH_ARRAY_FUNC_IDS_ARR).contains(Integer.valueOf(funcTok))) {
+      }      
+      else if ((FunctionTable.XPATH_MAP_FUNC_IDS_ARR).contains(Integer.valueOf(funcTok))) {
           funcTok = -1;
           error(XPATHErrorResources.ER_COULDNOT_FIND_FUNCTION,
                 new Object[] {"{" + FunctionTable.XPATH_BUILT_IN_FUNCS_NS_URI + "}" + m_token + "()"});  
       }
-      else if ((FunctionTable.XPATH_MAP_FUNC_IDS_ARR).contains(Integer.valueOf(funcTok))) {
+      else if ((FunctionTable.XPATH_ARRAY_FUNC_IDS_ARR).contains(Integer.valueOf(funcTok))) {
           funcTok = -1;
           error(XPATHErrorResources.ER_COULDNOT_FIND_FUNCTION,
                 new Object[] {"{" + FunctionTable.XPATH_BUILT_IN_FUNCS_NS_URI + "}" + m_token + "()"});  
diff --git a/src/org/apache/xpath/composite/MapConstructor.java b/src/org/apache/xpath/composite/MapConstructor.java
index 8619c223..40614da8 100644
--- a/src/org/apache/xpath/composite/MapConstructor.java
+++ b/src/org/apache/xpath/composite/MapConstructor.java
@@ -43,9 +43,12 @@ import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XNodeSet;
 import org.apache.xpath.objects.XNumber;
 import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XPathArray;
 import org.apache.xpath.objects.XPathMap;
+import org.apache.xpath.objects.XString;
 
 import xml.xpath31.processor.types.XSNumericType;
+import xml.xpath31.processor.types.XSString;
 
 /*
  * An XalanJ XPath parser, constructs an object of this class, 
@@ -70,6 +73,9 @@ public class MapConstructor extends Expression {
     private Vector fVars;    
     private int fGlobalsSize;
     
+    private String KEY = "key";
+    private String VALUE = "value";
+    
     @Override
     public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) {
        // no op
@@ -97,20 +103,18 @@ public class MapConstructor extends Expression {
                                                                                                       prefixTable);        	  
            }
            
-           ResultSequence mapEntryKey = evaluateXPathExpression(xpathKeyStr, xctxt);
+           XObject mapEntryKey = evaluateXPathExpression(xpathKeyStr, xctxt, KEY);
+           if (mapEntryKey instanceof XString) {
+        	  mapEntryKey = new XSString(((XString)mapEntryKey).str()); 
+           }
            
            if (prefixTable != null) {
         	  xpathValueStr = XslTransformEvaluationHelper.replaceNsUrisWithPrefixesOnXPathStr(xpathValueStr, 
                                                                                                        prefixTable);        	  
            }
            
-           ResultSequence mapEntryValue = evaluateXPathExpression(xpathValueStr, xctxt);
-           XObject mapEntryValueObj = mapEntryValue; 
-           if (mapEntryValue.size() == 1) {
-        	  mapEntryValueObj = mapEntryValue.item(0);
-           }
-           
-           xpathResultMap.put(mapEntryKey, mapEntryValueObj);
+           XObject mapEntryValue = evaluateXPathExpression(xpathValueStr, xctxt, VALUE);           
+           xpathResultMap.put(mapEntryKey, mapEntryValue);
         }
         
         return xpathResultMap;
@@ -135,15 +139,22 @@ public class MapConstructor extends Expression {
         return false;
     }
     
-    private ResultSequence evaluateXPathExpression(String xpathExprStr, XPathContext xctxt) throws TransformerException {
-    	ResultSequence resultSeq = null;
+    /**
+     * 
+     * @param xpathExprStr   XPath expression string to be evaluated
+     * @param xctxt          XPath context
+     * @param mapComponent   is either of strings "key", or "value"
+     * @return               Result of XPath expression evaluation
+     * 
+     * @throws TransformerException
+     */
+    private XObject evaluateXPathExpression(String xpathExprStr, XPathContext xctxt, String mapComponentName) throws TransformerException {
+    	XObject result = null;
     	
     	int contextNode = xctxt.getContextNode();
     	
     	SourceLocator srcLocator = xctxt.getSAXLocator();
     	
-    	resultSeq = new ResultSequence();
-    	
     	XPath xpathObj = new XPath(xpathExprStr, srcLocator, xctxt.getNamespaceContext(), XPath.SELECT, null);
         if (fVars != null) {
            xpathObj.fixupVariables(fVars, fGlobalsSize);
@@ -164,19 +175,31 @@ public class MapConstructor extends Expression {
             
             if (dtmIter != null) {
                int nextNode;
+               int nodeCount = 0;
+               XPathArray mapEntryValue = new XPathArray();
                while ((nextNode = dtmIter.nextNode()) != DTM.NULL) {
+            	   nodeCount++;
+            	   if (KEY.equals(mapComponentName)) {
+            	      if (nodeCount > 1) {
+            		     throw new javax.xml.transform.TransformerException("XPTY0004 : Key of a map cannot be a sequence of size "
+            		  		                                                                   + "greater than one.", srcLocator); 
+            	      }
+            	      else {
+            	    	 result = new XNodeSet(nextNode, xctxt);
+            	    	 return result;
+            	      }
+            	   }            	   
                    XNodeSet xNodeSetItem = new XNodeSet(nextNode, xctxt);
-                   resultSeq.add(xNodeSetItem);
+                   mapEntryValue.add(xNodeSetItem);
                }
+               
+               return mapEntryValue; 
             }
             else if (xpathExprStr.startsWith("$") && xpathExprStr.contains("[") && 
                                                                         xpathExprStr.endsWith("]")) {
                 String varRefXPathExprStr = "$" + xpathExprStr.substring(1, xpathExprStr.indexOf('['));
                 String xpathIndexExprStr = xpathExprStr.substring(xpathExprStr.indexOf('[') + 1, 
-                                                                                    xpathExprStr.indexOf(']'));
-                
-                // Evaluate the, variable reference XPath expression
-                
+                                                                                    xpathExprStr.indexOf(']'));                
                 XPath varXPathObj = new XPath(varRefXPathExprStr, srcLocator, xctxt.getNamespaceContext(), 
                                                                                                    XPath.SELECT, null);
                 XObject varEvalResult = varXPathObj.execute(xctxt, xctxt.getCurrentNode(), xctxt.getNamespaceContext());
@@ -197,7 +220,8 @@ public class MapConstructor extends Expression {
                        double dValIndex = ((XNumber)arrIndexEvalResult).num();
                        if (dValIndex == (int)dValIndex) {
                           XObject evalResult = varEvalResultSeq.item((int)dValIndex - 1);
-                          resultSeq.add(evalResult);
+                          result = evalResult;                          
+                          return result;
                        }
                        else {
                            throw new javax.xml.transform.TransformerException("XPTY0004 : an index value used with an xdm "
@@ -210,7 +234,8 @@ public class MapConstructor extends Expression {
                        double dValIndex = (Double.valueOf(indexStrVal)).doubleValue();
                        if (dValIndex == (int)dValIndex) {
                           XObject evalResult = varEvalResultSeq.item((int)dValIndex - 1);
-                          resultSeq.add(evalResult);
+                          result = evalResult;                          
+                          return result;
                        }
                        else {
                            throw new javax.xml.transform.TransformerException("XPTY0004 : an index value used with an xdm "
@@ -240,28 +265,49 @@ public class MapConstructor extends Expression {
                XNodeSet xNodeSet = (XNodeSet)xPathExprPartResult;
                DTMIterator sourceNodes = xNodeSet.iter();
                 
-               int nextNodeDtmHandle;
-                
-               while ((nextNodeDtmHandle = sourceNodes.nextNode()) != DTM.NULL) {
-                  XNodeSet xNodeSetItem = new XNodeSet(nextNodeDtmHandle, dtmMgr);
-                  resultSeq.add(xNodeSetItem);
+               int nextNode;
+               int nodeCount = 0;               
+               while ((nextNode = sourceNodes.nextNode()) != DTM.NULL) {
+            	  nodeCount++;
+                  XNodeSet xNodeSetItem = new XNodeSet(nextNode, dtmMgr);
+                  if (KEY.equals(mapComponentName)) {
+            	     if (nodeCount > 1) {
+            		    throw new javax.xml.transform.TransformerException("XPTY0004 : Key of a map cannot be a sequence of size "
+            		  		                                                                   + "greater than one.", srcLocator); 
+            	     }
+            	     else {
+            	    	result = new XNodeSet(nextNode, xctxt);
+            	    	return result;
+            	     }
+            	  } 
                }               
             }
             else if (xPathExprPartResult instanceof ResultSequence) {
-               ResultSequence inpResultSeq = (ResultSequence)xPathExprPartResult; 
+               ResultSequence inpResultSeq = (ResultSequence)xPathExprPartResult;
+               XPathArray mapEntryValue = new XPathArray();
                for (int idx1 = 0; idx1 < inpResultSeq.size(); idx1++) {
+            	  if (KEY.equals(mapComponentName)) {
+            		 if (idx1 > 0) {
+            	        throw new javax.xml.transform.TransformerException("XPTY0004 : Key of a map cannot be a sequence of size "
+            	     		                                                                        + "greater than one.", srcLocator);
+            		 }
+            		 else {
+            			result = inpResultSeq.item(idx1);
+            			return result;
+            		 }
+            	  }
                   XObject xObj = inpResultSeq.item(idx1);
-                  resultSeq.add(xObj);                 
+                  mapEntryValue.add(xObj);                 
                }
+               
+               return mapEntryValue;
             }
             else {
-               // We're assuming here that, an input value is an xdm sequence 
-               // with cardinality one.
-               resultSeq.add(xPathExprPartResult);               
+               return xPathExprPartResult;               
             }
         }
     	
-    	return resultSeq;
+    	return result;
     }
 
 }
diff --git a/src/org/apache/xpath/functions/DynamicFunctionCall.java b/src/org/apache/xpath/functions/DynamicFunctionCall.java
index a9722893..a6ace08b 100644
--- a/src/org/apache/xpath/functions/DynamicFunctionCall.java
+++ b/src/org/apache/xpath/functions/DynamicFunctionCall.java
@@ -42,6 +42,9 @@ import org.apache.xpath.objects.InlineFunction;
 import org.apache.xpath.objects.InlineFunctionParameter;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XPathMap;
+import org.apache.xpath.objects.XString;
+
+import xml.xpath31.processor.types.XSString;
 
 /*
  * XalanJ xpath parser, constructs an object of this class 
@@ -152,6 +155,9 @@ public class DynamicFunctionCall extends Expression {
                   }
 
                   XObject argValue = argXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
+                  if (argValue instanceof XString) {
+                	 argValue = new XSString(((XString)argValue).str());  
+                  }
                   
                   evalResult = xpathMap.get(argValue); 
     		   }    		   
diff --git a/src/org/apache/xpath/functions/FuncParseJson.java b/src/org/apache/xpath/functions/FuncParseJson.java
index 0d8fe2cf..40c3260d 100644
--- a/src/org/apache/xpath/functions/FuncParseJson.java
+++ b/src/org/apache/xpath/functions/FuncParseJson.java
@@ -24,8 +24,8 @@ import org.apache.xalan.res.XSLMessages;
 import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
 import org.apache.xpath.Expression;
 import org.apache.xpath.XPathContext;
-import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XPathArray;
 import org.apache.xpath.objects.XPathMap;
 import org.apache.xpath.res.XPATHErrorResources;
 import org.json.JSONArray;
@@ -130,7 +130,7 @@ public class FuncParseJson extends FunctionMultiArgs {
 	      		  ((XPathMap)result).put(new XSString(key), value1);
 	      	   }
 	      	   else if (value instanceof JSONArray) {
-	      		  ResultSequence rSeq = new ResultSequence();
+	      		  XPathArray xpathArr = new XPathArray();
 	      		  
 	      		  JSONArray jsonArr = (JSONArray)value;	      		  
 	      		  int arrLen = jsonArr.length();
@@ -151,15 +151,15 @@ public class FuncParseJson extends FunctionMultiArgs {
 	      				xObj = getXdmValueFromNativeJson(arrItem);
 	      			 }
 	      			 
-	      			 rSeq.add(xObj);
+	      			xpathArr.add(xObj);
 	      		  }
 	      		  
-	      		  ((XPathMap)result).put(new XSString(key), rSeq);
+	      		  ((XPathMap)result).put(new XSString(key), xpathArr);
 	      	   }
 	        }
     	}
     	else if (jsonObj instanceof JSONArray) {
-    		ResultSequence rSeq = new ResultSequence();
+    		XPathArray xpathArr = new XPathArray();
     		
     		JSONArray jsonArr = (JSONArray)jsonObj;	      		  
     		int arrLen = jsonArr.length();
@@ -180,10 +180,10 @@ public class FuncParseJson extends FunctionMultiArgs {
     		      xObj = getXdmValueFromNativeJson(arrItem);
     		   }
     			 
-    		   rSeq.add(xObj);
+    		   xpathArr.add(xObj);
     		}
     		  
-    		result = rSeq;
+    		result = xpathArr;
     	}
     	
     	return result;
diff --git a/src/org/apache/xpath/functions/array/FuncArrayAppend.java b/src/org/apache/xpath/functions/array/FuncArrayAppend.java
index 0f3a4419..4a570f83 100644
--- a/src/org/apache/xpath/functions/array/FuncArrayAppend.java
+++ b/src/org/apache/xpath/functions/array/FuncArrayAppend.java
@@ -26,7 +26,7 @@ import org.apache.xpath.objects.XPathArray;
 import org.apache.xpath.operations.Variable;
 
 /**
- * Implementation of the array:append() function.
+ * Implementation of the array:append function.
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
diff --git a/src/org/apache/xpath/functions/array/FuncArrayGet.java b/src/org/apache/xpath/functions/array/FuncArrayGet.java
index 7231ce10..25fddad0 100644
--- a/src/org/apache/xpath/functions/array/FuncArrayGet.java
+++ b/src/org/apache/xpath/functions/array/FuncArrayGet.java
@@ -35,7 +35,7 @@ import org.apache.xpath.operations.Variable;
 import xml.xpath31.processor.types.XSNumericType;
 
 /**
- * Implementation of the array:get() function.
+ * Implementation of the array:get function.
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
@@ -62,7 +62,7 @@ public class FuncArrayGet extends Function2Args {
 	       }
 	       else {
 	    	  throw new javax.xml.transform.TransformerException("FORG0006 : The 1st argument of array:get function call, "
-	    	  		                                                                      + "needs to be an xdm array", srcLocator);  
+	    	  		                                                                      + "needs to be of type array", srcLocator);  
 	       }
 	    }
 	    else {
@@ -72,7 +72,7 @@ public class FuncArrayGet extends Function2Args {
 		    }
 		    else {
 		       throw new javax.xml.transform.TransformerException("FORG0006 : The 1st argument of array:get function call, "
-		       		                                                                      + "needs to be an xdm array", srcLocator);   
+		       		                                                                      + "needs to be of type array", srcLocator);   
 		    }
 	    }
 	    
diff --git a/src/org/apache/xpath/functions/array/FuncArrayPut.java b/src/org/apache/xpath/functions/array/FuncArrayPut.java
index 826a3aff..57b9fb37 100644
--- a/src/org/apache/xpath/functions/array/FuncArrayPut.java
+++ b/src/org/apache/xpath/functions/array/FuncArrayPut.java
@@ -32,7 +32,7 @@ import org.apache.xpath.operations.Variable;
 import xml.xpath31.processor.types.XSNumericType;
 
 /**
- * Implementation of the array:put() function.
+ * Implementation of the array:put function.
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
diff --git a/src/org/apache/xpath/functions/array/FuncArrayRemove.java b/src/org/apache/xpath/functions/array/FuncArrayRemove.java
new file mode 100644
index 00000000..4f61f4af
--- /dev/null
+++ b/src/org/apache/xpath/functions/array/FuncArrayRemove.java
@@ -0,0 +1,236 @@
+/*
+ * 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.array;
+
+import javax.xml.transform.SourceLocator;
+
+import org.apache.xpath.Expression;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.functions.Function2Args;
+import org.apache.xpath.objects.ResultSequence;
+import org.apache.xpath.objects.XNumber;
+import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XPathArray;
+import org.apache.xpath.operations.Variable;
+
+import xml.xpath31.processor.types.XSInteger;
+import xml.xpath31.processor.types.XSNumericType;
+
+/**
+ * Implementation of the array:remove function.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FuncArrayRemove extends Function2Args {
+
+	private static final long serialVersionUID = 7890619596202668602L;
+
+	public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException {
+		
+	    XObject result = null;
+	       
+	    SourceLocator srcLocator = xctxt.getSAXLocator();
+	       
+	    Expression arg0Expr = getArg0();	    
+	    Expression arg1Expr = getArg1();	    	    
+	    
+	    XPathArray arg0Arr = null;
+	    if (arg0Expr instanceof Variable) {
+	       XObject arg0Value = ((Variable)arg0Expr).execute(xctxt);
+	       if (arg0Value instanceof XPathArray) {
+	    	  arg0Arr = (XPathArray)arg0Value;
+	       }
+	       else {
+	    	  throw new javax.xml.transform.TransformerException("FORG0006 : The 1st argument of array:remove function call, "
+	    	  		                                                                       + "needs to be an xdm array.", srcLocator);  
+	       }
+	    }
+	    else {
+	    	XObject arg0Value = arg0Expr.execute(xctxt);
+	    	if (arg0Value instanceof XPathArray) {
+	    	   arg0Arr = (XPathArray)arg0Value;
+		    }
+		    else {
+		       throw new javax.xml.transform.TransformerException("FORG0006 : The 1st argument of array:remove function call, "
+		       		                                                                      + "needs to be an xdm array.", srcLocator);   
+		    }
+	    }
+	    	    
+	    XPathArray resultArr = new XPathArray();
+	    
+	    XObject arg1 = null;
+	    if (arg1Expr instanceof Variable) {
+	       arg1 = ((Variable)arg1Expr).execute(xctxt);
+	       if (isXdmValueAnIntegerSeq(arg1)) {
+	    	  ResultSequence seqInt = getIntegerSeq(arg1); 
+	    	  for (int idx = 0; idx < arg0Arr.size(); idx++) {
+	    		 if (!isIntegerSeqContainsAnInteger(seqInt, idx + 1)) {
+	    			resultArr.add(arg0Arr.get(idx));  
+	    		 }
+	    	  }
+	       }
+	       else {
+	    	  throw new javax.xml.transform.TransformerException("FOAY0001 : The 2nd argument of array:remove function "
+	    	  		                                                    + "call, needs to be an xs:integer sequence.", srcLocator); 
+	       }
+	    }
+	    else {
+	       arg1 = arg1Expr.execute(xctxt);
+	       if (isXdmValueAnIntegerSeq(arg1)) {
+	    	  ResultSequence seqInt = getIntegerSeq(arg1); 
+		      for (int idx = 0; idx < arg0Arr.size(); idx++) {
+		         if (!isIntegerSeqContainsAnInteger(seqInt, idx + 1)) {
+		    	    resultArr.add(arg0Arr.get(idx));  
+		    	 }
+		      }   
+		   }
+		   else {
+			  throw new javax.xml.transform.TransformerException("FOAY0001 : The 2nd argument of array:remove function "
+                                                                         + "call, needs to be an xs:integer sequence.", srcLocator);	   
+		   }
+	    }
+	    
+	    result = resultArr;
+	    
+	    return result;
+	}
+
+	/**
+	 * Get an integer sequence, for an xdm value which is known 
+	 * to be a sequence of integer (or, which is castable to an 
+	 * integer) values.
+	 */
+	private ResultSequence getIntegerSeq(XObject xdmVal) {
+		ResultSequence result = new ResultSequence();
+		
+		if (xdmVal instanceof ResultSequence) {
+			   ResultSequence seq = (ResultSequence)xdmVal;
+			   for (int idx = 0; idx < seq.size(); idx++) {
+				  XObject item = seq.item(idx);
+				  if (item instanceof XSNumericType) {
+					 XSNumericType xsNumericVal = (XSNumericType)item;
+					 String strVal = xsNumericVal.stringValue();
+					 XSInteger xsInteger = new XSInteger(strVal);
+					 result.add(xsInteger);
+				  }
+				  else if (item instanceof XNumber) {
+					 XNumber xNumberVal = (XNumber)item;
+					 double dblVal = xNumberVal.num();
+					 String strVal = (Double.valueOf(dblVal)).toString();
+					 XSInteger xsInteger = new XSInteger(strVal);
+					 result.add(xsInteger);
+				  }
+			   }
+			} 
+			else if (xdmVal instanceof XSNumericType) {
+			   XSNumericType xsNumericVal = (XSNumericType)xdmVal;
+			   String strVal = xsNumericVal.stringValue();
+			   XSInteger xsInteger = new XSInteger(strVal);
+			   result.add(xsInteger);
+			}
+			else if (xdmVal instanceof XNumber) {
+			   XNumber xNumberVal = (XNumber)xdmVal;
+			   double dblVal = xNumberVal.num();
+			   // String strVal = (Double.valueOf(dblVal)).toString();
+				 XSInteger xsInteger = new XSInteger();
+				 xsInteger.setDouble(dblVal);
+				 result.add(xsInteger);
+			}
+		
+		return result;
+	}
+
+	/**
+	 * Find whether an, xdm value is an integer sequence.
+	 */
+	private boolean isXdmValueAnIntegerSeq(XObject xdmVal) {		
+		boolean isIntegerSeq = true;
+		
+		if (xdmVal instanceof ResultSequence) {
+		   ResultSequence seq = (ResultSequence)xdmVal;
+		   for (int idx = 0; idx < seq.size(); idx++) {
+			  XObject item = seq.item(idx);
+			  if (item instanceof XSNumericType) {
+				 XSNumericType xsNumericVal = (XSNumericType)item;
+				 String strVal = xsNumericVal.stringValue();
+				 try {
+				    Integer integer = Integer.valueOf(strVal);
+				 }
+				 catch (NumberFormatException ex) {
+					isIntegerSeq = false;
+					break;
+				 }
+			  }
+			  else if (item instanceof XNumber) {
+				 XNumber xNumberVal = (XNumber)item;
+				 double dblVal = xNumberVal.num();
+				 if (!((int)dblVal == dblVal)) {
+					isIntegerSeq = false;
+				    break; 
+				 }
+			  }
+			  else {
+				 isIntegerSeq = false;
+				 break;
+			  }
+		   }
+		} 
+		else if (xdmVal instanceof XSNumericType) {
+		   XSNumericType xsNumericVal = (XSNumericType)xdmVal;
+		   String strVal = xsNumericVal.stringValue();
+		   try {
+		      Integer integer = Integer.valueOf(strVal);
+		   }
+		   catch (NumberFormatException ex) {
+			  isIntegerSeq = false;
+		   }
+		}
+		else if (xdmVal instanceof XNumber) {
+		   XNumber xNumberVal = (XNumber)xdmVal;
+		   double dblVal = xNumberVal.num();
+		   if (!((int)dblVal == dblVal)) {
+			  isIntegerSeq = false; 
+		   } 
+		}
+		else {
+		   isIntegerSeq = false; 
+		}
+		
+		return isIntegerSeq; 
+	}
+	
+	/**
+	 * Find whether an, integer sequence contains a specific integer value.
+	 */
+	private boolean isIntegerSeqContainsAnInteger(ResultSequence seq, int value) {
+		boolean result = false;
+		
+		for (int idx = 0; idx < seq.size(); idx++) {
+		   XSInteger item = (XSInteger)(seq.item(idx));
+		   double dblVal = item.doubleValue();
+		   if ((int)dblVal == value) {
+			  result = true;
+			  break;
+		   }
+		}
+		
+		return result;
+    }
+
+}
diff --git a/src/org/apache/xpath/functions/array/FuncArraySize.java b/src/org/apache/xpath/functions/array/FuncArraySize.java
index 0c268d1a..96721960 100644
--- a/src/org/apache/xpath/functions/array/FuncArraySize.java
+++ b/src/org/apache/xpath/functions/array/FuncArraySize.java
@@ -30,7 +30,7 @@ import org.apache.xpath.operations.Variable;
 import xml.xpath31.processor.types.XSInteger;
 
 /**
- * Implementation of the array:size() function.
+ * Implementation of the array:size function.
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
diff --git a/src/org/apache/xpath/functions/array/FuncSubarray.java b/src/org/apache/xpath/functions/array/FuncSubarray.java
index 91ffac4e..bd9c7354 100644
--- a/src/org/apache/xpath/functions/array/FuncSubarray.java
+++ b/src/org/apache/xpath/functions/array/FuncSubarray.java
@@ -30,7 +30,7 @@ import org.apache.xpath.operations.Variable;
 import xml.xpath31.processor.types.XSNumericType;
 
 /**
- * Implementation of the array:subarray() function.
+ * Implementation of the array:subarray function.
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
diff --git a/src/org/apache/xpath/functions/map/FuncMapContains.java b/src/org/apache/xpath/functions/map/FuncMapContains.java
index 561cc8af..b230f629 100644
--- a/src/org/apache/xpath/functions/map/FuncMapContains.java
+++ b/src/org/apache/xpath/functions/map/FuncMapContains.java
@@ -25,9 +25,11 @@ import org.apache.xpath.XPathContext;
 import org.apache.xpath.functions.Function2Args;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XPathMap;
+import org.apache.xpath.objects.XString;
 import org.apache.xpath.operations.Variable;
 
 import xml.xpath31.processor.types.XSBoolean;
+import xml.xpath31.processor.types.XSString;
 
 /**
  * Implementation of an map:contains function.
@@ -62,6 +64,9 @@ public class FuncMapContains extends Function2Args {
 	    
 	    Expression arg1 = getArg1();
 	    XObject arg1Obj = arg1.execute(xctxt);
+	    if (arg1Obj instanceof XString) {
+	       arg1Obj = new XSString(((XString)arg1Obj).str());
+	    }
 	    
 	    if (nativeMap.get(arg1Obj) != null) {
 	       result = new XSBoolean(true);	
diff --git a/src/org/apache/xpath/functions/map/FuncMapEntry.java b/src/org/apache/xpath/functions/map/FuncMapEntry.java
index 12733895..fc511093 100644
--- a/src/org/apache/xpath/functions/map/FuncMapEntry.java
+++ b/src/org/apache/xpath/functions/map/FuncMapEntry.java
@@ -23,8 +23,11 @@ import org.apache.xpath.XPathContext;
 import org.apache.xpath.functions.Function2Args;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XPathMap;
+import org.apache.xpath.objects.XString;
 import org.apache.xpath.operations.Variable;
 
+import xml.xpath31.processor.types.XSString;
+
 /**
  * Implementation of an map:entry function.
  * 
@@ -55,6 +58,10 @@ public class FuncMapEntry extends Function2Args {
 	       resultMapEntryKey = arg0.execute(xctxt);
 	    }
 	    
+	    if (resultMapEntryKey instanceof XString) {
+	    	resultMapEntryKey = new XSString(((XString)resultMapEntryKey).str());
+	    }
+	    
 	    if (arg1 instanceof Variable) {
 	       resultMapEntryVal = ((Variable)arg1).execute(xctxt);
 		}
@@ -62,6 +69,10 @@ public class FuncMapEntry extends Function2Args {
 		   resultMapEntryVal = arg1.execute(xctxt);
 		}
 	    
+	    if (resultMapEntryVal instanceof XString) {
+	       resultMapEntryVal = new XSString(((XString)resultMapEntryVal).str());
+	    }
+	    
 	    XPathMap resultMap = new XPathMap();
 	    resultMap.put(resultMapEntryKey, resultMapEntryVal);
 	    
diff --git a/src/org/apache/xpath/functions/map/FuncMapGet.java b/src/org/apache/xpath/functions/map/FuncMapGet.java
index b9b1a24d..a8caaed2 100644
--- a/src/org/apache/xpath/functions/map/FuncMapGet.java
+++ b/src/org/apache/xpath/functions/map/FuncMapGet.java
@@ -26,8 +26,11 @@ import org.apache.xpath.functions.Function2Args;
 import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XPathMap;
+import org.apache.xpath.objects.XString;
 import org.apache.xpath.operations.Variable;
 
+import xml.xpath31.processor.types.XSString;
+
 /**
  * Implementation of an map:get function.
  * 
@@ -46,35 +49,27 @@ public class FuncMapGet extends Function2Args {
 	    SourceLocator srcLocator = xctxt.getSAXLocator();
 	       
 	    Expression arg0 = getArg0();
-	    XPathMap xpathMap = null;
+	    XPathMap arg0Map = null;
 	    
 	    if (arg0 instanceof Variable) {
 	       XObject xObject = ((Variable)arg0).execute(xctxt);
-	       xpathMap = (XPathMap)xObject;
+	       arg0Map = (XPathMap)xObject;
 	    }
 	    else {
 	       XObject xObject = arg0.execute(xctxt);
-		   xpathMap = (XPathMap)xObject;
+		   arg0Map = (XPathMap)xObject;
 	    }
 	    
-	    Map<XObject, XObject> nativeMap = xpathMap.getNativeMap();
+	    Map<XObject, XObject> nativeMap = arg0Map.getNativeMap();
 	    
 	    Expression arg1 = getArg1();
 	    XObject arg1Obj = arg1.execute(xctxt);
+	    if (arg1Obj instanceof XString) {
+	       arg1Obj = new XSString(((XString)arg1Obj).str());	
+	    }
 	    
 	    result = nativeMap.get(arg1Obj);
-	    if (result != null) {
-	       if (result instanceof ResultSequence) {
-	    	  ResultSequence rSeq = (ResultSequence)result;
-	    	  if (rSeq.size() == 1) {
-	    	     result = rSeq.item(0);
-	    	  }
-	    	  else {
-	    	     result = rSeq;
-	    	  }
-	       }
-	    }
-	    else {
+	    if (result == null) {	       
 	       result = new ResultSequence();	
 	    }
 	    
diff --git a/src/org/apache/xpath/functions/map/FuncMapPut.java b/src/org/apache/xpath/functions/map/FuncMapPut.java
index b6319369..7aa452e9 100644
--- a/src/org/apache/xpath/functions/map/FuncMapPut.java
+++ b/src/org/apache/xpath/functions/map/FuncMapPut.java
@@ -23,7 +23,6 @@ import javax.xml.transform.SourceLocator;
 import org.apache.xpath.Expression;
 import org.apache.xpath.XPathContext;
 import org.apache.xpath.functions.Function3Args;
-import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XPathMap;
 import org.apache.xpath.operations.Variable;
@@ -60,26 +59,10 @@ public class FuncMapPut extends Function3Args {
 	    Map<XObject, XObject> nativeMap = xpathMap.getNativeMap();
 	    
 	    Expression arg1 = getArg1();    // 'key' argument
-	    XObject arg1Obj = arg1.execute(xctxt);
-	    ResultSequence mapEntryKey = null;
-	    if (!(arg1Obj instanceof ResultSequence)) {
-	       mapEntryKey = new ResultSequence();
-	       mapEntryKey.add(arg1Obj);	       
-	    }
-	    else {
-	       mapEntryKey = (ResultSequence)arg1Obj;
-	    }
+	    XObject mapEntryKey = arg1.execute(xctxt);
 	    
 	    Expression arg2 = getArg2();   // 'value' argument
-	    XObject arg2Obj = arg2.execute(xctxt);
-	    ResultSequence mapEntryValue = null;
-	    if (!(arg2Obj instanceof ResultSequence)) {
-	       mapEntryValue = new ResultSequence();
-	       mapEntryValue.add(arg2Obj);	       
-	    }
-	    else {
-	       mapEntryValue = (ResultSequence)arg2Obj; 
-	    }
+	    XObject mapEntryValue = arg2.execute(xctxt);
 	    
 	    nativeMap.put(mapEntryKey, mapEntryValue);
 	    
diff --git a/tests/fn_parse_json/gold/xalanj_2738.out b/tests/fn_parse_json/gold/xalanj_2738.out
new file mode 100644
index 00000000..55fc28f5
--- /dev/null
+++ b/tests/fn_parse_json/gold/xalanj_2738.out
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <value>1</value>
+</result>
diff --git a/tests/xpath_maps/test13.xsl b/tests/fn_parse_json/parse-json-test1.xsl
similarity index 57%
copy from tests/xpath_maps/test13.xsl
copy to tests/fn_parse_json/parse-json-test1.xsl
index 2b56b7e4..bbae1707 100644
--- a/tests/xpath_maps/test13.xsl
+++ b/tests/fn_parse_json/parse-json-test1.xsl
@@ -1,31 +1,32 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"                
                 xmlns:xs="http://www.w3.org/2001/XMLSchema"
                 xmlns:map="http://www.w3.org/2005/xpath-functions/map"
-				exclude-result-prefixes="xs map"
-                version="3.0">				
+                xmlns:array="http://www.w3.org/2005/xpath-functions/array"
+				version="3.0"
+                exclude-result-prefixes="xs map array">
+                
+  <!-- XSL test case stylesheet, provided within XalanJ jira issue 
+       XALANJ-2738. Courtesy, Martin Honnen. -->
+       
+  <!-- use with xml-sample-with-json-data1.xml -->                      
 
-   <!-- Author: mukulg@apache.org -->                 				
+  <xsl:output method="xml" indent="yes"/>
 
-   <xsl:output method="xml" indent="yes"/>
-   
-   <!-- An XPath 3.1 test case, to test maps and arrays. -->
-
-   <xsl:template match="/">	  
-      <result>
-	     <xsl:variable name="map1" select="map {'ids' : [1, 2, 3, 4, 5], 'names' : ['Mukul', 'Joseph', 'Gary', 'John', 'Henry']}" as="map(*)"/>		 
-	     <map noOfEntries="{count(map:keys($map1))}">
-            <xsl:for-each select="map:keys($map1)">
-			   <xsl:variable name="key" select="."/>
-			   <entry key="{$key}">
-			      <xsl:value-of select="map:get($map1, $key)"/>
-			   </entry>
-			</xsl:for-each>
-		 </map>		 
-	  </result>
-   </xsl:template>
-   
-   <!--
+  <xsl:template match="/">
+    <result>
+       <value>
+	      <xsl:apply-templates select="root/data"/>
+	   </value>
+	</result>
+  </xsl:template>
+  
+  <xsl:template match="data">
+    <xsl:variable name="json-map" select="parse-json(.)"/>
+    <xsl:value-of select="array:get(map:get($json-map, 'data'), 1)"/>
+  </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
diff --git a/tests/fn_parse_json/xml-sample-with-json-data1.xml b/tests/fn_parse_json/xml-sample-with-json-data1.xml
new file mode 100644
index 00000000..307f8b57
--- /dev/null
+++ b/tests/fn_parse_json/xml-sample-with-json-data1.xml
@@ -0,0 +1,3 @@
+<root>
+  <data>{ "foo" : "bar", "data" : [1,2,3] }</data>
+</root>
diff --git a/tests/org/apache/xalan/xpath3/FnParseJsonTests.java b/tests/org/apache/xalan/xpath3/FnParseJsonTests.java
index 4d5e9d56..30bd824d 100644
--- a/tests/org/apache/xalan/xpath3/FnParseJsonTests.java
+++ b/tests/org/apache/xalan/xpath3/FnParseJsonTests.java
@@ -76,5 +76,15 @@ public class FnParseJsonTests extends XSLTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslFnParseJsonTest4() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "xml-sample-with-json-data1.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "parse-json-test1.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "xalanj_2738.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
 
 }
diff --git a/tests/org/apache/xalan/xpath3/XPathArrayTests.java b/tests/org/apache/xalan/xpath3/XPathArrayTests.java
index 896694b0..bc9359a3 100644
--- a/tests/org/apache/xalan/xpath3/XPathArrayTests.java
+++ b/tests/org/apache/xalan/xpath3/XPathArrayTests.java
@@ -117,5 +117,15 @@ public class XPathArrayTests extends XSLTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslArrayTest8() {
+        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/xpath_array/gold/test8.out b/tests/xpath_array/gold/test8.out
new file mode 100644
index 00000000..a194bb5a
--- /dev/null
+++ b/tests/xpath_array/gold/test8.out
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <one>b c d</one>
+  <two>a c d</two>
+  <three arrSizeAfterRemove="0"/>
+  <four>d</four>
+  <five>a b c d</five>
+</result>
diff --git a/tests/xpath_array/test8.xsl b/tests/xpath_array/test8.xsl
new file mode 100644
index 00000000..5d3aac5a
--- /dev/null
+++ b/tests/xpath_array/test8.xsl
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                xmlns:array="http://www.w3.org/2005/xpath-functions/array"
+                exclude-result-prefixes="xs array"
+                version="3.0">
+                
+    <!-- Author: mukulg@apache.org -->
+    
+    <!-- An XSLT 3.0 test case to test, XPath 3.1 function 
+         array:remove.
+    -->                              
+
+    <xsl:output method="xml" indent="yes"/>
+
+    <xsl:template match="/">
+       <result>
+         <xsl:variable name="arr1" select="['a', 'b', 'c', 'd']" as="array(xs:string)"/>
+         <xsl:variable name="arr2" select="['a']" as="array(xs:string)"/>
+         <one>
+            <xsl:value-of select="array:remove($arr1, 1)"/>
+         </one>
+         <two>
+            <xsl:value-of select="array:remove($arr1, 2)"/>
+         </two>
+         <xsl:variable name="arrResult" select="array:remove($arr2, 1)"/>
+         <three arrSizeAfterRemove="{array:size($arrResult)}">            
+            <xsl:value-of select="$arrResult"/>
+         </three>
+         <four>            
+            <xsl:value-of select="array:remove($arr1, 1 to 3)"/>
+         </four>
+         <five>            
+            <xsl:value-of select="array:remove($arr1, ())"/>
+         </five>
+       </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>
diff --git a/tests/xpath_maps/gold/test12.out b/tests/xpath_maps/gold/test12.out
index b5679d9c..4a0aeac1 100644
--- a/tests/xpath_maps/gold/test12.out
+++ b/tests/xpath_maps/gold/test12.out
@@ -1,13 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?><result>
-  <map noOfEntries="2">
-    <entry value="false" key="zero"/>
-    <entry value="true" key="one"/>
-  </map>
-  <map noOfEntries="5">
-    <entry value="Mukul" key="1"/>
-    <entry value="Joseph" key="2"/>
-    <entry value="Gary" key="3"/>
-    <entry value="John" key="4"/>
-    <entry value="Henry" key="5"/>
-  </map>
+  <map noOfEntries="2"/>
+  <map noOfEntries="5"/>
 </result>
diff --git a/tests/xpath_maps/gold/test13.out b/tests/xpath_maps/gold/test13.out
index 0063e570..f79e40b7 100644
--- a/tests/xpath_maps/gold/test13.out
+++ b/tests/xpath_maps/gold/test13.out
@@ -1,6 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?><result>
-  <map noOfEntries="2">
-    <entry key="names">Mukul Joseph Gary John Henry</entry>
-    <entry key="ids">1 2 3 4 5</entry>
-  </map>
+  <map noOfEntries="2"/>
 </result>
diff --git a/tests/xpath_maps/gold/test14.out b/tests/xpath_maps/gold/test14.out
index 6a28eb4c..f79e40b7 100644
--- a/tests/xpath_maps/gold/test14.out
+++ b/tests/xpath_maps/gold/test14.out
@@ -1,6 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?><result>
-  <map noOfEntries="2">
-    <entry value="Mukul Joseph Gary John Henry" key="names"/>
-    <entry value="1 2 3 4 5" key="ids"/>
-  </map>
+  <map noOfEntries="2"/>
 </result>
diff --git a/tests/xpath_maps/gold/test3.out b/tests/xpath_maps/gold/test3.out
index 7854314e..a69e2548 100644
--- a/tests/xpath_maps/gold/test3.out
+++ b/tests/xpath_maps/gold/test3.out
@@ -1,22 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?><result>
   <map>
-    <keys>
-      <val>Tu</val>
-      <val>Mo</val>
-      <val>Su</val>
-      <val>Th</val>
-      <val>Fr</val>
-      <val>Sa</val>
-      <val>We</val>
-    </keys>
+    <keys count="7"/>
   </map>
   <map>
-    <keys>
-      <val>1</val>
-      <val>2</val>
-    </keys>
+    <keys count="2"/>
   </map>
   <map>
-    <keys/>
+    <keys count="0"/>
   </map>
 </result>
diff --git a/tests/xpath_maps/gold/test9.out b/tests/xpath_maps/gold/test9.out
index ef485ccd..d3cd38a4 100644
--- a/tests/xpath_maps/gold/test9.out
+++ b/tests/xpath_maps/gold/test9.out
@@ -1,22 +1 @@
-<?xml version="1.0" encoding="UTF-8"?><innerMap>
-  <entry>
-    <key>x1</key>
-    <value>p</value>
-  </entry>
-  <entry>
-    <key>x2</key>
-    <value>q</value>
-  </entry>
-  <entry>
-    <key>x3</key>
-    <value>r</value>
-  </entry>
-  <entry>
-    <key>x4</key>
-    <value>s</value>
-  </entry>
-  <entry>
-    <key>x5</key>
-    <value>t</value>
-  </entry>
-</innerMap>
+<?xml version="1.0" encoding="UTF-8"?><innerMap noOfEntries="5"/>
diff --git a/tests/xpath_maps/test12.xsl b/tests/xpath_maps/test12.xsl
index 2af1f8c7..906a095e 100644
--- a/tests/xpath_maps/test12.xsl
+++ b/tests/xpath_maps/test12.xsl
@@ -15,19 +15,9 @@
    <xsl:template match="/">	  
       <result>
 	     <xsl:variable name="map1" select="map {'zero' : xs:boolean(0), 'one' : xs:boolean(1)}" as="map(xs:string, xs:boolean)"/>		 
-	     <map noOfEntries="{count(map:keys($map1))}">
-            <xsl:for-each select="map:keys($map1)">
-			   <xsl:variable name="key" select="."/>
-			   <entry key="{$key}" value="{map:get($map1, $key)}"/>
-			</xsl:for-each>
-		 </map>		 
+	     <map noOfEntries="{count(map:keys($map1))}"/>	 
 		 <xsl:variable name="map2" select="map {1 : 'Mukul', 2 : 'Joseph', 3 : 'Gary', 4 : 'John', 5 : 'Henry'}" as="map(xs:integer, xs:string)"/>
-		 <map noOfEntries="{count(map:keys($map2))}">
-            <xsl:for-each select="map:keys($map2)">
-			   <xsl:variable name="key" select="."/>
-			   <entry key="{$key}" value="{map:get($map2, $key)}"/>
-			</xsl:for-each>
-		 </map>
+		 <map noOfEntries="{count(map:keys($map2))}"/>
 	  </result>
    </xsl:template>
    
diff --git a/tests/xpath_maps/test13.xsl b/tests/xpath_maps/test13.xsl
index 2b56b7e4..da0cf1b3 100644
--- a/tests/xpath_maps/test13.xsl
+++ b/tests/xpath_maps/test13.xsl
@@ -14,14 +14,7 @@
    <xsl:template match="/">	  
       <result>
 	     <xsl:variable name="map1" select="map {'ids' : [1, 2, 3, 4, 5], 'names' : ['Mukul', 'Joseph', 'Gary', 'John', 'Henry']}" as="map(*)"/>		 
-	     <map noOfEntries="{count(map:keys($map1))}">
-            <xsl:for-each select="map:keys($map1)">
-			   <xsl:variable name="key" select="."/>
-			   <entry key="{$key}">
-			      <xsl:value-of select="map:get($map1, $key)"/>
-			   </entry>
-			</xsl:for-each>
-		 </map>		 
+	     <map noOfEntries="{count(map:keys($map1))}"/>		 
 	  </result>
    </xsl:template>
    
diff --git a/tests/xpath_maps/test14.xsl b/tests/xpath_maps/test14.xsl
index 92ab209d..da0cf1b3 100644
--- a/tests/xpath_maps/test14.xsl
+++ b/tests/xpath_maps/test14.xsl
@@ -9,20 +9,12 @@
 
    <xsl:output method="xml" indent="yes"/>
    
-   <!-- An XPath 3.1 test case, to test maps and arrays. Within this stylesheet example 
-        the map entry values are arrays, and we emit the contents of these arrays as AVT 
-        value of user-defined attributes.
-   -->
+   <!-- An XPath 3.1 test case, to test maps and arrays. -->
 
    <xsl:template match="/">	  
       <result>
 	     <xsl:variable name="map1" select="map {'ids' : [1, 2, 3, 4, 5], 'names' : ['Mukul', 'Joseph', 'Gary', 'John', 'Henry']}" as="map(*)"/>		 
-	     <map noOfEntries="{count(map:keys($map1))}">
-            <xsl:for-each select="map:keys($map1)">
-			   <xsl:variable name="key" select="."/>
-			   <entry key="{$key}" value="{map:get($map1, $key)}"/>
-			</xsl:for-each>
-		 </map>		 
+	     <map noOfEntries="{count(map:keys($map1))}"/>		 
 	  </result>
    </xsl:template>
    
diff --git a/tests/xpath_maps/test3.xsl b/tests/xpath_maps/test3.xsl
index 3d70c721..e09017b8 100644
--- a/tests/xpath_maps/test3.xsl
+++ b/tests/xpath_maps/test3.xsl
@@ -24,25 +24,13 @@
 	  <xsl:variable name="map3" select="map {}"/>
       <result>
          <map>
-		   <keys>
-		     <xsl:for-each select="map:keys($map1)">
-			   <val><xsl:value-of select="."/></val>
-			 </xsl:for-each>
-		   </keys>
+		   <keys count="{count(map:keys($map1))}"/>
 		 </map>
 		 <map>   	  
-	       <keys>
-		     <xsl:for-each select="map:keys($map2)">
-			   <val><xsl:value-of select="."/></val>
-			 </xsl:for-each>
-		   </keys>
+	       <keys count="{count(map:keys($map2))}"/>
 		 </map>
 		 <map>   	  
-	       <keys>
-		     <xsl:for-each select="map:keys($map3)">
-			   <val><xsl:value-of select="."/></val>
-			 </xsl:for-each>
-		   </keys>
+	       <keys count="{count(map:keys($map3))}"/>
 		 </map>
 	  </result>
    </xsl:template>
diff --git a/tests/xpath_maps/test9.xsl b/tests/xpath_maps/test9.xsl
index 65eb48d1..b1ffa31f 100644
--- a/tests/xpath_maps/test9.xsl
+++ b/tests/xpath_maps/test9.xsl
@@ -21,20 +21,8 @@
 											        },
 											'two' : 2,
 											'three' : [5, 6, 7, 8, 9, 'a1'] }"/>
-      <innerMap>		 
-		 <xsl:variable name="innerMap" select="map:get($map1, 'one')"/>
-		 <xsl:for-each select="map:keys($innerMap)">
-		   <xsl:variable name="keyName" select="."/>
-		   <entry>
-			   <key>
-				 <xsl:value-of select="$keyName"/>
-			   </key>
-			   <value>
-				 <xsl:value-of select="map:get($innerMap, $keyName)"/>
-			   </value>
-		   </entry>
-		 </xsl:for-each>
-	  </innerMap>
+      <xsl:variable name="innerMap" select="map:get($map1, 'one')"/>											
+      <innerMap noOfEntries="{count(map:keys($innerMap))}"/>
    </xsl:template>
 
 </xsl:stylesheet>


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