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/23 06:16:25 UTC
(xalan-java) branch xalan-j_xslt3.0 updated: Committing implementation, of xpath 3.1's SequenceType for xpath map expressions, along with few new relevant working test cases
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 05dae167 Committing implementation, of xpath 3.1's SequenceType for xpath map expressions, along with few new relevant working test cases
05dae167 is described below
commit 05dae1678788e7225b5726cab1046c3ea04890e9
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Thu May 23 11:46:07 2024 +0530
Committing implementation, of xpath 3.1's SequenceType for xpath map expressions, along with few new relevant working test cases
---
src/org/apache/xalan/templates/ElemVariable.java | 20 +-
src/org/apache/xpath/compiler/XPathParserImpl.java | 257 ++++++++++++++++++++-
.../apache/xpath/composite/SequenceTypeData.java | 10 +
.../xpath/composite/SequenceTypeFunctionTest.java | 2 +-
...eFunctionTest.java => SequenceTypeMapTest.java} | 44 ++--
.../xpath/composite/SequenceTypeSupport.java | 49 +++-
.../xpath/composite/XPathSequenceTypeExpr.java | 15 +-
tests/org/apache/xalan/xpath3/XPathMapTests.java | 30 +++
tests/xpath_maps/gold/test10.out | 1 +
tests/xpath_maps/gold/test11.out | 1 +
tests/xpath_maps/gold/test12.out | 13 ++
tests/xpath_maps/test10.xsl | 40 ++++
tests/xpath_maps/test11.xsl | 40 ++++
tests/xpath_maps/test12.xsl | 34 +++
tests/xpath_maps/test8.xsl | 4 +-
15 files changed, 522 insertions(+), 38 deletions(-)
diff --git a/src/org/apache/xalan/templates/ElemVariable.java b/src/org/apache/xalan/templates/ElemVariable.java
index 02383a71..221770a5 100644
--- a/src/org/apache/xalan/templates/ElemVariable.java
+++ b/src/org/apache/xalan/templates/ElemVariable.java
@@ -44,6 +44,7 @@ import org.apache.xpath.objects.XNodeSet;
import org.apache.xpath.objects.XNodeSetForDOM;
import org.apache.xpath.objects.XNumber;
import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XPathMap;
import org.apache.xpath.objects.XRTreeFrag;
import org.apache.xpath.objects.XRTreeFragSelectWrapper;
import org.apache.xpath.objects.XString;
@@ -609,7 +610,24 @@ public class ElemVariable extends ElemTemplateElement
else {
var = SequenceTypeSupport.convertXDMValueToAnotherType(var, m_asAttr, null, xctxt);
}
- }
+ }
+ else if (var instanceof XPathMap) {
+ try {
+ var = SequenceTypeSupport.convertXDMValueToAnotherType(var, m_asAttr, null, xctxt);
+ }
+ catch (TransformerException ex) {
+ String errMesg = ex.getMessage();
+ boolean indicatorOne = errMesg.contains("The string value");
+ boolean indicatorTwo = errMesg.contains("cannot be cast to a type");
+ if (indicatorOne && indicatorTwo) {
+ errMesg = errMesg + " An error occured, while evaluating xdm map's key or value [map's sequenceType is '" + m_asAttr + "'].";
+ throw new TransformerException(errMesg, srcLocator);
+ }
+ else {
+ throw new TransformerException(errMesg, srcLocator);
+ }
+ }
+ }
else {
var = SequenceTypeSupport.convertXDMValueToAnotherType(var, m_asAttr, null, xctxt);
}
diff --git a/src/org/apache/xpath/compiler/XPathParserImpl.java b/src/org/apache/xpath/compiler/XPathParserImpl.java
index dd6f8f07..6b19bd47 100644
--- a/src/org/apache/xpath/compiler/XPathParserImpl.java
+++ b/src/org/apache/xpath/compiler/XPathParserImpl.java
@@ -44,6 +44,7 @@ import org.apache.xpath.composite.QuantifiedExpr;
import org.apache.xpath.composite.SequenceTypeData;
import org.apache.xpath.composite.SequenceTypeFunctionTest;
import org.apache.xpath.composite.SequenceTypeKindTest;
+import org.apache.xpath.composite.SequenceTypeMapTest;
import org.apache.xpath.composite.SequenceTypeSupport;
import org.apache.xpath.composite.XPathSequenceConstructor;
import org.apache.xpath.composite.SquareArrayConstructor;
@@ -57,8 +58,16 @@ import org.apache.xpath.objects.XString;
import org.apache.xpath.res.XPATHErrorResources;
/**
- * Tokenizes and parses XPath expressions, as specified by
- * XPath 3.1 spec.
+ * Tokenizes and parses XPath expressions.
+ *
+ * Author: Scott Boag,
+ * Myriam Midy,
+ * Joseph Kesselman
+ *
+ * @modification notes: Mukul Gandhi
+ * XalanJ's XPath 1.0 implementation class XPathParser has been renamed to
+ * XPathParserImpl, with modifications/additions to implement XPath 3.1 grammar
+ * to produce the present form of this class.
*
* @xsl.usage general
*/
@@ -1137,7 +1146,7 @@ public class XPathParserImpl
* @throws javax.xml.transform.TransformerException
*/
protected void Expr() throws javax.xml.transform.TransformerException
- {
+ {
if (fIsBeginParse && (tokenIs("(") || tokenIs("["))) {
boolean isSquareArrayConstructor = false;
if (tokenIs("[")) {
@@ -1300,13 +1309,18 @@ public class XPathParserImpl
else if (fIsBeginParse && tokenIs("map")) {
// Parse an XPath "map" expression
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
+
+ if (fIsSequenceTypeXPathExpr) {
+ fXpathSequenceTypeExpr = SequenceTypeExpr(false);
+ return;
+ }
nextToken();
insertOp(opPos, 2, OpCodes.OP_MAP_CONSTRUCTOR_EXPR);
fMapConstructor = new MapConstructor();
- Map<String, String> nativeMapVar = new HashMap<String, String>();
+ Map<String, String> nativeMapVar = new HashMap<String, String>();
consumeExpected('{');
@@ -1329,13 +1343,28 @@ public class XPathParserImpl
else {
// The map's key value here is a simple value (i.e, not an array or
// map).
- mapValueExprStr = m_token;
+ mapValueExprStr = m_token;
+ while (!(tokenIs(',') || tokenIs('}'))) {
+ nextToken();
+ if (!(tokenIs(',') || tokenIs('}'))) {
+ mapValueExprStr += m_token;
+ }
+ }
}
nativeMapVar.put(mapKeyExprStr, mapValueExprStr);
- nextToken();
if (tokenIs(',')) {
consumeExpected(',');
}
+ else if (tokenIs(']')) {
+ consumeExpected(']');
+ if (tokenIs(',')) {
+ consumeExpected(',');
+ }
+ else if (tokenIs('}')) {
+ consumeExpected('}');
+ break;
+ }
+ }
else if (tokenIs('}')) {
consumeExpected('}');
break;
@@ -1469,7 +1498,8 @@ public class XPathParserImpl
}
/**
- * Get the count of a specific character within a string.
+ * Get the count of specified character within
+ * a string.
*/
private int countCharInStr(String str, char cVal) {
int count = 0;
@@ -4145,7 +4175,7 @@ public class XPathParserImpl
SequenceTypeFunctionTest sequenceTypeFunctionTest = null;
if (lookahead('(', 1) && lookahead('*', 2) && lookahead(')', 3)) {
- // Handles FunctionTest of variety AnyFunctionTest
+ // handles FunctionTest of variety AnyFunctionTest
sequenceTypeFunctionTest = new SequenceTypeFunctionTest();
sequenceTypeFunctionTest.setIsAnyFunctionTest(true);
nextToken();
@@ -4155,7 +4185,7 @@ public class XPathParserImpl
xpathSequenceTypeExpr.setSequenceTypeFunctionTest(sequenceTypeFunctionTest);
}
else {
- // Handles FunctionTest of variety TypedFunctionTest
+ // handles FunctionTest of variety TypedFunctionTest
sequenceTypeFunctionTest = new SequenceTypeFunctionTest();
nextToken();
consumeExpected('(');
@@ -4222,6 +4252,215 @@ public class XPathParserImpl
xpathSequenceTypeExpr.setSequenceTypeFunctionTest(sequenceTypeFunctionTest);
}
}
+ else if (tokenIs("map")) {
+ SequenceTypeMapTest sequenceTypeMapTest = null;
+
+ if (lookahead('(', 1) && lookahead('*', 2) && lookahead(')', 3)) {
+ // handles MapTest of variety AnyMapTest
+ sequenceTypeMapTest = new SequenceTypeMapTest();
+ sequenceTypeMapTest.setIsAnyMapTest(true);
+ nextToken();
+ consumeExpected('(');
+ consumeExpected('*');
+ consumeExpected(')');
+ xpathSequenceTypeExpr.setSequenceTypeMapTest(sequenceTypeMapTest);
+ }
+ else {
+ // handles MapTest of variety TypedMapTest
+ sequenceTypeMapTest = new SequenceTypeMapTest();
+ nextToken();
+ consumeExpected('(');
+ /*String mapEntryKeyTypeStr = "";
+ String mapEntryValueTypeStr = "";
+ consumeExpected('(');
+ while (m_token != null) {
+ while (!tokenIs(',')) {
+ mapEntryKeyTypeStr += m_token;
+ nextToken();
+ }
+ consumeExpected(',');
+ while (!tokenIs(')')) {
+ mapEntryValueTypeStr += m_token;
+ nextToken();
+ }
+ consumeExpected(')');
+ }*/
+
+ SequenceTypeData keySequenceTypeData = new SequenceTypeData();
+ SequenceTypeData valueSequenceTypeData = new SequenceTypeData();
+
+ while ((m_token != null) && !tokenIs(',')) {
+ if (tokenIs(XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
+ consumeExpected(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ consumeExpected(':');
+
+ switch (m_token) {
+ case Keywords.FUNC_BOOLEAN_STRING :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.BOOLEAN);
+ break;
+ case Keywords.XS_STRING :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.STRING);
+ break;
+ case Keywords.XS_NORMALIZED_STRING :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_NORMALIZED_STRING);
+ break;
+ case Keywords.XS_TOKEN :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_TOKEN);
+ break;
+ case Keywords.XS_DECIMAL :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DECIMAL);
+ break;
+ case Keywords.XS_FLOAT :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_FLOAT);
+ break;
+ case Keywords.XS_DOUBLE :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DOUBLE);
+ break;
+ case Keywords.XS_INTEGER :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_INTEGER);
+ break;
+ case Keywords.XS_LONG :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_LONG);
+ break;
+ case Keywords.XS_INT :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_INT);
+ break;
+ case Keywords.XS_DATE :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DATE);
+ break;
+ case Keywords.XS_DATETIME :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DATETIME);
+ break;
+ case Keywords.XS_DURATION :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DURATION);
+ break;
+ case Keywords.XS_YEAR_MONTH_DURATION :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_YEARMONTH_DURATION);
+ break;
+ case Keywords.XS_DAY_TIME_DURATION :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DAYTIME_DURATION);
+ break;
+ case Keywords.XS_TIME :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_TIME);
+ break;
+ case Keywords.XS_ANY_URI :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_ANY_URI);
+ break;
+ case Keywords.XS_QNAME :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_QNAME);
+ break;
+ case Keywords.XS_ANY_ATOMIC_TYPE :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_ANY_ATOMIC_TYPE);
+ break;
+ case Keywords.XS_UNTYPED_ATOMIC :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_UNTYPED_ATOMIC);
+ break;
+ case Keywords.XS_UNTYPED :
+ keySequenceTypeData.setSequenceType(SequenceTypeSupport.XS_UNTYPED);
+ break;
+ default :
+ throw new javax.xml.transform.TransformerException("XPST0051 : An XML Schema type 'xs:" + m_token + "' is not "
+ + "recognized, within the provided sequence type expression.");
+ }
+
+ nextToken();
+ }
+ }
+
+ consumeExpected(',');
+
+ while ((m_token != null) && !tokenIs(')')) {
+ if (tokenIs(XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
+ consumeExpected(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ consumeExpected(':');
+
+ switch (m_token) {
+ case Keywords.FUNC_BOOLEAN_STRING :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.BOOLEAN);
+ break;
+ case Keywords.XS_STRING :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.STRING);
+ break;
+ case Keywords.XS_NORMALIZED_STRING :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_NORMALIZED_STRING);
+ break;
+ case Keywords.XS_TOKEN :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_TOKEN);
+ break;
+ case Keywords.XS_DECIMAL :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DECIMAL);
+ break;
+ case Keywords.XS_FLOAT :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_FLOAT);
+ break;
+ case Keywords.XS_DOUBLE :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DOUBLE);
+ break;
+ case Keywords.XS_INTEGER :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_INTEGER);
+ break;
+ case Keywords.XS_LONG :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_LONG);
+ break;
+ case Keywords.XS_INT :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_INT);
+ break;
+ case Keywords.XS_DATE :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DATE);
+ break;
+ case Keywords.XS_DATETIME :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DATETIME);
+ break;
+ case Keywords.XS_DURATION :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DURATION);
+ break;
+ case Keywords.XS_YEAR_MONTH_DURATION :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_YEARMONTH_DURATION);
+ break;
+ case Keywords.XS_DAY_TIME_DURATION :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_DAYTIME_DURATION);
+ break;
+ case Keywords.XS_TIME :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_TIME);
+ break;
+ case Keywords.XS_ANY_URI :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_ANY_URI);
+ break;
+ case Keywords.XS_QNAME :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_QNAME);
+ break;
+ case Keywords.XS_ANY_ATOMIC_TYPE :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_ANY_ATOMIC_TYPE);
+ break;
+ case Keywords.XS_UNTYPED_ATOMIC :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_UNTYPED_ATOMIC);
+ break;
+ case Keywords.XS_UNTYPED :
+ valueSequenceTypeData.setSequenceType(SequenceTypeSupport.XS_UNTYPED);
+ break;
+ default :
+ throw new javax.xml.transform.TransformerException("XPST0051 : An XML Schema type 'xs:" + m_token + "' is not "
+ + "recognized, within the provided sequence type expression.");
+ }
+
+ nextToken();
+
+ /*if (m_token != null) {
+ if (!tokenIs(')') && (valueSequenceTypeData.getSequenceType() > 0)) {
+ setSequenceTypeOccurenceIndicator(valueSequenceTypeExpr, isInlineFunction);
+ }
+ }*/
+
+ consumeExpected(')');
+ }
+ }
+
+ sequenceTypeMapTest.setKeySequenceTypeData(keySequenceTypeData);
+ sequenceTypeMapTest.setValueSequenceTypeData(valueSequenceTypeData);
+
+ xpathSequenceTypeExpr.setSequenceTypeMapTest(sequenceTypeMapTest);
+ }
+ }
else {
throw new javax.xml.transform.TransformerException("XPST0051 The sequence type '" + m_token + "' is not "
+ "recognized, within the provided sequence type expression.");
diff --git a/src/org/apache/xpath/composite/SequenceTypeData.java b/src/org/apache/xpath/composite/SequenceTypeData.java
index ff9d0cbc..0bbe7590 100644
--- a/src/org/apache/xpath/composite/SequenceTypeData.java
+++ b/src/org/apache/xpath/composite/SequenceTypeData.java
@@ -42,6 +42,8 @@ public class SequenceTypeData extends XObject {
private SequenceTypeKindTest sequenceTypeKindTest;
private SequenceTypeFunctionTest fSequenceTypeFunctionTest;
+
+ private SequenceTypeMapTest fSequenceTypeMapTest;
public int getSequenceType() {
return fSequenceType;
@@ -75,6 +77,14 @@ public class SequenceTypeData extends XObject {
this.fSequenceTypeFunctionTest = sequenceTypeFunctionTest;
}
+ public SequenceTypeMapTest getSequenceTypeMapTest() {
+ return fSequenceTypeMapTest;
+ }
+
+ public void setSequenceTypeMapTest(SequenceTypeMapTest sequenceTypeMapTest) {
+ this.fSequenceTypeMapTest = sequenceTypeMapTest;
+ }
+
/**
* Check whether, one SequenceTypeData object is functionally
* equal to another SequenceTypeData object.
diff --git a/src/org/apache/xpath/composite/SequenceTypeFunctionTest.java b/src/org/apache/xpath/composite/SequenceTypeFunctionTest.java
index 2cabb919..ca773b14 100644
--- a/src/org/apache/xpath/composite/SequenceTypeFunctionTest.java
+++ b/src/org/apache/xpath/composite/SequenceTypeFunctionTest.java
@@ -20,7 +20,7 @@ import java.util.List;
/**
* An object of this class stores, an XSLT transformation run-time
- * information for an occurrence of a XPath 3.1 sequence type
+ * information for an occurrence of a XPath 3.1 sequence type
* FunctionTest.
*
* @author Mukul Gandhi <mu...@apache.org>
diff --git a/src/org/apache/xpath/composite/SequenceTypeFunctionTest.java b/src/org/apache/xpath/composite/SequenceTypeMapTest.java
similarity index 52%
copy from src/org/apache/xpath/composite/SequenceTypeFunctionTest.java
copy to src/org/apache/xpath/composite/SequenceTypeMapTest.java
index 2cabb919..b9dd601d 100644
--- a/src/org/apache/xpath/composite/SequenceTypeFunctionTest.java
+++ b/src/org/apache/xpath/composite/SequenceTypeMapTest.java
@@ -16,47 +16,49 @@
*/
package org.apache.xpath.composite;
-import java.util.List;
-
/**
* An object of this class stores, an XSLT transformation run-time
- * information for an occurrence of a XPath 3.1 sequence type
- * FunctionTest.
+ * information for an occurrence of a XPath 3.1 sequence type
+ * MapTest.
*
* @author Mukul Gandhi <mu...@apache.org>
*
* @xsl.usage advanced
*/
-public class SequenceTypeFunctionTest {
+public class SequenceTypeMapTest {
- private boolean fIsAnyFunctionTest;
+ private boolean fIsAnyMapTest;
- private List<String> typedFunctionTestPrefixList;
+ private SequenceTypeData keySequenceTypeData;
- private String typedFunctionTestReturnType;
+ private SequenceTypeData valueSequenceTypeData;
- public boolean isAnyFunctionTest() {
- return fIsAnyFunctionTest;
+ public boolean isfIsAnyMapTest() {
+ return fIsAnyMapTest;
}
- public void setIsAnyFunctionTest(boolean isAnyFunctionTest) {
- this.fIsAnyFunctionTest = isAnyFunctionTest;
+ public boolean getIsAnyMapTest() {
+ return fIsAnyMapTest;
+ }
+
+ public void setIsAnyMapTest(boolean isAnyMapTest) {
+ this.fIsAnyMapTest = isAnyMapTest;
}
- public List<String> getTypedFunctionTestPrefixList() {
- return typedFunctionTestPrefixList;
+ public SequenceTypeData getKeySequenceTypeData() {
+ return keySequenceTypeData;
}
- public void setTypedFunctionTestPrefixList(List<String> typedFunctionTestPrefix) {
- this.typedFunctionTestPrefixList = typedFunctionTestPrefix;
+ public void setKeySequenceTypeData(SequenceTypeData keySequenceTypeData) {
+ this.keySequenceTypeData = keySequenceTypeData;
}
- public String getTypedFunctionTestReturnType() {
- return typedFunctionTestReturnType;
+ public SequenceTypeData getValueSequenceTypeData() {
+ return valueSequenceTypeData;
}
- public void setTypedFunctionTestReturnType(String typedFunctionTestReturnType) {
- this.typedFunctionTestReturnType = typedFunctionTestReturnType;
- }
+ public void setValueSequenceTypeData(SequenceTypeData valueSequenceTypeData) {
+ this.valueSequenceTypeData = valueSequenceTypeData;
+ }
}
diff --git a/src/org/apache/xpath/composite/SequenceTypeSupport.java b/src/org/apache/xpath/composite/SequenceTypeSupport.java
index 210ece51..783b8909 100644
--- a/src/org/apache/xpath/composite/SequenceTypeSupport.java
+++ b/src/org/apache/xpath/composite/SequenceTypeSupport.java
@@ -17,7 +17,10 @@
package org.apache.xpath.composite;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;
@@ -37,6 +40,7 @@ import org.apache.xpath.objects.XNodeSet;
import org.apache.xpath.objects.XNodeSetForDOM;
import org.apache.xpath.objects.XNumber;
import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XPathMap;
import org.apache.xpath.objects.XString;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -234,7 +238,7 @@ public class SequenceTypeSupport {
XObject seqTypeExpressionEvalResult = null;
SequenceTypeData seqExpectedTypeData = null;
- if (xctxt != null) {
+ if ((xctxt != null) && (sequenceTypeXPathExprStr != null) && (seqExpectedTypeDataInp == null)) {
seqTypeXPath = new XPath(sequenceTypeXPathExprStr, srcLocator,
xctxt.getNamespaceContext(), XPath.SELECT, null, true);
@@ -317,7 +321,7 @@ public class SequenceTypeSupport {
xsNumericType.stringType(), sequenceTypeXPathExprStr);
}
catch (TransformerException ex2) {
- throw ex2;
+ throw ex2;
}
}
else {
@@ -492,6 +496,47 @@ public class SequenceTypeSupport {
}
}
}
+ else if (srcValue instanceof XPathMap) {
+ SequenceTypeMapTest sequenceTypeMapTest = seqExpectedTypeData.getSequenceTypeMapTest();
+ if (sequenceTypeMapTest != null) {
+ if (sequenceTypeMapTest.isfIsAnyMapTest()) {
+ result = srcValue;
+ }
+ else {
+ XPathMap xpathMap = (XPathMap)srcValue;
+ Map<XObject, XObject> nativeMap = xpathMap.getNativeMap();
+ Set<XObject> mapKeys = nativeMap.keySet();
+ Iterator<XObject> keysIter = mapKeys.iterator();
+ // We check below each of map's entry, with expected type of map entry's keys and values
+ while (keysIter.hasNext()) {
+ XObject mapKey = keysIter.next();
+ XObject mapEntry = nativeMap.get(mapKey);
+ String keyStrVal = XslTransformEvaluationHelper.getStrVal(mapKey);
+ if (mapKey instanceof ResultSequence) {
+ mapKey = ((ResultSequence)mapKey).item(0);
+ }
+ if (mapEntry instanceof ResultSequence) {
+ mapEntry = ((ResultSequence)mapEntry).item(0);
+ }
+ SequenceTypeData keySeqTypeData = sequenceTypeMapTest.getKeySequenceTypeData();
+ SequenceTypeData valueSeqTypeData = sequenceTypeMapTest.getValueSequenceTypeData();
+ XObject mapKeyValTypeCheckResult = SequenceTypeSupport.convertXDMValueToAnotherType(mapKey, null, keySeqTypeData, xctxt);
+ String mapSequenceTypeStr = (sequenceTypeXPathExprStr != null) ? sequenceTypeXPathExprStr : "";
+ if (mapKeyValTypeCheckResult == null) {
+ throw new TransformerException("XPTY0004 : XPath map entry key's [entry's key name: '" + keyStrVal + "'] value doesn't conform to the key's expected "
+ + "type [map's sequenceType is '" + mapSequenceTypeStr + "'].");
+ }
+ XObject mapEntryValTypeCheckResult = SequenceTypeSupport.convertXDMValueToAnotherType(mapEntry, null, valueSeqTypeData, xctxt);
+ if (mapEntryValTypeCheckResult == null) {
+ throw new TransformerException("XPTY0004 : XPath map entry's [entry's key name: '" + keyStrVal + "'] value doesn't conform to the map entry value's expected "
+ + "type [map's sequenceType is '" + mapSequenceTypeStr + "'].");
+ }
+ }
+
+ result = srcValue;
+ }
+ }
+ }
}
catch (TransformerException ex) {
if (ex.getLocator() != null) {
diff --git a/src/org/apache/xpath/composite/XPathSequenceTypeExpr.java b/src/org/apache/xpath/composite/XPathSequenceTypeExpr.java
index bb64bc6d..740cb074 100644
--- a/src/org/apache/xpath/composite/XPathSequenceTypeExpr.java
+++ b/src/org/apache/xpath/composite/XPathSequenceTypeExpr.java
@@ -45,6 +45,8 @@ public class XPathSequenceTypeExpr extends Expression {
private SequenceTypeKindTest fSequenceTypeKindTest;
private SequenceTypeFunctionTest fSequenceTypeFunctionTest;
+
+ private SequenceTypeMapTest fSequenceTypeMapTest;
@Override
public XObject execute(XPathContext xctxt) throws TransformerException {
@@ -54,6 +56,7 @@ public class XPathSequenceTypeExpr extends Expression {
sequenceTypeData.setSequenceTypeKindTest(fSequenceTypeKindTest);
sequenceTypeData.setItemTypeOccurrenceIndicator(fItemTypeOccurrenceIndicator);
sequenceTypeData.setSequenceTypeFunctionTest(fSequenceTypeFunctionTest);
+ sequenceTypeData.setSequenceTypeMapTest(fSequenceTypeMapTest);
return sequenceTypeData;
}
@@ -97,8 +100,16 @@ public class XPathSequenceTypeExpr extends Expression {
return fSequenceTypeFunctionTest;
}
- public void setSequenceTypeFunctionTest(SequenceTypeFunctionTest fSequenceTypeFunctionTest) {
- this.fSequenceTypeFunctionTest = fSequenceTypeFunctionTest;
+ public void setSequenceTypeFunctionTest(SequenceTypeFunctionTest sequenceTypeFunctionTest) {
+ this.fSequenceTypeFunctionTest = sequenceTypeFunctionTest;
+ }
+
+ public SequenceTypeMapTest getSequenceTypeMapTest() {
+ return fSequenceTypeMapTest;
+ }
+
+ public void setSequenceTypeMapTest(SequenceTypeMapTest sequenceTypeMapTest) {
+ this.fSequenceTypeMapTest = sequenceTypeMapTest;
}
@Override
diff --git a/tests/org/apache/xalan/xpath3/XPathMapTests.java b/tests/org/apache/xalan/xpath3/XPathMapTests.java
index 5a9cecbb..23351c25 100644
--- a/tests/org/apache/xalan/xpath3/XPathMapTests.java
+++ b/tests/org/apache/xalan/xpath3/XPathMapTests.java
@@ -137,5 +137,35 @@ public class XPathMapTests extends XSLTransformTestsUtil {
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
}
+
+ @Test
+ public void xslMapTest10() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test10.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test10.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test10.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslMapTest11() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test11.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test11.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test11.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslMapTest12() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test12.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test12.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test12.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
}
diff --git a/tests/xpath_maps/gold/test10.out b/tests/xpath_maps/gold/test10.out
new file mode 100644
index 00000000..db07d8ce
--- /dev/null
+++ b/tests/xpath_maps/gold/test10.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>2</result>
diff --git a/tests/xpath_maps/gold/test11.out b/tests/xpath_maps/gold/test11.out
new file mode 100644
index 00000000..db07d8ce
--- /dev/null
+++ b/tests/xpath_maps/gold/test11.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>2</result>
diff --git a/tests/xpath_maps/gold/test12.out b/tests/xpath_maps/gold/test12.out
new file mode 100644
index 00000000..b5679d9c
--- /dev/null
+++ b/tests/xpath_maps/gold/test12.out
@@ -0,0 +1,13 @@
+<?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>
+</result>
diff --git a/tests/xpath_maps/test10.xsl b/tests/xpath_maps/test10.xsl
new file mode 100644
index 00000000..dfdea04a
--- /dev/null
+++ b/tests/xpath_maps/test10.xsl
@@ -0,0 +1,40 @@
+<?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">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <!-- An XPath 3.1 test case, to test map constructor expression
+ and the associated map functions. -->
+
+ <xsl:template match="/">
+ <xsl:variable name="map1" select="map {'true' : xs:boolean(1), 'false' : xs:boolean(0)}"/>
+ <result>
+ <xsl:value-of select="count(map:keys($map1))"/>
+ </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/test11.xsl b/tests/xpath_maps/test11.xsl
new file mode 100644
index 00000000..f938577a
--- /dev/null
+++ b/tests/xpath_maps/test11.xsl
@@ -0,0 +1,40 @@
+<?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">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <!-- An XPath 3.1 test case, to test SequenceType MapTest specified as
+ value of xsl:variable's "as" attribute. -->
+
+ <xsl:template match="/">
+ <xsl:variable name="map1" select="map {'true' : xs:boolean(1), 'false' : xs:boolean(0)}" as="map(*)"/>
+ <result>
+ <xsl:value-of select="count(map:keys($map1))"/>
+ </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/test12.xsl b/tests/xpath_maps/test12.xsl
new file mode 100644
index 00000000..d8d1e9e5
--- /dev/null
+++ b/tests/xpath_maps/test12.xsl
@@ -0,0 +1,34 @@
+<?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">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <!-- An XPath 3.1 test case, to test SequenceType MapTest specified as
+ value of xsl:variable's "as" attribute. -->
+
+ <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>
+ <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>
+ </result>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tests/xpath_maps/test8.xsl b/tests/xpath_maps/test8.xsl
index 98303d31..265d7359 100644
--- a/tests/xpath_maps/test8.xsl
+++ b/tests/xpath_maps/test8.xsl
@@ -28,8 +28,8 @@
'one' : map {
'x1' : 'p',
'x2' : 'q',
- 'x3' : 'r'
- 'x4' : 's'
+ 'x3' : 'r',
+ 'x4' : 's',
'x5' : 't'
},
'two' : 2,
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org