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/20 16:35:35 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: implementation enhancements to xpath 3.1 fn:sort function to optionally use collation uri, and committing a new relevant working test case for these implementation changes. doing minor refactoring and codebase comments changes 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 f9fd2e21 implementation enhancements to xpath 3.1 fn:sort function to optionally use collation uri, and committing a new relevant working test case for these implementation changes. doing minor refactoring and codebase comments changes as well.
     new d4546d00 Merge pull request #55 from mukulga/xalan-j_xslt3.0_mukul
f9fd2e21 is described below

commit f9fd2e2190f2f4817464da62845c8396f9385441
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sun Aug 20 21:57:56 2023 +0530

    implementation enhancements to xpath 3.1 fn:sort function to optionally use collation uri, and committing a new relevant working test case for these implementation changes. doing minor refactoring and codebase comments changes as well.
---
 src/org/apache/xpath/XPathCollationSupport.java | 96 +++++++++++++++----------
 src/org/apache/xpath/functions/FuncCompare.java |  8 +--
 src/org/apache/xpath/functions/FuncSort.java    | 56 ++++++++++-----
 src/org/apache/xpath/objects/XObject.java       | 43 ++++++++---
 src/org/apache/xpath/operations/VcGe.java       |  6 +-
 src/org/apache/xpath/operations/VcGt.java       |  6 +-
 src/org/apache/xpath/operations/VcLe.java       |  6 +-
 src/org/apache/xpath/operations/VcLt.java       |  6 +-
 tests/fn_sort/gold/test10.out                   |  5 ++
 tests/fn_sort/test13.xsl                        | 49 +++++++++++++
 tests/org/apache/xalan/xpath3/FnSortTests.java  | 10 +++
 11 files changed, 221 insertions(+), 70 deletions(-)

diff --git a/src/org/apache/xpath/XPathCollationSupport.java b/src/org/apache/xpath/XPathCollationSupport.java
index a903a87e..f5abf9ed 100644
--- a/src/org/apache/xpath/XPathCollationSupport.java
+++ b/src/org/apache/xpath/XPathCollationSupport.java
@@ -27,7 +27,7 @@ import java.util.Map;
 import javax.xml.transform.TransformerException;
 
 /**
- * This class provides, collation support to XalanJ's XPath 3.1 
+ * This class provides, collation support for XalanJ's XPath 3.1 
  * implementation.
  * 
  * Ref : https://www.w3.org/TR/xpath-functions-31/#collations
@@ -99,8 +99,8 @@ public class XPathCollationSupport {
      *                             
      * @throws javax.xml.transform.TransformerException
      */
-    public int compareStringsUsingCollationUri(String str1, String str2, String collationUri) 
-                                                                                       throws javax.xml.transform.TransformerException {
+    public int compareStringsUsingCollation(String str1, String str2, String collationUri) 
+                                                                                  throws javax.xml.transform.TransformerException {
        int comparisonResult = 0;
        
        if (UNICODE_CODEPOINT_COLLATION_URI.equals(collationUri)) {
@@ -108,16 +108,17 @@ public class XPathCollationSupport {
        }
        else if (collationUri.startsWith(UNICODE_COLLATION_ALGORITHM_URI)) {
           try {
-             Collator collator = getCollatorFromCollationUri(collationUri);
+             Collator strComparisonCollator = getUCACollatorFromCollationUri(collationUri);
              
-             if (collator != null) {
-                comparisonResult = collator.compare(str1, str2);                
+             if (strComparisonCollator != null) {
+                comparisonResult = strComparisonCollator.compare(str1, str2);                
              }
              else if (UCA_FALLBACK_YES.equals(fQueryStrFallbackValue)) {                    
-                comparisonResult = compareStringsUsingCollationUri(str1, str2, fDefaultCollationUri);
+                comparisonResult = compareStringsUsingCollation(str1, str2, fDefaultCollationUri);
              }
              else {
-                throw new javax.xml.transform.TransformerException("FOCH0002 : The requested collation '" + collationUri + "' is not supported.");  
+                throw new javax.xml.transform.TransformerException("FOCH0002 : The requested collation '" + collationUri + 
+                                                                                                                   "' is not supported.");  
              }
           }
           catch (javax.xml.transform.TransformerException ex) {
@@ -157,7 +158,8 @@ public class XPathCollationSupport {
     }
     
     /**
-     * This method compares, two string values using 'unicode codepoint collation'.
+     * This method compares, two string values using 'Unicode Codepoint Collation'
+     * as specified by XPath 3.1 F&O spec.
      *
      * @param str1    the first string
      * @param str2    the second string
@@ -177,7 +179,7 @@ public class XPathCollationSupport {
     
     /**
      * Compare two int[] arrays comprising unicode codepoints, according to
-     * 'unicode codepoint collation'.
+     * 'Unicode Codepoint Collation'.
      */
     private int compareCodepointArrays(int[] codePointsArr1, int[] codePointsArr2) {
        
@@ -256,26 +258,25 @@ public class XPathCollationSupport {
     }
     
     /**
-     * This method helps to implement, unicode collation algorithm as specified by XPath 3.1 F&O
-     * spec, which in turn is based on UTS #10 (Unicode Technical Standard #10 : Unicode Collation
-     * Algorithm).
+     * This method implements, 'Unicode Collation Algorithm' as specified by XPath 3.1 F&O spec
+     * (which in turn is based on UTS #10 [Unicode Technical Standard #10 : Unicode Collation
+     * Algorithm]).
      * 
-     * @param collationUri     the collation uri, specified by users of XPath 3.1 string comparison
-     *                         , or sorting of strings.
+     * @param collationUri     the requested collation uri, during XPath 3.1 string comparisons,
+     *                         and sorting of strings.
      *                         
      * @return                 a configured Java object of type java.text.Collator, that callers of
      *                         this method can use to do locale specific string comparisons.
      * 
      * @throws TransformerException
      */
-    private Collator getCollatorFromCollationUri(String collationUri) throws TransformerException {
+    private Collator getUCACollatorFromCollationUri(String collationUri) throws TransformerException {
        
        Collator strComparisonCollator = null;
        
        try {
            if (collationUri.equals(UNICODE_COLLATION_ALGORITHM_URI)) {
-              strComparisonCollator = Collator.getInstance(DEFAULT_UCA_LOCALE);
-              strComparisonCollator.setStrength(Collator.TERTIARY);
+              strComparisonCollator = getDefaultUCACollator();
            }
            else {
               int ucaUriPrefixLength = UNICODE_COLLATION_ALGORITHM_URI.length();              
@@ -338,6 +339,34 @@ public class XPathCollationSupport {
        return strComparisonCollator;
     }
     
+    /**
+     * Get the java.text.Collator object, for XalanJ's
+     * default collation when using 'unicode collation algorithm'.
+     */
+    private Collator getDefaultUCACollator() {
+        
+        Collator strComparisonCollator = Collator.getInstance(DEFAULT_UCA_LOCALE);
+        
+        switch (DEFAULT_UCA_STRENGTH_VALUE) {
+            case UCA_STRENGTH_PRIMARY :
+               strComparisonCollator.setStrength(Collator.PRIMARY);
+               break;
+            case UCA_STRENGTH_SECONDARY :
+               strComparisonCollator.setStrength(Collator.SECONDARY); 
+               break;
+            case UCA_STRENGTH_TERTIARY :   
+               strComparisonCollator.setStrength(Collator.TERTIARY);
+               break;
+            case UCA_STRENGTH_IDENTICAL :
+               strComparisonCollator.setStrength(Collator.TERTIARY);
+               break;
+            default :
+               // no op
+        }
+        
+        return strComparisonCollator;
+    }
+    
     /**
      * From the requested collation uri, build a corresponding java.util.Map object
      * representation.  
@@ -419,21 +448,24 @@ public class XPathCollationSupport {
     }
     
     /**
-     * An object of this class, stores definition of one
-     * "Unicode Collation Algorithm" (UCA) uri query
-     * parameter.
+     * An object of this class, stores data for one 'Unicode 
+     * Collation Algorithm' (UCA) collation uri query parameter/
+     * keyword (the words 'parameter' and 'keyword' are synonym,
+     * here).
+     * 
+     * XalanJ's XPath 3.1 implementation, currently supports only
+     * following UCA parameters : 'fallback', 'lang', 'strength'. 
      */
     private class UCAParameter {        
         
-        // Variable denoting, keyword/parameter name
-        // (for e.g, 'fallback', 'lang', 'strength').
+        // Variable denoting, UCA keyword name (for e.g, 
+        // 'fallback', 'lang', 'strength').
         private String keywordName;
         
-        // Variable denoting, permitted values for the keyword/parameter
-        // name.
-        // For e.g, the 'fallback' parameter has possible values 'yes'/'no'.
-        // The 'strength' parameter has possible values 'primary',
-        // 'secondary', 'tertiary', 'identical'.
+        // Variable denoting, permitted values for an UCA keyword (for e.g, 
+        // the 'fallback' parameter has possible values 'yes', 'no'. The 
+        // 'strength' parameter has possible values 'primary', 'secondary',
+        // 'tertiary', 'identical').
         private List<String> paramValues;
         
         public UCAParameter(String keywordName, List<String> paramValues) {
@@ -445,17 +477,9 @@ public class XPathCollationSupport {
             return keywordName;
         }
 
-        public void setKeywordName(String keywordName) {
-            this.keywordName = keywordName;
-        }
-
         public List<String> getParamValues() {
             return paramValues;
         }
-
-        public void setParamValues(List<String> paramValues) {
-            this.paramValues = paramValues;
-        }
         
     }
 
diff --git a/src/org/apache/xpath/functions/FuncCompare.java b/src/org/apache/xpath/functions/FuncCompare.java
index 5c477d6c..c85ccd84 100644
--- a/src/org/apache/xpath/functions/FuncCompare.java
+++ b/src/org/apache/xpath/functions/FuncCompare.java
@@ -80,8 +80,8 @@ public class FuncCompare extends FunctionMultiArgs {
                // set the collation to default collation
                String collationUri = xctxt.getDefaultCollation();
                
-               int comparisonResult = xPathCollationSupport.compareStringsUsingCollationUri(
-                                                                                       str0, str1, collationUri);
+               int comparisonResult = xPathCollationSupport.compareStringsUsingCollation(
+                                                                                    str0, str1, collationUri);
                
                result = new XSInteger(BigInteger.valueOf((long)comparisonResult));
             }
@@ -100,8 +100,8 @@ public class FuncCompare extends FunctionMultiArgs {
                 
                 String collationUri = XslTransformEvaluationHelper.getStrVal(xObject2);
                 
-                int comparisonResult = xPathCollationSupport.compareStringsUsingCollationUri(
-                                                                                        str0, str1, collationUri);
+                int comparisonResult = xPathCollationSupport.compareStringsUsingCollation(
+                                                                                     str0, str1, collationUri);
                 
                 result = new XSInteger(BigInteger.valueOf((long)comparisonResult)); 
             }
diff --git a/src/org/apache/xpath/functions/FuncSort.java b/src/org/apache/xpath/functions/FuncSort.java
index 14b68a76..2e2053af 100644
--- a/src/org/apache/xpath/functions/FuncSort.java
+++ b/src/org/apache/xpath/functions/FuncSort.java
@@ -91,15 +91,21 @@ public class FuncSort extends FunctionMultiArgs
         List<InpSeqItemWithSortKeyValue> inpSeqItemWithSortKeyValueList = new 
                                                                    ArrayList<InpSeqItemWithSortKeyValue>();
         
-        if ((numOfArgs == 3) || (numOfArgs == 2)) {
-           arg1 = m_arg1;           
+        String collationUri = xctxt.getDefaultCollation();
+        
+        if ((numOfArgs == 2) || (numOfArgs == 3)) {
+           arg1 = m_arg1;
+           
            XObject XObjArg1 = arg1.execute(xctxt);
             
-           if (!((XObjArg1 instanceof ResultSequence) && 
-                                                (((ResultSequence)XObjArg1).size() == 0))) {
-               throw new javax.xml.transform.TransformerException("FORG0006 : The collation corresponding to supplied value of "
-                                                                                     + "second argument to function call fn:sort, is "
-                                                                                     + "not supported.", srcLocator);  
+           if ((XObjArg1 instanceof ResultSequence) && 
+                                                (((ResultSequence)XObjArg1).size() == 0)) {
+              collationUri = xctxt.getDefaultCollation();   
+           }
+           else {
+              // a collation uri was, explicitly provided during the function call fn:sort
+               
+              collationUri = XslTransformEvaluationHelper.getStrVal(XObjArg1); 
            }
            
            arg2 = m_arg2;
@@ -160,7 +166,12 @@ public class FuncSort extends FunctionMultiArgs
                }
            }
            
-           inpSeqItemWithSortKeyValueList.sort(new FnSortComparator(srcLocator));
+           FnSortComparator fnSortComparator = new FnSortComparator(collationUri, srcLocator);           
+           inpSeqItemWithSortKeyValueList.sort(fnSortComparator);
+           
+           if (fnSortComparator.getErrMessage() != null) {
+              throw new javax.xml.transform.TransformerException(fnSortComparator.getErrMessage(), srcLocator); 
+           }
            
            for (int idx = 0; idx < inpSeqItemWithSortKeyValueList.size(); idx++) {
               InpSeqItemWithSortKeyValue inpSeqItemWithSortKeyValue = inpSeqItemWithSortKeyValueList.get(idx);
@@ -208,7 +219,12 @@ public class FuncSort extends FunctionMultiArgs
               }
            }
            
-           inpSeqItemWithSortKeyValueList.sort(new FnSortComparator(srcLocator));
+           FnSortComparator fnSortComparator = new FnSortComparator(collationUri, srcLocator);
+           inpSeqItemWithSortKeyValueList.sort(fnSortComparator);
+           
+           if (fnSortComparator.getErrMessage() != null) {
+              throw new javax.xml.transform.TransformerException(fnSortComparator.getErrMessage(), srcLocator); 
+           }
                
            for (int idx = 0; idx < inpSeqItemWithSortKeyValueList.size(); idx++) {
               InpSeqItemWithSortKeyValue inpSeqItemWithSortKeyValue = inpSeqItemWithSortKeyValueList.get(idx);
@@ -289,14 +305,19 @@ public class FuncSort extends FunctionMultiArgs
      * An object of this class, is used to support sorting of an 
      * xdm input sequence. 
      */
-    class FnSortComparator implements Comparator {
+    private class FnSortComparator implements Comparator {
+        
+        private String collationUri;
         
         private SourceLocator srcLocator;
         
+        private String errMesg = null;
+        
         /*
          * The class constructor.
          */
-        public FnSortComparator(SourceLocator srcLocator) {
+        public FnSortComparator(String collationUri, SourceLocator srcLocator) {
+           this.collationUri = collationUri; 
            this.srcLocator = srcLocator;    
         }
 
@@ -308,20 +329,23 @@ public class FuncSort extends FunctionMultiArgs
            XObject sortKeyVal2 = ((InpSeqItemWithSortKeyValue)obj2).getInpSeqItemSortKeyVal();
            
            try {
-              if (sortKeyVal1.vcGreaterThan(sortKeyVal2, null, true)) {
+              if (sortKeyVal1.vcGreaterThan(sortKeyVal2, null, collationUri, true)) {
                  comparisonResult = 1;  
               }
-              else if (sortKeyVal1.vcLessThan(sortKeyVal2, null, false)) {
+              else if (sortKeyVal1.vcLessThan(sortKeyVal2, null, collationUri, true)) {
                  comparisonResult = -1; 
               }
            }
            catch (javax.xml.transform.TransformerException ex) {
-              // NO OP
-              // REVISIT
+              errMesg = ex.getMessage();
            }
            
            return comparisonResult;           
-        }        
+        }
+        
+        public String getErrMessage() {
+           return errMesg; 
+        }
     }
     
 }
diff --git a/src/org/apache/xpath/objects/XObject.java b/src/org/apache/xpath/objects/XObject.java
index 189d0db9..f191bd84 100644
--- a/src/org/apache/xpath/objects/XObject.java
+++ b/src/org/apache/xpath/objects/XObject.java
@@ -30,6 +30,7 @@ import org.apache.xpath.Expression;
 import org.apache.xpath.ExpressionNode;
 import org.apache.xpath.ExpressionOwner;
 import org.apache.xpath.NodeSetDTM;
+import org.apache.xpath.XPathCollationSupport;
 import org.apache.xpath.XPathContext;
 import org.apache.xpath.XPathException;
 import org.apache.xpath.XPathVisitor;
@@ -567,7 +568,9 @@ public class XObject extends Expression implements Serializable, Cloneable
    * of value comparison operator "lt".
    *
    * @param obj2                Object to compare this to
-   * @param expressionOwner     this object is used, for error reporting 
+   * @param expressionOwner     this object is used, for error reporting
+   * @param collationUri        collation uri, that needs to be used for string
+   *                            comparison.
    * @param isLtTest            is this method called, to check "lt" or "ge"
    *                            operation. true, if that's "lt" check and false
    *                            otherwise. 
@@ -576,9 +579,12 @@ public class XObject extends Expression implements Serializable, Cloneable
    *
    * @throws javax.xml.transform.TransformerException             
    */
-  public boolean vcLessThan(XObject obj2, ExpressionNode expressionOwner, boolean isLtTest) throws 
-                                                                    javax.xml.transform.TransformerException {
+  public boolean vcLessThan(XObject obj2, ExpressionNode expressionOwner, 
+                                                               String collationUri, boolean isLtTest) 
+                                                                                throws javax.xml.transform.TransformerException {       
        
+       XPathContext xctxt = new XPathContext();
+      
        if ((this instanceof XSDecimal) && (obj2 instanceof XSDecimal)) {
           return ((XSDecimal)this).lt((XSDecimal)obj2);        
        }
@@ -608,8 +614,14 @@ public class XObject extends Expression implements Serializable, Cloneable
        }
        else if ((this instanceof XString) && (obj2 instanceof XString)) {
            String lStr = (((XString)this)).str();
-           String rStr = (((XString)obj2)).str();
-           return (lStr.compareTo(rStr) < 0) ? true : false;
+           String rStr = (((XString)obj2)).str();                      
+           
+           XPathCollationSupport xpathCollationSupport = xctxt.getXPathCollationSupport();
+           
+           int comparisonResult = xpathCollationSupport.compareStringsUsingCollation(lStr, rStr, 
+                                                                                             collationUri);
+           
+           return (comparisonResult < 0) ? true : false;
         }
        
        boolean isOperandNodeSet1 = false;
@@ -646,7 +658,9 @@ public class XObject extends Expression implements Serializable, Cloneable
    * of value comparison operator "gt".
    *
    * @param obj2                Object to compare this to
-   * @param expressionOwner     this object is used, for error reporting 
+   * @param expressionOwner     this object is used, for error reporting
+   * @param collationUri        collation uri, that needs to be used for string
+   *                            comparison. 
    * @param isGtTest            is this method called, to check "gt" or "le"
    *                            operation. true, if that's "gt" check and false
    *                            otherwise.
@@ -655,9 +669,12 @@ public class XObject extends Expression implements Serializable, Cloneable
    *
    * @throws javax.xml.transform.TransformerException            
    */
-  public boolean vcGreaterThan(XObject obj2, ExpressionNode expressionOwner, boolean isGtTest) throws 
-                                                                    javax.xml.transform.TransformerException {
+  public boolean vcGreaterThan(XObject obj2, ExpressionNode expressionOwner, 
+                                                  String collationUri, boolean isGtTest) 
+                                                                 throws javax.xml.transform.TransformerException {
        
+       XPathContext xctxt = new XPathContext();
+      
        if ((this instanceof XSDecimal) && (obj2 instanceof XSDecimal)) {
           return ((XSDecimal)this).gt((XSDecimal)obj2);        
        }
@@ -682,10 +699,16 @@ public class XObject extends Expression implements Serializable, Cloneable
        else if ((this instanceof XSDate) && (obj2 instanceof XSDate)) {
           return ((XSDate)this).gt((XSDate)obj2);    
        }
-       else if ((this instanceof XString) && (obj2 instanceof XString)) {
+       else if ((this instanceof XString) && (obj2 instanceof XString)) {          
           String lStr = (((XString)this)).str();
           String rStr = (((XString)obj2)).str();
-          return (lStr.compareTo(rStr) > 0) ? true : false;
+          
+          XPathCollationSupport xpathCollationSupport = xctxt.getXPathCollationSupport();
+          
+          int comparisonResult = xpathCollationSupport.compareStringsUsingCollation(lStr, rStr, 
+                                                                                            collationUri);
+          
+          return (comparisonResult > 0) ? true : false;
        }
        
        boolean isOperandNodeSet1 = false;
diff --git a/src/org/apache/xpath/operations/VcGe.java b/src/org/apache/xpath/operations/VcGe.java
index aaa54f51..141e0392 100644
--- a/src/org/apache/xpath/operations/VcGe.java
+++ b/src/org/apache/xpath/operations/VcGe.java
@@ -20,6 +20,7 @@
  */
 package org.apache.xpath.operations;
 
+import org.apache.xpath.XPathContext;
 import org.apache.xpath.objects.XBoolean;
 import org.apache.xpath.objects.XObject;
 
@@ -49,6 +50,9 @@ public class VcGe extends Operation
   public XObject operate(XObject left, XObject right) 
                                                  throws javax.xml.transform.TransformerException
   {
-      return left.vcLessThan(right, getExpressionOwner(), false) ? XBoolean.S_FALSE : XBoolean.S_TRUE;
+      XPathContext xctxt = new XPathContext();
+      
+      return left.vcLessThan(right, getExpressionOwner(), xctxt.getDefaultCollation(), 
+                                                                             false) ? XBoolean.S_FALSE : XBoolean.S_TRUE;
   }
 }
diff --git a/src/org/apache/xpath/operations/VcGt.java b/src/org/apache/xpath/operations/VcGt.java
index 43a0f6c2..0d1cc9a8 100644
--- a/src/org/apache/xpath/operations/VcGt.java
+++ b/src/org/apache/xpath/operations/VcGt.java
@@ -20,6 +20,7 @@
  */
 package org.apache.xpath.operations;
 
+import org.apache.xpath.XPathContext;
 import org.apache.xpath.objects.XBoolean;
 import org.apache.xpath.objects.XObject;
 
@@ -49,6 +50,9 @@ public class VcGt extends Operation
   public XObject operate(XObject left, XObject right) 
                                                  throws javax.xml.transform.TransformerException
   {
-      return left.vcGreaterThan(right, getExpressionOwner(), true) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
+      XPathContext xctxt = new XPathContext();            
+      
+      return left.vcGreaterThan(right, getExpressionOwner(), xctxt.getDefaultCollation(), 
+                                                                                  true) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
   }
 }
diff --git a/src/org/apache/xpath/operations/VcLe.java b/src/org/apache/xpath/operations/VcLe.java
index 67372a01..7caa3182 100644
--- a/src/org/apache/xpath/operations/VcLe.java
+++ b/src/org/apache/xpath/operations/VcLe.java
@@ -20,6 +20,7 @@
  */
 package org.apache.xpath.operations;
 
+import org.apache.xpath.XPathContext;
 import org.apache.xpath.objects.XBoolean;
 import org.apache.xpath.objects.XObject;
 
@@ -49,6 +50,9 @@ public class VcLe extends Operation
   public XObject operate(XObject left, XObject right) 
                                                  throws javax.xml.transform.TransformerException
   {
-      return left.vcGreaterThan(right, getExpressionOwner(), false) ? XBoolean.S_FALSE : XBoolean.S_TRUE;
+      XPathContext xctxt = new XPathContext();
+      
+      return left.vcGreaterThan(right, getExpressionOwner(), xctxt.getDefaultCollation(), 
+                                                                                false) ? XBoolean.S_FALSE : XBoolean.S_TRUE;
   }
 }
diff --git a/src/org/apache/xpath/operations/VcLt.java b/src/org/apache/xpath/operations/VcLt.java
index 3412f133..e9b7f75f 100644
--- a/src/org/apache/xpath/operations/VcLt.java
+++ b/src/org/apache/xpath/operations/VcLt.java
@@ -20,6 +20,7 @@
  */
 package org.apache.xpath.operations;
 
+import org.apache.xpath.XPathContext;
 import org.apache.xpath.objects.XBoolean;
 import org.apache.xpath.objects.XObject;
 
@@ -49,6 +50,9 @@ public class VcLt extends Operation
   public XObject operate(XObject left, XObject right) 
                                                  throws javax.xml.transform.TransformerException
   {
-      return left.vcLessThan(right, getExpressionOwner(), true) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
+      XPathContext xctxt = new XPathContext();  
+      
+      return left.vcLessThan(right, getExpressionOwner(), xctxt.getDefaultCollation(), 
+                                                                             true) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
   }
 }
diff --git a/tests/fn_sort/gold/test10.out b/tests/fn_sort/gold/test10.out
new file mode 100644
index 00000000..ef9b52fb
--- /dev/null
+++ b/tests/fn_sort/gold/test10.out
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <one>peach p�ch� p�che sin</one>
+  <two>peach p�ch� p�che sin</two>
+  <three>peach p�che p�ch� sin</three>
+</result>
diff --git a/tests/fn_sort/test13.xsl b/tests/fn_sort/test13.xsl
new file mode 100644
index 00000000..28bee9f3
--- /dev/null
+++ b/tests/fn_sort/test13.xsl
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">             
+
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- An XSLT stylesheet test case, to test XPath 3.1 fn:sort function.
+   
+        Within this stylesheet test example, the data to be sorted and
+        the expected sort results using English and French collations, are
+        borrowed from Oracle's Java SE documentation (https://docs.oracle.com/en/java/javase/20/).
+   -->
+   
+   <xsl:output method="xml" indent="yes"/>
+   
+   <xsl:variable name="seq1" select="('p�ch�', 'peach', 'p�che', 'sin')"/>
+   
+   <xsl:template match="/">
+     <result>
+        <!-- sort using default collation (for XalanJ, default collation is 'unicode codepoint collation') -->
+        <one><xsl:value-of select="sort($seq1)"/></one>
+        
+        <!-- sort using English collation, using 'unicode collation algorithm' -->
+        <two><xsl:value-of select="sort($seq1, 'http://www.w3.org/2013/collation/UCA?lang=en')"/></two>
+        
+        <!-- sort using French collation, using 'unicode collation algorithm' -->
+        <three><xsl:value-of select="sort($seq1, 'http://www.w3.org/2013/collation/UCA?lang=fr')"/></three>
+     </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/org/apache/xalan/xpath3/FnSortTests.java b/tests/org/apache/xalan/xpath3/FnSortTests.java
index c5ccb818..e0ad09a6 100644
--- a/tests/org/apache/xalan/xpath3/FnSortTests.java
+++ b/tests/org/apache/xalan/xpath3/FnSortTests.java
@@ -168,5 +168,15 @@ public class FnSortTests extends XslTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslFnSortTest13() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test13.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test13.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test10.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