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