You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mu...@apache.org on 2023/08/30 12:47:13 UTC
[xalan-java] branch xalan-j_xslt3.0 updated: committing improvements to the use of xml schema data types xs:duration, xs:yearMonthDuration, xs:dayTimeDuration within xpath 3.1 implementation. also committing improvements to the implementation of xpath 3.1 functions fn:max, fn:min when using the xml schema data types xs:yearMonthDuration, xs:dayTimeDuration. also committing few new working related test cases as well.
This is an automated email from the ASF dual-hosted git repository.
mukulg pushed a commit to branch xalan-j_xslt3.0
in repository https://gitbox.apache.org/repos/asf/xalan-java.git
The following commit(s) were added to refs/heads/xalan-j_xslt3.0 by this push:
new c7217abe committing improvements to the use of xml schema data types xs:duration, xs:yearMonthDuration, xs:dayTimeDuration within xpath 3.1 implementation. also committing improvements to the implementation of xpath 3.1 functions fn:max, fn:min when using the xml schema data types xs:yearMonthDuration, xs:dayTimeDuration. also committing few new working related test cases as well.
new 04989dd9 Merge pull request #70 from mukulga/xalan-j_xslt3.0_mukul
c7217abe is described below
commit c7217abe8842d475e358374657328fc4291d24d1
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Wed Aug 30 18:10:09 2023 +0530
committing improvements to the use of xml schema data types xs:duration, xs:yearMonthDuration, xs:dayTimeDuration within xpath 3.1 implementation. also committing improvements to the implementation of xpath 3.1 functions fn:max, fn:min when using the xml schema data types xs:yearMonthDuration, xs:dayTimeDuration. also committing few new working related test cases as well.
---
.../xalan/templates/XSConstructorFunctionUtil.java | 296 +++++++++++----------
src/org/apache/xpath/compiler/Keywords.java | 3 +
src/org/apache/xpath/functions/FuncMax.java | 68 ++++-
src/org/apache/xpath/functions/FuncMin.java | 70 ++++-
.../apache/xpath/xs/types/XSDayTimeDuration.java | 108 ++++++++
src/org/apache/xpath/xs/types/XSDuration.java | 128 +++++++--
.../apache/xpath/xs/types/XSYearMonthDuration.java | 138 +++++++---
tests/fn_max/gold/test3.out | 1 +
tests/fn_max/gold/test4.out | 1 +
tests/fn_max/gold/test5.out | 1 +
tests/fn_max/test1_b.xml | 5 +
tests/fn_max/test3.xsl | 47 ++++
tests/fn_max/test4.xsl | 43 +++
tests/fn_max/test5.xsl | 43 +++
tests/fn_min/gold/test3.out | 1 +
tests/fn_min/gold/test4.out | 1 +
tests/fn_min/test3.xsl | 43 +++
tests/fn_min/test4.xsl | 43 +++
tests/fn_sort/gold/test16.out | 32 +++
tests/fn_sort/test19.xsl | 57 ++++
tests/fn_sort/test1_i.xml | 10 +
tests/org/apache/xalan/xpath3/FnMaxTests.java | 30 +++
tests/org/apache/xalan/xpath3/FnMinTests.java | 20 ++
tests/org/apache/xalan/xpath3/FnSortTests.java | 10 +
24 files changed, 981 insertions(+), 218 deletions(-)
diff --git a/src/org/apache/xalan/templates/XSConstructorFunctionUtil.java b/src/org/apache/xalan/templates/XSConstructorFunctionUtil.java
index 2e44d4d9..be8e2a15 100644
--- a/src/org/apache/xalan/templates/XSConstructorFunctionUtil.java
+++ b/src/org/apache/xalan/templates/XSConstructorFunctionUtil.java
@@ -53,12 +53,9 @@ import org.xml.sax.SAXException;
*/
public class XSConstructorFunctionUtil {
- /*
- * Process an XPath expression of the type FuncExtFunction, XPath operation,
- * and also few default XPath expression processing.
- *
- * We use the XalanJ extension function evaluation mechanism, to evaluate
- * XPath 3.1 constructor functions.
+ /**
+ * Process an XPath expression of type FuncExtFunction, XPath operation,
+ * and also few XPath default expression processing.
*/
public static XObject processFuncExtFunctionOrXPathOpn(XPathContext xctxt, Expression expr)
throws TransformerException, SAXException {
@@ -66,144 +63,175 @@ public class XSConstructorFunctionUtil {
SourceLocator srcLocator = xctxt.getSAXLocator();
+ // XalanJ's extension function handler mechanism, treats at a syntactic level,
+ // XPath 3.1 constructor function calls like xs:type_name(..) as calls to XSLT/XPath
+ // extension functions. If the XML namespace of XSLT/XPath function calls is an XML Schema
+ // namespace, then we use this fact to treat such function calls as XPath 3.1 constructor
+ // function calls, as has been implemented within code below.
+
if (expr instanceof FuncExtFunction) {
FuncExtFunction funcExtFunction = (FuncExtFunction)expr;
+
if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(funcExtFunction.getNamespace())) {
- // evaluate XPath 3.1 constructor function calls, corresponding to XML Schema
- // built-in types.
+ // Handle as an XPath 3.1 constructor function call
- if ((Keywords.XS_STRING).equals(funcExtFunction.getFunctionName())) {
- ResultSequence argSequence = new ResultSequence();
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- argSequence.add(new XSString(XslTransformEvaluationHelper.getStrVal(argVal)));
- }
-
- ResultSequence rSeq = (new XSString()).constructor(argSequence);
- evalResult = rSeq.item(0);
- }
- else if ((Keywords.XS_DECIMAL).equals(funcExtFunction.getFunctionName())) {
- ResultSequence argSequence = new ResultSequence();
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- argSequence.add(new XSDecimal(XslTransformEvaluationHelper.getStrVal(argVal)));
- }
-
- ResultSequence rSeq = (new XSDecimal()).constructor(argSequence);
- evalResult = rSeq.item(0);
- }
- else if ((Keywords.XS_FLOAT).equals(funcExtFunction.getFunctionName())) {
- ResultSequence argSequence = new ResultSequence();
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- argSequence.add(new XSFloat(XslTransformEvaluationHelper.getStrVal(argVal)));
- }
-
- ResultSequence rSeq = (new XSFloat()).constructor(argSequence);
- evalResult = rSeq.item(0);
- }
- else if ((Keywords.XS_DOUBLE).equals(funcExtFunction.getFunctionName())) {
- ResultSequence argSequence = new ResultSequence();
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- argSequence.add(new XSDouble(XslTransformEvaluationHelper.getStrVal(argVal)));
- }
-
- ResultSequence rSeq = (new XSDouble()).constructor(argSequence);
- evalResult = rSeq.item(0);
- }
- else if ((Keywords.XS_INTEGER).equals(funcExtFunction.getFunctionName())) {
- ResultSequence argSequence = new ResultSequence();
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- argSequence.add(new XSInteger(XslTransformEvaluationHelper.getStrVal(argVal)));
- }
-
- ResultSequence rSeq = (new XSInteger()).constructor(argSequence);
- evalResult = rSeq.item(0);
- }
- else if ((Keywords.XS_LONG).equals(funcExtFunction.getFunctionName())) {
- ResultSequence argSequence = new ResultSequence();
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- argSequence.add(new XSLong(XslTransformEvaluationHelper.getStrVal(argVal)));
- }
-
- ResultSequence rSeq = (new XSLong()).constructor(argSequence);
- evalResult = rSeq.item(0);
- }
- else if ((Keywords.XS_INT).equals(funcExtFunction.getFunctionName())) {
- ResultSequence argSequence = new ResultSequence();
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- argSequence.add(new XSInt(XslTransformEvaluationHelper.getStrVal(argVal)));
- }
-
- ResultSequence rSeq = (new XSInt()).constructor(argSequence);
- evalResult = rSeq.item(0);
- }
- else if ((Keywords.FUNC_BOOLEAN_STRING).equals(funcExtFunction.getFunctionName())) {
- ResultSequence argSequence = new ResultSequence();
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- Boolean boolVal = Boolean.valueOf("0".equals(XslTransformEvaluationHelper.getStrVal(argVal)) ?
- "false" : "true");
- argSequence.add(new XSBoolean(boolVal));
- }
-
- ResultSequence rSeq = (new XSBoolean()).constructor(argSequence);
- evalResult = rSeq.item(0);
- }
- else if ((Keywords.XS_DATE).equals(funcExtFunction.getFunctionName())) {
- ResultSequence argSequence = new ResultSequence();
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- argSequence.add(XSDate.parseDate(XslTransformEvaluationHelper.getStrVal(argVal)));
- }
-
- ResultSequence rSeq = (new XSDate()).constructor(argSequence);
- evalResult = rSeq.item(0);
- }
- else if ((Keywords.XS_YEAR_MONTH_DURATION).equals(funcExtFunction.getFunctionName())) {
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- String strVal = XslTransformEvaluationHelper.getStrVal(argVal);
- XSDuration xsDuration = XSYearMonthDuration.parseYearMonthDuration(strVal);
- if (xsDuration != null) {
- ResultSequence argSequence = new ResultSequence();
- argSequence.add(xsDuration);
- ResultSequence rSeq = (new XSYearMonthDuration()).constructor(argSequence);
- evalResult = rSeq.item(0);
+ ResultSequence argSequence = new ResultSequence();
+ ResultSequence evalResultSequence = null;
+
+ switch (funcExtFunction.getFunctionName()) {
+ case Keywords.XS_STRING :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ argSequence.add(new XSString(XslTransformEvaluationHelper.getStrVal(argVal)));
+ }
+
+ evalResultSequence = (new XSString()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+
+ break;
+ case Keywords.XS_DECIMAL :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ argSequence.add(new XSDecimal(XslTransformEvaluationHelper.getStrVal(argVal)));
+ }
+
+ evalResultSequence = (new XSDecimal()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+
+ break;
+ case Keywords.XS_FLOAT :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ argSequence.add(new XSFloat(XslTransformEvaluationHelper.getStrVal(argVal)));
+ }
+
+ evalResultSequence = (new XSFloat()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+
+ break;
+ case Keywords.XS_DOUBLE :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ argSequence.add(new XSDouble(XslTransformEvaluationHelper.getStrVal(argVal)));
+ }
+
+ evalResultSequence = (new XSDouble()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+
+ break;
+ case Keywords.XS_INTEGER :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ argSequence.add(new XSInteger(XslTransformEvaluationHelper.getStrVal(argVal)));
+ }
+
+ evalResultSequence = (new XSInteger()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+
+ break;
+ case Keywords.XS_LONG :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ argSequence.add(new XSLong(XslTransformEvaluationHelper.getStrVal(argVal)));
+ }
+
+ evalResultSequence = (new XSLong()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+
+ break;
+ case Keywords.XS_INT :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ argSequence.add(new XSInt(XslTransformEvaluationHelper.getStrVal(argVal)));
+ }
+
+ evalResultSequence = (new XSInt()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+
+ break;
+ case Keywords.FUNC_BOOLEAN_STRING :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ Boolean boolVal = Boolean.valueOf("0".equals(XslTransformEvaluationHelper.getStrVal(argVal)) ?
+ "false" : "true");
+ argSequence.add(new XSBoolean(boolVal));
+ }
+
+ evalResultSequence = (new XSBoolean()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+
+ break;
+ case Keywords.XS_DATE :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ argSequence.add(XSDate.parseDate(XslTransformEvaluationHelper.getStrVal(argVal)));
+ }
+
+ evalResultSequence = (new XSDate()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+
+ break;
+ case Keywords.XS_DURATION :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ String strVal = XslTransformEvaluationHelper.getStrVal(argVal);
+ XSDuration xsDuration = XSDuration.parseDuration(strVal);
+ if (xsDuration != null) {
+ argSequence.add(xsDuration);
+ evalResultSequence = (new XSDuration()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+ }
+ else {
+ throw new TransformerException("FORG0001 : An incorrectly formatted xs:duration value '" +
+ strVal + "' is present in the input.", srcLocator);
+ }
}
- else {
- throw new TransformerException("FORG0001 : an invalid duration value '" + strVal + "' is "
- + "present in the input.", srcLocator);
+
+ break;
+ case Keywords.XS_YEAR_MONTH_DURATION :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ String strVal = XslTransformEvaluationHelper.getStrVal(argVal);
+ XSDuration xsDuration = XSYearMonthDuration.parseYearMonthDuration(strVal);
+ if (xsDuration != null) {
+ argSequence.add(xsDuration);
+ evalResultSequence = (new XSYearMonthDuration()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+ }
+ else {
+ throw new TransformerException("FORG0001 : An incorrectly formatted xs:yearMonthDuration value '" +
+ strVal + "' is present in the input.", srcLocator);
+ }
}
- }
- }
- else if ((Keywords.XS_DAY_TIME_DURATION).equals(funcExtFunction.getFunctionName())) {
- for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
- XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
- String strVal = XslTransformEvaluationHelper.getStrVal(argVal);
- XSDuration xsDuration = XSDayTimeDuration.parseDayTimeDuration(strVal);
- if (xsDuration != null) {
- ResultSequence argSequence = new ResultSequence();
- argSequence.add(xsDuration);
- ResultSequence rSeq = (new XSDayTimeDuration()).constructor(argSequence);
- evalResult = rSeq.item(0);
+
+ break;
+ case Keywords.XS_DAY_TIME_DURATION :
+ for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+ XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+ String strVal = XslTransformEvaluationHelper.getStrVal(argVal);
+ XSDuration xsDuration = XSDayTimeDuration.parseDayTimeDuration(strVal);
+ if (xsDuration != null) {
+ argSequence.add(xsDuration);
+ evalResultSequence = (new XSDayTimeDuration()).constructor(argSequence);
+ evalResult = evalResultSequence.item(0);
+ }
+ else {
+ throw new TransformerException("FORG0001 : An incorrectly formatted xs:dayTimeDuration value '" +
+ strVal + "' is present in the input.", srcLocator);
+ }
}
- else {
- throw new TransformerException("FORG0001 : an invalid duration value '" + strVal + "' is "
- + "present in the input.", srcLocator);
- }
- }
- }
+
+ break;
+
+ default:
+ // no op
+ }
}
}
else if (expr instanceof Operation) {
- // we need to call this method recursively, for the possibility of more than one
- // XPath expression evaluation operator present within an XPath expression.
- // for e.g, a + b - c.
+ // We need to call this method recursively, for the possibility of more than one
+ // XPath expression evaluation operator present within an XPath expression
+ // (for e.g, a + b - c).
Operation opn = (Operation)expr;
XObject leftOperand = processFuncExtFunctionOrXPathOpn(xctxt, opn.getLeftOperand());
XObject rightOperand = processFuncExtFunctionOrXPathOpn(xctxt, opn.getRightOperand());
diff --git a/src/org/apache/xpath/compiler/Keywords.java b/src/org/apache/xpath/compiler/Keywords.java
index c7541dab..fa281598 100644
--- a/src/org/apache/xpath/compiler/Keywords.java
+++ b/src/org/apache/xpath/compiler/Keywords.java
@@ -379,6 +379,9 @@ public class Keywords
/** xs:date data type string. */
public static final String XS_DATE = "date";
+ /** xs:duration data type string. */
+ public static final String XS_DURATION = "duration";
+
/** xs:yearMonthDuration data type string. */
public static final String XS_YEAR_MONTH_DURATION = "yearMonthDuration";
diff --git a/src/org/apache/xpath/functions/FuncMax.java b/src/org/apache/xpath/functions/FuncMax.java
index 3f8e7642..8533a6dd 100644
--- a/src/org/apache/xpath/functions/FuncMax.java
+++ b/src/org/apache/xpath/functions/FuncMax.java
@@ -33,11 +33,13 @@ import org.apache.xpath.objects.XString;
import org.apache.xpath.operations.Variable;
import org.apache.xpath.res.XPATHErrorResources;
import org.apache.xpath.xs.types.XSDate;
+import org.apache.xpath.xs.types.XSDayTimeDuration;
import org.apache.xpath.xs.types.XSDouble;
import org.apache.xpath.xs.types.XSNumericType;
import org.apache.xpath.xs.types.XSString;
import org.apache.xpath.xs.types.XSUntyped;
import org.apache.xpath.xs.types.XSUntypedAtomic;
+import org.apache.xpath.xs.types.XSYearMonthDuration;
/**
* Implementation of an XPath 3.1 function fn:max.
@@ -87,6 +89,8 @@ public class FuncMax extends FunctionMultiArgs
int doubleItemCount = 0;
int strItemCount = 0;
int dateItemCount = 0;
+ int yearMonthDurationItemCount = 0;
+ int dayTimeDurationItemCount = 0;
if (xObjArg0 instanceof XNodeSet) {
// If for all the nodes of an input sequence, the node's string
@@ -148,10 +152,15 @@ public class FuncMax extends FunctionMultiArgs
convetedInpSequence.add((XSDate)seqObj);
dateItemCount++;
}
+ else if (seqObj instanceof XSYearMonthDuration) {
+ convetedInpSequence.add((XSYearMonthDuration)seqObj);
+ yearMonthDurationItemCount++;
+ }
+ else if (seqObj instanceof XSDayTimeDuration) {
+ convetedInpSequence.add((XSDayTimeDuration)seqObj);
+ dayTimeDurationItemCount++;
+ }
}
-
- // TO DO : to handle XML Schema types xs:duration (and its subtypes), xs:anyURI as
- // well, within function call fn:max's input sequence.
}
else {
result = xObjArg0;
@@ -169,16 +178,25 @@ public class FuncMax extends FunctionMultiArgs
else if ((dateItemCount > 0) && (convetedInpSequence.size() == dateItemCount)) {
result = getMaxValueFromXSDateSequence(convetedInpSequence);
}
+ else if ((yearMonthDurationItemCount > 0) && (convetedInpSequence.size() ==
+ yearMonthDurationItemCount)) {
+ result = getMaxValueFromXSYearMonthDurationSequence(convetedInpSequence);
+ }
+ else if ((dayTimeDurationItemCount > 0) && (convetedInpSequence.size() ==
+ dayTimeDurationItemCount)) {
+ result = getMaxValueFromXSDayTimeDurationSequence(convetedInpSequence);
+ }
else if ((xObjArg0 instanceof ResultSequence) && (((ResultSequence)xObjArg0).
size() == 0)) {
// the result value is an empty sequence
result = new ResultSequence();
}
else {
- throw new javax.xml.transform.TransformerException("FORG0006 : An input sequence processed by function fn:max, "
+ throw new javax.xml.transform.TransformerException("FORG0006 : An input sequence processed by function fn:max "
+ "should have data values of same type for all the items of "
- + "sequence (for e.g, all xs:double, all xs:string, all xs:date "
- + "etc).", srcLocator);
+ + "sequence (for e.g, all xs:double, all xs:string, all xs:date, "
+ + "all xs:yearMonthDuration, all xs:dayTimeDuration etc).",
+ srcLocator);
}
}
@@ -280,6 +298,44 @@ public class FuncMax extends FunctionMultiArgs
return result;
}
+ /**
+ * Given a sequence of xdm XSYearMonthDuration objects, find the
+ * XSYearMonthDuration object that represents the latest value amongst
+ * the items of the provided sequence.
+ */
+ private XSYearMonthDuration getMaxValueFromXSYearMonthDurationSequence(
+ ResultSequence inpSeq) {
+ XSYearMonthDuration result = (XSYearMonthDuration)(inpSeq.item(0));
+
+ for (int idx = 1; idx < inpSeq.size(); idx++) {
+ XSYearMonthDuration nextVal = (XSYearMonthDuration)(inpSeq.item(idx));
+ if (nextVal.gt(result)) {
+ result = nextVal;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Given a sequence of xdm XSDayTimeDuration objects, find the
+ * XSDayTimeDuration object that represents the latest value amongst
+ * the items of the provided sequence.
+ */
+ private XSDayTimeDuration getMaxValueFromXSDayTimeDurationSequence(
+ ResultSequence inpSeq) {
+ XSDayTimeDuration result = (XSDayTimeDuration)(inpSeq.item(0));
+
+ for (int idx = 1; idx < inpSeq.size(); idx++) {
+ XSDayTimeDuration nextVal = (XSDayTimeDuration)(inpSeq.item(idx));
+ if (nextVal.gt(result)) {
+ result = nextVal;
+ }
+ }
+
+ return result;
+ }
+
/**
* Get the string comparison collation uri, for function call fn:max's evaluation.
*/
diff --git a/src/org/apache/xpath/functions/FuncMin.java b/src/org/apache/xpath/functions/FuncMin.java
index 4c80bc6e..97631ac7 100644
--- a/src/org/apache/xpath/functions/FuncMin.java
+++ b/src/org/apache/xpath/functions/FuncMin.java
@@ -33,11 +33,13 @@ import org.apache.xpath.objects.XString;
import org.apache.xpath.operations.Variable;
import org.apache.xpath.res.XPATHErrorResources;
import org.apache.xpath.xs.types.XSDate;
+import org.apache.xpath.xs.types.XSDayTimeDuration;
import org.apache.xpath.xs.types.XSDouble;
import org.apache.xpath.xs.types.XSNumericType;
import org.apache.xpath.xs.types.XSString;
import org.apache.xpath.xs.types.XSUntyped;
import org.apache.xpath.xs.types.XSUntypedAtomic;
+import org.apache.xpath.xs.types.XSYearMonthDuration;
/**
* Implementation of an XPath 3.1 function fn:min.
@@ -87,6 +89,8 @@ public class FuncMin extends FunctionMultiArgs
int doubleItemCount = 0;
int strItemCount = 0;
int dateItemCount = 0;
+ int yearMonthDurationItemCount = 0;
+ int dayTimeDurationItemCount = 0;
if (xObjArg0 instanceof XNodeSet) {
// If for all the nodes of an input sequence, the node's string
@@ -148,10 +152,15 @@ public class FuncMin extends FunctionMultiArgs
convetedInpSequence.add((XSDate)seqObj);
dateItemCount++;
}
+ else if (seqObj instanceof XSYearMonthDuration) {
+ convetedInpSequence.add((XSYearMonthDuration)seqObj);
+ yearMonthDurationItemCount++;
+ }
+ else if (seqObj instanceof XSDayTimeDuration) {
+ convetedInpSequence.add((XSDayTimeDuration)seqObj);
+ dayTimeDurationItemCount++;
+ }
}
-
- // TO DO : to handle XML Schema types xs:duration (and its subtypes), xs:anyURI as
- // well, within function call fn:min's input sequence.
}
else {
result = xObjArg0;
@@ -169,16 +178,25 @@ public class FuncMin extends FunctionMultiArgs
else if ((dateItemCount > 0) && (convetedInpSequence.size() == dateItemCount)) {
result = getMinValueFromXSDateSequence(convetedInpSequence);
}
+ else if ((yearMonthDurationItemCount > 0) && (convetedInpSequence.size() ==
+ yearMonthDurationItemCount)) {
+ result = getMinValueFromXSYearMonthDurationSequence(convetedInpSequence);
+ }
+ else if ((dayTimeDurationItemCount > 0) && (convetedInpSequence.size() ==
+ dayTimeDurationItemCount)) {
+ result = getMinValueFromXSDayTimeDurationSequence(convetedInpSequence);
+ }
else if ((xObjArg0 instanceof ResultSequence) && (((ResultSequence)xObjArg0).
size() == 0)) {
// the result value is an empty sequence
result = new ResultSequence();
}
else {
- throw new javax.xml.transform.TransformerException("FORG0006 : An input sequence processed by function fn:min, "
- + "should have data values of same type for all the items of "
- + "sequence (for e.g, all xs:double, all xs:string, all xs:date "
- + "etc).", srcLocator);
+ throw new javax.xml.transform.TransformerException("FORG0006 : An input sequence processed by function fn:min "
+ + "should have data values of same type for all the items of "
+ + "sequence (for e.g, all xs:double, all xs:string, all xs:date, "
+ + "all xs:yearMonthDuration, all xs:dayTimeDuration etc).",
+ srcLocator);
}
}
@@ -280,6 +298,44 @@ public class FuncMin extends FunctionMultiArgs
return result;
}
+ /**
+ * Given a sequence of xdm XSYearMonthDuration objects, find the
+ * XSYearMonthDuration object that represents the smallest value
+ * amongst the items of the provided sequence.
+ */
+ private XSYearMonthDuration getMinValueFromXSYearMonthDurationSequence(
+ ResultSequence inpSeq) {
+ XSYearMonthDuration result = (XSYearMonthDuration)(inpSeq.item(0));
+
+ for (int idx = 1; idx < inpSeq.size(); idx++) {
+ XSYearMonthDuration nextVal = (XSYearMonthDuration)(inpSeq.item(idx));
+ if (nextVal.lt(result)) {
+ result = nextVal;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Given a sequence of xdm XSDayTimeDuration objects, find the
+ * XSDayTimeDuration object that represents the smallest value
+ * amongst the items of the provided sequence.
+ */
+ private XSDayTimeDuration getMinValueFromXSDayTimeDurationSequence(
+ ResultSequence inpSeq) {
+ XSDayTimeDuration result = (XSDayTimeDuration)(inpSeq.item(0));
+
+ for (int idx = 1; idx < inpSeq.size(); idx++) {
+ XSDayTimeDuration nextVal = (XSDayTimeDuration)(inpSeq.item(idx));
+ if (nextVal.lt(result)) {
+ result = nextVal;
+ }
+ }
+
+ return result;
+ }
+
/**
* Get the string comparison collation uri, for function call fn:min's evaluation.
*/
diff --git a/src/org/apache/xpath/xs/types/XSDayTimeDuration.java b/src/org/apache/xpath/xs/types/XSDayTimeDuration.java
index 074768b3..625558ea 100644
--- a/src/org/apache/xpath/xs/types/XSDayTimeDuration.java
+++ b/src/org/apache/xpath/xs/types/XSDayTimeDuration.java
@@ -19,6 +19,10 @@
*/
package org.apache.xpath.xs.types;
+import java.math.BigDecimal;
+
+import javax.xml.transform.TransformerException;
+
import org.apache.xpath.objects.ResultSequence;
/**
@@ -202,6 +206,110 @@ public class XSDayTimeDuration extends XSDuration {
return XS_DAY_TIME_DURATION;
}
+ /**
+ * Method to add an XSDayTimeDuration value, to this
+ * XSDayTimeDuration value.
+ */
+ public XSDayTimeDuration add(XSDayTimeDuration xsDayTimeDuration) {
+ double sum = value() + xsDayTimeDuration.value();
+
+ return new XSDayTimeDuration(sum);
+ }
+
+ /**
+ * Method to subtract an XSDayTimeDuration value, from this
+ * XSDayTimeDuration value.
+ */
+ public XSDayTimeDuration subtract(XSDayTimeDuration xsDayTimeDuration) {
+ double diff = value() - xsDayTimeDuration.value();
+
+ return new XSDayTimeDuration(diff);
+ }
+
+ /**
+ * Method to multiply an XSDayTimeDuration value represented by this
+ * object, with a numeric value represented by an argument passed to
+ * this method.
+ *
+ * @throws TransformerException
+ */
+ public XSDayTimeDuration mult(XSAnyType xsAnyType) throws TransformerException {
+
+ XSDayTimeDuration result = null;
+
+ if (xsAnyType instanceof XSNumericType) {
+ String argStrVal = ((XSNumericType)xsAnyType).stringValue();
+ XSDouble argDoubleVal = new XSDouble(argStrVal);
+ if (argDoubleVal.nan()) {
+ throw new TransformerException("FOCA0005 : Cannot multiply an XSDayTimeDuration value with NaN.");
+ }
+ else {
+ result = new XSDayTimeDuration(value() * argDoubleVal.doubleValue());
+ }
+ }
+ else {
+ throw new TransformerException("FOCA0005 : Cannot multiply an XSDayTimeDuration value with a "
+ + "non-numeric value");
+ }
+
+ return result;
+ }
+
+ /**
+ * Method to divide this XSDayTimeDuration value, by a value (that needs to be
+ * either a numeric value or a XSDayTimeDuration value) that is passed as an
+ * argument to this method.
+ *
+ * @throws TransformerException
+ */
+ public XSDayTimeDuration div(XSAnyType xsAnyType) throws TransformerException {
+
+ XSDayTimeDuration result = null;
+
+ if (xsAnyType instanceof XSNumericType) {
+ String argStrVal = ((XSNumericType)xsAnyType).stringValue();
+ XSDouble argDoubleVal = new XSDouble(argStrVal);
+ if (argDoubleVal.nan()) {
+ throw new TransformerException("FOCA0005 : Cannot divide an XSDayTimeDuration value with NaN.");
+ }
+ else if (argDoubleVal.zero()) {
+ throw new TransformerException("FODT0001 : Cannot divide an XSDayTimeDuration value with zero.");
+ }
+ else if (argDoubleVal.infinite()) {
+ double doubleResultVal = value() / argDoubleVal.doubleValue();
+ result = new XSDayTimeDuration(doubleResultVal);
+ }
+ else {
+ BigDecimal bigDecimal1 = new BigDecimal(value());
+ BigDecimal bigDecimal2 = new BigDecimal(argDoubleVal.doubleValue());
+ BigDecimal bigDecimalResult = bigDecimal1.divide(new BigDecimal(bigDecimal2.doubleValue()),
+ 18, BigDecimal.ROUND_HALF_EVEN);
+ result = new XSDayTimeDuration(bigDecimalResult.doubleValue());
+ }
+ }
+ else if (xsAnyType instanceof XSDayTimeDuration) {
+ double dbl2 = ((XSDayTimeDuration)xsAnyType).seconds();
+
+ if (dbl2 != 0) {
+ BigDecimal bigDecimal1 = new BigDecimal(value());
+ BigDecimal bigDecimal2 = new BigDecimal(dbl2);
+ BigDecimal bigDecimalResult = bigDecimal1.divide(new BigDecimal(bigDecimal2.doubleValue()),
+ 18, BigDecimal.ROUND_HALF_EVEN);
+ result = new XSDayTimeDuration(bigDecimalResult.doubleValue());
+ }
+ else {
+ throw new TransformerException("FODT0001 : Cannot divide an XSDayTimeDuration value, with a XSDayTimeDuration "
+ + "value that represents zero seconds.");
+ }
+ }
+ else {
+ throw new TransformerException("FORG0006 : Cannot divide an XSDayTimeDuration value, with a value that is of "
+ + "a type other than numeric or XSDayTimeDuration.");
+ }
+
+ return result;
+ }
+
/**
* Do a data type cast, of a XSAnyType value to an XSDuration
* value.
diff --git a/src/org/apache/xpath/xs/types/XSDuration.java b/src/org/apache/xpath/xs/types/XSDuration.java
index 72be5b33..81656f5f 100644
--- a/src/org/apache/xpath/xs/types/XSDuration.java
+++ b/src/org/apache/xpath/xs/types/XSDuration.java
@@ -20,6 +20,8 @@
*/
package org.apache.xpath.xs.types;
+import javax.xml.transform.TransformerException;
+
import org.apache.xpath.objects.ResultSequence;
/**
@@ -31,7 +33,9 @@ import org.apache.xpath.objects.ResultSequence;
*/
public class XSDuration extends XSCtrType {
- private static final String XS_DURATION = "xs:duration";
+ private static final long serialVersionUID = -8460416911698841833L;
+
+ private static final String XS_DURATION = "xs:duration";
protected int _year;
protected int _month;
@@ -248,41 +252,56 @@ public class XSDuration extends XSCtrType {
ret += seconds();
if (negative()) {
- ret *= -1;
+ ret *= -1;
}
return ret;
}
- public double time_value() {
+ public double timeValue() {
double ret = 0;
ret += hours() * 60 * 60;
ret += minutes() * 60;
ret += seconds();
- if (negative())
- ret *= -1;
+ if (negative()) {
+ ret *= -1;
+ }
+
return ret;
}
/**
- * TO DO
- */
- public ResultSequence constructor(ResultSequence arg) {
- ResultSequence rs = null;
-
- return rs;
+ * A method to construct an xdm sequence comprising a
+ * xs:duration value, given input data as argument to
+ * this method.
+ *
+ * @throws TransformerException
+ */
+ public ResultSequence constructor(ResultSequence arg) throws TransformerException {
+ ResultSequence resultSeq = new ResultSequence();
+
+ if (arg.size() == 0) {
+ return resultSeq;
+ }
+
+ XSAnyType xsAnyType = (XSAnyType)arg.item(0);
+
+ XSDuration xsDuration = castToDuration(xsAnyType);
+
+ resultSeq.add(xsDuration);
+
+ return resultSeq;
}
/**
- * Construct a new XSDuration object, by parsing the
- * supplied string.
+ * Construct a new XSDuration object, by parsing the supplied string.
*
* @param str string to be parsed
*
* @return XSDuration object representing the duration of time supplied
*/
- public static XSDuration parse(String str) {
+ public static XSDuration parseDuration(String str) throws TransformerException {
boolean negative = false;
int years = 0;
int months = 0;
@@ -291,29 +310,28 @@ public class XSDuration extends XSCtrType {
int minutes = 0;
double seconds = 0;
- // string following the P
String pstr = "";
String tstr = "";
- // get the negative and pstr
if (str.startsWith("-P")) {
negative = true;
pstr = str.substring(2, str.length());
} else if (str.startsWith("P")) {
negative = false;
pstr = str.substring(1, str.length());
- } else
+ } else {
return null;
+ }
try {
int index = pstr.indexOf('Y');
- boolean did_something = false;
+ boolean isAction = false;
if (index != -1) {
String digit = pstr.substring(0, index);
years = Integer.parseInt(digit);
pstr = pstr.substring(index + 1, pstr.length());
- did_something = true;
+ isAction = true;
}
index = pstr.indexOf('M');
@@ -321,10 +339,10 @@ public class XSDuration extends XSCtrType {
String digit = pstr.substring(0, index);
months = Integer.parseInt(digit);
pstr = pstr.substring(index + 1, pstr.length());
- did_something = true;
+ isAction = true;
}
- // get the days
+ // days
index = pstr.indexOf('D');
if (index == -1) {
@@ -340,25 +358,25 @@ public class XSDuration extends XSCtrType {
tstr = tstr.substring(1, tstr.length());
} else {
tstr = "";
- did_something = true;
+ isAction = true;
}
}
- // hour
+ // hours
index = tstr.indexOf('H');
if (index != -1) {
String digit = tstr.substring(0, index);
hours = Integer.parseInt(digit);
tstr = tstr.substring(index + 1, tstr.length());
- did_something = true;
+ isAction = true;
}
- // minute
+ // minutes
index = tstr.indexOf('M');
if (index != -1) {
String digit = tstr.substring(0, index);
minutes = Integer.parseInt(digit);
tstr = tstr.substring(index + 1, tstr.length());
- did_something = true;
+ isAction = true;
}
// seconds
index = tstr.indexOf('S');
@@ -366,14 +384,15 @@ public class XSDuration extends XSCtrType {
String digit = tstr.substring(0, index);
seconds = Double.parseDouble(digit);
tstr = tstr.substring(index + 1, tstr.length());
- did_something = true;
+ isAction = true;
}
- if (!did_something) {
+ if (!isAction) {
return null;
}
} catch (NumberFormatException ex) {
- return null;
+ throw new TransformerException("FORG0001 : The provided string, cannot be parsed "
+ + "to a xs:duration value.");
}
return new XSDuration(years, months, days, hours, minutes, seconds, negative);
@@ -396,5 +415,56 @@ public class XSDuration extends XSCtrType {
public int month() {
return _month;
}
+
+ /**
+ * This method does an equality comparison between, this and
+ * another XSDuration value.
+ */
+ public boolean equals(XSDuration xsDuration) {
+ double val1 = value();
+ double val2 = xsDuration.value();
+
+ return val1 == val2;
+ }
+
+ /**
+ * This method checks whether, this XSDuration value is less
+ * than another one.
+ */
+ public boolean lt(XSDuration xsDuration) {
+ double val1 = value();
+ double val2 = xsDuration.value();
+
+ return val1 < val2;
+ }
+
+ /**
+ * This method checks whether, this XSDuration value is
+ * greater than another one.
+ */
+ public boolean gt(XSDuration xsDuration) {
+ double val1 = value();
+ double val2 = xsDuration.value();
+
+ return val1 > val2;
+ }
+
+ /**
+ * Do a data type cast, of a XSAnyType value to an XSDuration
+ * value.
+ *
+ * @throws TransformerException
+ */
+ private XSDuration castToDuration(XSAnyType xsAnyType) throws TransformerException {
+
+ if (xsAnyType instanceof XSDuration) {
+ XSDuration duration = (XSDuration) xsAnyType;
+
+ return new XSDuration(duration.year(), duration.month(), duration.days(), duration.hours(),
+ duration.minutes(), duration.seconds(), duration.negative());
+ }
+
+ return parseDuration(xsAnyType.stringValue());
+ }
}
diff --git a/src/org/apache/xpath/xs/types/XSYearMonthDuration.java b/src/org/apache/xpath/xs/types/XSYearMonthDuration.java
index fcd721cb..f143b34e 100644
--- a/src/org/apache/xpath/xs/types/XSYearMonthDuration.java
+++ b/src/org/apache/xpath/xs/types/XSYearMonthDuration.java
@@ -19,7 +19,10 @@
*/
package org.apache.xpath.xs.types;
-import org.apache.xpath.XPathException;
+import java.math.BigDecimal;
+
+import javax.xml.transform.TransformerException;
+
import org.apache.xpath.objects.ResultSequence;
/**
@@ -245,12 +248,46 @@ public class XSYearMonthDuration extends XSDuration {
public int monthValue() {
int retVal = (year() * 12) + month();
- if (negative())
+ if (negative()) {
retVal *= -1;
+ }
return retVal;
}
+ /**
+ * This method does an equality comparison between, this and
+ * another XSYearMonthDuration value.
+ */
+ public boolean equals(XSYearMonthDuration xsYearMonthDuration) {
+ double val1 = monthValue();
+ double val2 = xsYearMonthDuration.monthValue();
+
+ return val1 == val2;
+ }
+
+ /**
+ * This method checks whether, this XSYearMonthDuration value is
+ * less than another one.
+ */
+ public boolean lt(XSYearMonthDuration xsYearMonthDuration) {
+ double val1 = monthValue();
+ double val2 = xsYearMonthDuration.monthValue();
+
+ return val1 < val2;
+ }
+
+ /**
+ * This method checks whether, this XSYearMonthDuration value is
+ * greater than another one.
+ */
+ public boolean gt(XSYearMonthDuration xsYearMonthDuration) {
+ double val1 = monthValue();
+ double val2 = xsYearMonthDuration.monthValue();
+
+ return val1 > val2;
+ }
+
/**
* Add two XSYearMonthDuration values, and return the result
* as an XSYearMonthDuration value.
@@ -272,56 +309,73 @@ public class XSYearMonthDuration extends XSDuration {
}
/**
- * Multiply an XSYearMonthDuration value by a numeric value, and return the
- * result as an XSYearMonthDuration value.
+ * Method to multiply an XSYearMonthDuration value represented by this
+ * object, with a numeric value represented by an argument passed to
+ * this method.
+ *
+ * @throws TransformerException
*/
- public XSYearMonthDuration mult(XSDouble arg) throws XPathException {
- XSYearMonthDuration result = null;
-
- if (arg.nan()) {
- throw new XPathException("FOCA0005 : NaN supplied as float/double value.");
- }
-
- if (arg.infinite()) {
- throw new XPathException("FODT0001 : Overflow/underflow of value for the "
- + "date/time operation.");
- }
-
- int intVal = (int)Math.round(monthValue() * arg.doubleValue());
-
- result = new XSYearMonthDuration(intVal);
-
- return result;
+ public XSYearMonthDuration mult(XSAnyType xsAnyType) throws TransformerException {
+
+ XSYearMonthDuration result = null;
+
+ if (xsAnyType instanceof XSNumericType) {
+ String argStrVal = ((XSNumericType)xsAnyType).stringValue();
+ XSDouble argDoubleVal = new XSDouble(argStrVal);
+ if (argDoubleVal.nan()) {
+ throw new TransformerException("FOCA0005 : Cannot multiply an XSYearMonthDuration value with NaN.");
+ }
+ else {
+ int res = (int) Math.round(monthValue() * argDoubleVal.doubleValue());
+
+ result = new XSYearMonthDuration(res);
+ }
+ }
+ else {
+ throw new TransformerException("FOCA0005 : Cannot multiply an XSYearMonthDuration value with a "
+ + "non-numeric value");
+ }
+
+ return result;
}
/**
- * Divide an XSYearMonthDuration value by a numeric value, and return the
- * result as an XSYearMonthDuration value.
+ * Method to divide this XSYearMonthDuration value, by a value (that needs to be
+ * either a numeric value or a XSYearMonthDuration value) that is passed as an
+ * argument to this method.
+ *
+ * @throws TransformerException
*/
- public XSYearMonthDuration div(XSDouble arg) throws XPathException {
- XSYearMonthDuration result = null;
+ public XSAnyType div(XSAnyType xsAnyType) throws TransformerException {
- if (arg.nan()) {
- throw new XPathException("FOCA0005 : NaN supplied as float/double value.");
- }
+ XSAnyType result = null;
- if (arg.infinite()) {
- result = new XSYearMonthDuration(0);
- }
- else {
- XSDouble xsDouble = (XSDouble)arg;
-
- if (!arg.zero()) {
- int intVal = (int)Math.round(monthValue() / xsDouble.doubleValue());
- result = new XSYearMonthDuration(intVal);
+ if (xsAnyType instanceof XSNumericType) {
+ String argStrVal = ((XSNumericType)xsAnyType).stringValue();
+ XSDouble argDoubleVal = new XSDouble(argStrVal);
+ if (argDoubleVal.nan()) {
+ throw new TransformerException("FOCA0005 : Cannot divide an XSYearMonthDuration value with NaN.");
+ }
+ else if (argDoubleVal.zero()) {
+ throw new TransformerException("FODT0001 : Cannot divide an XSYearMonthDuration value with zero.");
}
else {
- throw new XPathException("FODT0001 : Overflow/underflow of value for the "
- + "date/time operation.");
- }
+ int intResultVal = (int) Math.round(monthValue() / argDoubleVal.doubleValue());
+ result = new XSYearMonthDuration(intResultVal);
+ }
}
-
- return result;
+ else if (xsAnyType instanceof XSYearMonthDuration) {
+ XSYearMonthDuration argXSYearMonthDuration = (XSYearMonthDuration) xsAnyType;
+ double dblResultVal = (double) monthValue() / argXSYearMonthDuration.monthValue();
+
+ result = new XSDecimal(new BigDecimal(dblResultVal));
+ }
+ else {
+ throw new TransformerException("FORG0006 : Cannot divide an XSYearMonthDuration value, with a value that is of "
+ + "a type other than numeric or XSYearMonthDuration.");
+ }
+
+ return result;
}
/**
diff --git a/tests/fn_max/gold/test3.out b/tests/fn_max/gold/test3.out
new file mode 100644
index 00000000..37769264
--- /dev/null
+++ b/tests/fn_max/gold/test3.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>c</result>
diff --git a/tests/fn_max/gold/test4.out b/tests/fn_max/gold/test4.out
new file mode 100644
index 00000000..c83abe5d
--- /dev/null
+++ b/tests/fn_max/gold/test4.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>P2Y2M</result>
diff --git a/tests/fn_max/gold/test5.out b/tests/fn_max/gold/test5.out
new file mode 100644
index 00000000..7a70f149
--- /dev/null
+++ b/tests/fn_max/gold/test5.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>P6DT11H32M20S</result>
diff --git a/tests/fn_max/test1_b.xml b/tests/fn_max/test1_b.xml
new file mode 100644
index 00000000..c958b047
--- /dev/null
+++ b/tests/fn_max/test1_b.xml
@@ -0,0 +1,5 @@
+<info>
+ <val>a</val>
+ <val>c</val>
+ <val>b</val>
+</info>
\ No newline at end of file
diff --git a/tests/fn_max/test3.xsl b/tests/fn_max/test3.xsl
new file mode 100644
index 00000000..187aa249
--- /dev/null
+++ b/tests/fn_max/test3.xsl
@@ -0,0 +1,47 @@
+<?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"
+ exclude-result-prefixes="xs"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- use with test1_b.xml -->
+
+ <!-- An XSLT stylesheet test, to test the XPath 3.1 fn:max()
+ function. Within this stylesheet, while finding the
+ maximum value amongst XML sibling element nodes, we
+ wish to treat each XML element as having a type
+ annotation xs:string.
+
+ This stylesheet, gets an input data to be transformed
+ from an XML external document.
+ -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/info">
+ <result>
+ <xsl:value-of select="max(for $val in * return xs:string($val))"/>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/fn_max/test4.xsl b/tests/fn_max/test4.xsl
new file mode 100644
index 00000000..66cfb79e
--- /dev/null
+++ b/tests/fn_max/test4.xsl
@@ -0,0 +1,43 @@
+<?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"
+ exclude-result-prefixes="xs"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSLT stylesheet test, to test the XPath 3.1 function
+ fn:max. Within this stylesheet, we find the maximum
+ value within a sequence of xs:yearMonthDuration values.
+ -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:variable name="seq1" select="(xs:yearMonthDuration('P1Y3M'), xs:yearMonthDuration('P2Y2M'),
+ xs:yearMonthDuration('P3M'), xs:yearMonthDuration('P1Y5M'))"/>
+
+ <xsl:template match="/">
+ <result>
+ <xsl:value-of select="max($seq1)"/>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/fn_max/test5.xsl b/tests/fn_max/test5.xsl
new file mode 100644
index 00000000..b3373bc1
--- /dev/null
+++ b/tests/fn_max/test5.xsl
@@ -0,0 +1,43 @@
+<?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"
+ exclude-result-prefixes="xs"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSLT stylesheet test, to test the XPath 3.1 function
+ fn:max. Within this stylesheet, we find the maximum
+ value within a sequence of xs:dayTimeDuration values.
+ -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:variable name="seq1" select="(xs:dayTimeDuration('PT40H'), xs:dayTimeDuration('P6DT11H32M20S'),
+ xs:dayTimeDuration('P2DT3H'))"/>
+
+ <xsl:template match="/">
+ <result>
+ <xsl:value-of select="max($seq1)"/>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/fn_min/gold/test3.out b/tests/fn_min/gold/test3.out
new file mode 100644
index 00000000..21a2c20e
--- /dev/null
+++ b/tests/fn_min/gold/test3.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>P3M</result>
diff --git a/tests/fn_min/gold/test4.out b/tests/fn_min/gold/test4.out
new file mode 100644
index 00000000..e2017da4
--- /dev/null
+++ b/tests/fn_min/gold/test4.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>P1DT16H</result>
diff --git a/tests/fn_min/test3.xsl b/tests/fn_min/test3.xsl
new file mode 100644
index 00000000..0a2c1ee1
--- /dev/null
+++ b/tests/fn_min/test3.xsl
@@ -0,0 +1,43 @@
+<?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"
+ exclude-result-prefixes="xs"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSLT stylesheet test, to test the XPath 3.1 function
+ fn:min. Within this stylesheet, we find the minimum
+ value within a sequence of xs:yearMonthDuration values.
+ -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:variable name="seq1" select="(xs:yearMonthDuration('P1Y3M'), xs:yearMonthDuration('P2Y2M'),
+ xs:yearMonthDuration('P3M'), xs:yearMonthDuration('P1Y5M'))"/>
+
+ <xsl:template match="/">
+ <result>
+ <xsl:value-of select="min($seq1)"/>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/fn_min/test4.xsl b/tests/fn_min/test4.xsl
new file mode 100644
index 00000000..7771c586
--- /dev/null
+++ b/tests/fn_min/test4.xsl
@@ -0,0 +1,43 @@
+<?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"
+ exclude-result-prefixes="xs"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSLT stylesheet test, to test the XPath 3.1 function
+ fn:min. Within this stylesheet, we find the minimum
+ value within a sequence of xs:dayTimeDuration values.
+ -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:variable name="seq1" select="(xs:dayTimeDuration('PT40H'), xs:dayTimeDuration('P6DT11H32M20S'),
+ xs:dayTimeDuration('P2DT3H'))"/>
+
+ <xsl:template match="/">
+ <result>
+ <xsl:value-of select="min($seq1)"/>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/fn_sort/gold/test16.out b/tests/fn_sort/gold/test16.out
new file mode 100644
index 00000000..14b27963
--- /dev/null
+++ b/tests/fn_sort/gold/test16.out
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+ <data1>
+ <d>are</d>
+ <h>for testing</h>
+ <a>hi</a>
+ <c>how</c>
+ <b>there</b>
+ <f>this is an</f>
+ <g>xml document</g>
+ <e>you</e>
+ </data1>
+ <data2>
+ <d>are</d>
+ <h>for testing</h>
+ <a>hi</a>
+ <c>how</c>
+ <b>there</b>
+ <f>this is an</f>
+ <g>xml document</g>
+ <e>you</e>
+ </data2>
+ <data3>
+ <d>are</d>
+ <h>for testing</h>
+ <a>hi</a>
+ <c>how</c>
+ <b>there</b>
+ <f>this is an</f>
+ <g>xml document</g>
+ <e>you</e>
+ </data3>
+</result>
diff --git a/tests/fn_sort/test19.xsl b/tests/fn_sort/test19.xsl
new file mode 100644
index 00000000..bfaf4a3e
--- /dev/null
+++ b/tests/fn_sort/test19.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"
+ exclude-result-prefixes="xs"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- use with test1_i.xml -->
+
+ <!-- An XSLT stylesheet test case, to test an XPath 3.1
+ function fn:sort, using collations.
+ -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:variable name="collation1" select="'http://www.w3.org/2005/xpath-functions/collation/codepoint'"/>
+
+ <xsl:variable name="collation2" select="'http://www.w3.org/2013/collation/UCA?lang=en'"/>
+
+ <xsl:template match="/info">
+ <result>
+ <data1>
+ <!-- implicitly using 'Unicode codepoint collation' -->
+ <xsl:copy-of select="sort(*, (), function($elem) { xs:string($elem) })"/>
+ </data1>
+ <data2>
+ <!-- explicitly requesting 'Unicode codepoint collation', via a collation uri -->
+ <xsl:copy-of select="sort(*, $collation1, function($elem) { xs:string($elem) })"/>
+ </data2>
+ <data3>
+ <!-- requesting to use 'Unicode Collation Algorithm', via a collation uri
+ with collation language as English (using language code, 'en'). -->
+ <xsl:copy-of select="sort(*, $collation2, function($elem) { xs:string($elem) })"/>
+ </data3>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/fn_sort/test1_i.xml b/tests/fn_sort/test1_i.xml
new file mode 100644
index 00000000..ee2a0f3a
--- /dev/null
+++ b/tests/fn_sort/test1_i.xml
@@ -0,0 +1,10 @@
+<info>
+ <a>hi</a>
+ <b>there</b>
+ <c>how</c>
+ <d>are</d>
+ <e>you</e>
+ <f>this is an</f>
+ <g>xml document</g>
+ <h>for testing</h>
+</info>
\ No newline at end of file
diff --git a/tests/org/apache/xalan/xpath3/FnMaxTests.java b/tests/org/apache/xalan/xpath3/FnMaxTests.java
index 6f6f7720..30e9ff42 100644
--- a/tests/org/apache/xalan/xpath3/FnMaxTests.java
+++ b/tests/org/apache/xalan/xpath3/FnMaxTests.java
@@ -68,5 +68,35 @@ public class FnMaxTests extends XslTransformTestsUtil {
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
}
+
+ @Test
+ public void xslFnMaxTest3() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_b.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test3.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test3.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslFnMaxTest4() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test4.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslFnMaxTest5() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test5.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test5.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test5.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
}
diff --git a/tests/org/apache/xalan/xpath3/FnMinTests.java b/tests/org/apache/xalan/xpath3/FnMinTests.java
index 56881cb6..0f59d657 100644
--- a/tests/org/apache/xalan/xpath3/FnMinTests.java
+++ b/tests/org/apache/xalan/xpath3/FnMinTests.java
@@ -68,5 +68,25 @@ public class FnMinTests extends XslTransformTestsUtil {
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
}
+
+ @Test
+ public void xslFnMinTest3() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test3.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test3.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test3.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslFnMinTest4() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test4.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
}
diff --git a/tests/org/apache/xalan/xpath3/FnSortTests.java b/tests/org/apache/xalan/xpath3/FnSortTests.java
index d8373c92..b4ea1874 100644
--- a/tests/org/apache/xalan/xpath3/FnSortTests.java
+++ b/tests/org/apache/xalan/xpath3/FnSortTests.java
@@ -228,5 +228,15 @@ public class FnSortTests extends XslTransformTestsUtil {
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
}
+
+ @Test
+ public void xslFnSortTest19() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_i.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test19.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test16.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org