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/09/18 14:23:19 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing implementation of xpath 3.1 function fn:data, and few new related working test cases. modifying the implementation of xpath 3.1 'instance of' expression, making it more correct. also committing few minor related xalanj codebase changes on this branch.

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 12ed7225 committing implementation of xpath 3.1 function fn:data, and few new related working test cases. modifying the implementation of xpath 3.1 'instance of' expression, making it more correct. also committing few minor related xalanj codebase changes on this branch.
     new cde03ddd Merge pull request #87 from mukulga/xalan-j_xslt3.0_mukul
12ed7225 is described below

commit 12ed7225b670c8dbafe67f41c314a9b02d66be3d
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Mon Sep 18 19:42:43 2023 +0530

    committing implementation of xpath 3.1 function fn:data, and few new related working test cases. modifying the implementation of xpath 3.1 'instance of' expression, making it more correct. also committing few minor related xalanj codebase changes on this branch.
---
 src/org/apache/xalan/templates/ElemChoose.java     |  85 ++-----
 src/org/apache/xalan/templates/ElemCopyOf.java     |  36 +++
 .../xalan/templates/XSConstructorFunctionUtil.java |  22 +-
 src/org/apache/xpath/compiler/FunctionTable.java   |  12 +-
 src/org/apache/xpath/compiler/Keywords.java        |  16 +-
 src/org/apache/xpath/compiler/XPathParser.java     |   9 +
 .../xpath/composite/SequenceTypeKindTest.java      |   6 +-
 .../xpath/composite/SequenceTypeSupport.java       |  72 +++---
 src/org/apache/xpath/functions/FuncData.java       | 155 ++++++++++++
 src/org/apache/xpath/operations/InstanceOf.java    | 259 ++++++++++++++++++++-
 src/org/apache/xpath/xs/types/XSTime.java          |  78 ++++++-
 tests/fn_data/gold/test1.out                       |  19 ++
 tests/fn_data/gold/test2.out                       |  14 ++
 tests/fn_data/test1.xsl                            |  45 ++++
 tests/fn_data/test1_a.xml                          |  22 ++
 tests/fn_data/test2.xsl                            |  59 +++++
 tests/org/apache/xalan/xpath3/FnDataTests.java     |  72 ++++++
 tests/org/apache/xalan/xslt3/AllXsl3Tests.java     |   4 +-
 18 files changed, 866 insertions(+), 119 deletions(-)

diff --git a/src/org/apache/xalan/templates/ElemChoose.java b/src/org/apache/xalan/templates/ElemChoose.java
index 187e8a1a..8303a93e 100644
--- a/src/org/apache/xalan/templates/ElemChoose.java
+++ b/src/org/apache/xalan/templates/ElemChoose.java
@@ -30,38 +30,14 @@ import org.apache.xpath.XPathContext;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.xs.types.XSAnyType;
 
-/** 
- * XSLT 3.0 xsl:choose element.
- * 
-   <xsl:choose>
-      <!-- Content: (xsl:when+, xsl:otherwise?) -->
-   </xsl:choose>
-
-   <xsl:when
-          test = expression>
-       <!-- Content: sequence-constructor -->
-   </xsl:when>
-
-   <xsl:otherwise>
-      <!-- Content: sequence-constructor -->
-   </xsl:otherwise>
-
- * @xsl.usage advanced
- */
-/*
+/**
  *  Implementation of the XSLT 3.0 xsl:choose instruction.
  *  
- *  An XSLT xsl:choose instruction is used, to perform conditional processing.
- *  
- *  The xsl:choose element selects one among a number of possible alternatives. 
- *  It consists of a sequence of one or more xsl:when elements followed by an 
- *  optional xsl:otherwise element. Each xsl:when element has a single attribute, 
- *  test, which specifies an expression. The content of the xsl:when and 
- *  xsl:otherwise elements is a sequence constructor.
+ *  @xsl.usage advanced
  */
 public class ElemChoose extends ElemTemplateElement
 {
-    static final long serialVersionUID = -3070117361903102033L;
+   static final long serialVersionUID = -3070117361903102033L;
 
   /**
    * Get an int constant identifying the type of element.
@@ -120,38 +96,25 @@ public class ElemChoose extends ElemTemplateElement
         // must be xsl:when
         XPathContext xctxt = transformer.getXPathContext();
         int sourceNode = xctxt.getCurrentNode();
-        
-        // System.err.println("\""+when.getTest().getPatternString()+"\"");
-        
-        // if(when.getTest().getPatternString().equals("COLLECTION/icuser/ictimezone/LITERAL='GMT +13:00 Pacific/Tongatapu'"))
-        // 	System.err.println("Found COLLECTION/icuser/ictimezone/LITERAL");
 
         if (transformer.getDebug())
         {
-          XObject test = when.getTest().execute(xctxt, sourceNode, when);
-
-          if (transformer.getDebug())
-            transformer.getTraceManager().fireSelectedEvent(sourceNode, when,
-                    "test", when.getTest(), test);
-
-          if (test.bool())
-          {
-            transformer.getTraceManager().fireTraceEvent(when);
+            XObject test = when.getTest().execute(xctxt, sourceNode, when);
+
+            if (transformer.getDebug())
+               transformer.getTraceManager().fireSelectedEvent(sourceNode, when,
+                                                                        "test", when.getTest(), test);
+            if (test.bool())
+            {
+               transformer.getTraceManager().fireTraceEvent(when);
             
-            transformer.executeChildTemplates(when, true);
+               transformer.executeChildTemplates(when, true);
 
-	        transformer.getTraceManager().fireTraceEndEvent(when); 
+	           transformer.getTraceManager().fireTraceEndEvent(when); 
 	                  
-            return;
-          }
-
+               return;
+            }
         }
-        /*else if (when.getTest().bool(xctxt, sourceNode, when))
-        {
-          transformer.executeChildTemplates(when, true);
-
-          return;
-        }*/
         else {
             XObject xpath3ContextItem = xctxt.getXPath3ContextItem();        
             if (xpath3ContextItem != null) {
@@ -225,17 +188,13 @@ public class ElemChoose extends ElemTemplateElement
 
     switch (type)
     {
-    case Constants.ELEMNAME_WHEN :
-    case Constants.ELEMNAME_OTHERWISE :
-
-      // TODO: Positional checking
-      break;
-    default :
-      error(XSLTErrorResources.ER_CANNOT_ADD,
-            new Object[]{ newChild.getNodeName(),
-                          this.getNodeName() });  //"Can not add " +((ElemTemplateElement)newChild).m_elemName +
-
-    //" to " + this.m_elemName);
+        case Constants.ELEMNAME_WHEN :
+        case Constants.ELEMNAME_OTHERWISE :
+          break;
+        default :
+          error(XSLTErrorResources.ER_CANNOT_ADD,
+                new Object[]{ newChild.getNodeName(),
+                              this.getNodeName() });
     }
 
     return super.appendChild(newChild);
diff --git a/src/org/apache/xalan/templates/ElemCopyOf.java b/src/org/apache/xalan/templates/ElemCopyOf.java
index e2de4b8d..6828b74d 100644
--- a/src/org/apache/xalan/templates/ElemCopyOf.java
+++ b/src/org/apache/xalan/templates/ElemCopyOf.java
@@ -43,6 +43,8 @@ import org.apache.xpath.objects.XNumber;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XString;
 import org.apache.xpath.xs.types.XSAnyAtomicType;
+import org.apache.xpath.xs.types.XSUntyped;
+import org.apache.xpath.xs.types.XSUntypedAtomic;
 import org.xml.sax.SAXException;
 
 /**
@@ -212,6 +214,14 @@ public class ElemCopyOf extends ElemTemplateElement
                 strVal = ((XSAnyAtomicType)value).stringValue();
                 handler.characters(strVal.toCharArray(), 0, strVal.length());
             }
+            else if (value instanceof XSUntypedAtomic) {
+                strVal = ((XSUntypedAtomic)value).stringValue();
+                handler.characters(strVal.toCharArray(), 0, strVal.length());
+            }
+            else if (value instanceof XSUntyped) {
+                strVal = ((XSUntyped)value).stringValue();
+                handler.characters(strVal.toCharArray(), 0, strVal.length());
+            }
             else if (value instanceof InlineFunction) {
                 throw new TransformerException("XTDE0450 : Cannot add a function item to an XDM result tree, "
                                                                                                      + "via xsl:copy-of instruction.", srcLocator);
@@ -329,6 +339,32 @@ public class ElemCopyOf extends ElemTemplateElement
                 }
             }
          }
+         else if (xdmItem instanceof XSUntypedAtomic) {
+             strVal = ((XSUntypedAtomic)xdmItem).stringValue();
+             if (xslSeqProc) {
+                 strVal = strVal + ElemSequence.STRING_VAL_SERIALIZATION_SUFFIX;
+                 serializationHandler.characters(strVal.toCharArray(), 0, strVal.length());
+             }
+             else {
+                 serializationHandler.characters(strVal.toCharArray(), 0, strVal.length());
+                 if (idx < (resultSequence.size() - 1)) {                     
+                    serializationHandler.characters(spaceCharArr, 0, 1);
+                 }
+             }
+          }
+         else if (xdmItem instanceof XSUntyped) {
+             strVal = ((XSUntyped)xdmItem).stringValue();
+             if (xslSeqProc) {
+                 strVal = strVal + ElemSequence.STRING_VAL_SERIALIZATION_SUFFIX;
+                 serializationHandler.characters(strVal.toCharArray(), 0, strVal.length());
+             }
+             else {
+                 serializationHandler.characters(strVal.toCharArray(), 0, strVal.length());
+                 if (idx < (resultSequence.size() - 1)) {                     
+                    serializationHandler.characters(spaceCharArr, 0, 1);
+                 }
+             }
+          }
          else if (xdmItem.getType() == XObject.CLASS_NODESET) {                 
              copyOfActionOnNodeSet((XNodeSet)xdmItem, transformer, serializationHandler, xctxt);
          }
diff --git a/src/org/apache/xalan/templates/XSConstructorFunctionUtil.java b/src/org/apache/xalan/templates/XSConstructorFunctionUtil.java
index 24a30f04..870a6c21 100644
--- a/src/org/apache/xalan/templates/XSConstructorFunctionUtil.java
+++ b/src/org/apache/xalan/templates/XSConstructorFunctionUtil.java
@@ -41,6 +41,7 @@ import org.apache.xpath.xs.types.XSInt;
 import org.apache.xpath.xs.types.XSInteger;
 import org.apache.xpath.xs.types.XSLong;
 import org.apache.xpath.xs.types.XSString;
+import org.apache.xpath.xs.types.XSTime;
 import org.apache.xpath.xs.types.XSYearMonthDuration;
 import org.xml.sax.SAXException;
 
@@ -233,7 +234,7 @@ public class XSConstructorFunctionUtil {
                                evalResult = evalResultSequence.item(0);
                             }
                             else {
-                                throw new TransformerException("FORG0001 : An incorrectly formatted xs:yearMonthDuration value '" + 
+                               throw new TransformerException("FORG0001 : An incorrectly formatted xs:yearMonthDuration value '" + 
                                                                                                 strVal + "' is present in the input.", srcLocator); 
                             }
                         }
@@ -250,7 +251,24 @@ public class XSConstructorFunctionUtil {
                                evalResult = evalResultSequence.item(0);
                             }
                             else {
-                                throw new TransformerException("FORG0001 : An incorrectly formatted xs:dayTimeDuration value '" + 
+                               throw new TransformerException("FORG0001 : An incorrectly formatted xs:dayTimeDuration value '" + 
+                                                                                                strVal + "' is present in the input.", srcLocator); 
+                            }                            
+                        }
+                        
+                        break;
+                    case Keywords.XS_TIME :                 
+                        for (int idx = 0; idx < funcExtFunction.getArgCount(); idx++) {
+                            XObject argVal = (funcExtFunction.getArg(idx)).execute(xctxt);
+                            String strVal = XslTransformEvaluationHelper.getStrVal(argVal);
+                            XSTime xsTime = XSTime.parseTime(strVal);
+                            if (xsTime != null) {
+                               argSequence.add(xsTime);
+                               evalResultSequence = (new XSTime()).constructor(argSequence); 
+                               evalResult = evalResultSequence.item(0);
+                            }
+                            else {
+                               throw new TransformerException("FORG0001 : An incorrectly formatted xs:time value '" + 
                                                                                                 strVal + "' is present in the input.", srcLocator); 
                             }                            
                         }
diff --git a/src/org/apache/xpath/compiler/FunctionTable.java b/src/org/apache/xpath/compiler/FunctionTable.java
index 78b58f4e..f42d0654 100644
--- a/src/org/apache/xpath/compiler/FunctionTable.java
+++ b/src/org/apache/xpath/compiler/FunctionTable.java
@@ -323,6 +323,9 @@ public class FunctionTable
   
   /** The 'doc()' id. */
   public static final int FUNC_DOC = 99;
+  
+  /** The 'data()' id. */
+  public static final int FUNC_DATA = 100;
 
   // Proprietary
 
@@ -380,7 +383,7 @@ public class FunctionTable
    * Number of built in functions. Be sure to update this as
    * built-in functions are added.
    */
-  private static final int NUM_BUILT_IN_FUNCS = 100;
+  private static final int NUM_BUILT_IN_FUNCS = 101;
 
   /**
    * Number of built-in functions that may be added.
@@ -420,6 +423,9 @@ public class FunctionTable
     m_functions[FUNC_ROUND] = org.apache.xpath.functions.FuncRound.class;
     m_functions[FUNC_SUM] = org.apache.xpath.functions.FuncSum.class;
     m_functions[FUNC_STRING] = org.apache.xpath.functions.FuncString.class;
+    
+    m_functions[FUNC_DATA] = org.apache.xpath.functions.FuncData.class;
+    
     m_functions[FUNC_STARTS_WITH] = 
       org.apache.xpath.functions.FuncStartsWith.class;
     m_functions[FUNC_CONTAINS] = org.apache.xpath.functions.FuncContains.class;
@@ -624,6 +630,10 @@ public class FunctionTable
                           new Integer(FunctionTable.FUNC_SUM));
           m_functionID.put(Keywords.FUNC_STRING_STRING,
                           new Integer(FunctionTable.FUNC_STRING));
+          
+          m_functionID.put(Keywords.FUNC_DATA_STRING,
+                          new Integer(FunctionTable.FUNC_DATA));
+          
           m_functionID.put(Keywords.FUNC_STARTS_WITH_STRING,
                           new Integer(FunctionTable.FUNC_STARTS_WITH));
           m_functionID.put(Keywords.FUNC_CONTAINS_STRING,
diff --git a/src/org/apache/xpath/compiler/Keywords.java b/src/org/apache/xpath/compiler/Keywords.java
index 8169df1a..33ff76f9 100644
--- a/src/org/apache/xpath/compiler/Keywords.java
+++ b/src/org/apache/xpath/compiler/Keywords.java
@@ -168,6 +168,9 @@ public class Keywords
 
   /** string function string. */
   public static final String FUNC_STRING_STRING = "string";
+  
+  /** data function string. */
+  public static final String FUNC_DATA_STRING = "data";
 
   /** starts-with function string. */
   public static final String FUNC_STARTS_WITH_STRING = "starts-with";
@@ -356,7 +359,9 @@ public class Keywords
   /** contains-token function string. */
   public static final String FUNC_CONTAINS_TOKEN = "contains-token";
   
-  // XML Schema built-in data type name keywords
+  /**
+   * XML Schema built-in data type name keywords.
+   */
   
   /** xs:string data type string. */
   public static final String XS_STRING = "string";
@@ -391,6 +396,15 @@ public class Keywords
   /** xs:dayTimeDuration data type string. */
   public static final String XS_DAY_TIME_DURATION = "dayTimeDuration";
   
+  /** xs:time data type string. */
+  public static final String XS_TIME = "time";
+  
+  /** xs:untypedAtomic data type string. */
+  public static final String XS_UNTYPED_ATOMIC = "untypedAtomic";
+  
+  /** xs:untyped data type string. */
+  public static final String XS_UNTYPED = "untyped";
+  
   
   /** empty function string. */
   public static final String FUNC_EMPTY = "empty";
diff --git a/src/org/apache/xpath/compiler/XPathParser.java b/src/org/apache/xpath/compiler/XPathParser.java
index 070bcf49..456a4060 100644
--- a/src/org/apache/xpath/compiler/XPathParser.java
+++ b/src/org/apache/xpath/compiler/XPathParser.java
@@ -3794,6 +3794,15 @@ public class XPathParser
             case Keywords.XS_DAY_TIME_DURATION :
                xpathSequenceTypeExpr.setSequenceType(SequenceTypeSupport.XS_DAYTIME_DURATION);
                break;
+            case Keywords.XS_TIME :
+                xpathSequenceTypeExpr.setSequenceType(SequenceTypeSupport.XS_TIME);
+                break;
+            case Keywords.XS_UNTYPED_ATOMIC :
+                xpathSequenceTypeExpr.setSequenceType(SequenceTypeSupport.XS_UNTYPED_ATOMIC);
+                break;
+            case Keywords.XS_UNTYPED :
+                xpathSequenceTypeExpr.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.");        
diff --git a/src/org/apache/xpath/composite/SequenceTypeKindTest.java b/src/org/apache/xpath/composite/SequenceTypeKindTest.java
index 6eefec74..65d88f9d 100644
--- a/src/org/apache/xpath/composite/SequenceTypeKindTest.java
+++ b/src/org/apache/xpath/composite/SequenceTypeKindTest.java
@@ -30,13 +30,13 @@ public class SequenceTypeKindTest {
     
     private int kindVal;
     
-    // for XML element and attribute nodes
+    // For XML element and attribute nodes
     private String nodeLocalName;
     
-    // for XML element and attribute nodes
+    // For XML element and attribute nodes
     private String nodeNsUri;
     
-    // data type's name (for e.g, string, integer etc)
+    // Data type's name (for e.g, string, integer etc)
     private String dataTypeLocalName;
     
     // XML namespace uri of the data type (for e.g, http://www.w3.org/2001/XMLSchema)
diff --git a/src/org/apache/xpath/composite/SequenceTypeSupport.java b/src/org/apache/xpath/composite/SequenceTypeSupport.java
index d581fd85..4b82ab92 100644
--- a/src/org/apache/xpath/composite/SequenceTypeSupport.java
+++ b/src/org/apache/xpath/composite/SequenceTypeSupport.java
@@ -68,17 +68,19 @@ import org.w3c.dom.NodeList;
  */
 public class SequenceTypeSupport {
     
-    // Following are various constant int values, denoting 
-    // XPath 3.1 and XML Schema data types.
+    /** 
+     * Following are various constant int values, denoting XPath 3.1 and 
+     * XML Schema data types.
+     */
         
     public static int EMPTY_SEQUENCE = 1;
     
-    // Represents both XalanJ legacy boolean data type,
-    // and XML Schema data type xs:boolean.
+    // Represents both XML Schema data type xs:boolean, and 
+    // XalanJ legacy boolean data type.
     public static int BOOLEAN = 2;
     
-    // Represents both XalanJ legacy string data type,
-    // and XML Schema data type xs:string.
+    // Represents both XML Schema data type xs:string, and 
+    // XalanJ legacy string data type.
     public static int STRING = 3;
     
     public static int XS_DATE = 4;
@@ -105,8 +107,14 @@ public class SequenceTypeSupport {
     
     public static int XS_FLOAT = 15;
     
-    // following are constant int values denoting XPath sequence type 
-    // KindTest expressions.
+    public static int XS_UNTYPED_ATOMIC = 16;
+    
+    public static int XS_UNTYPED = 17;
+    
+    /** 
+     * Following are constant int values denoting XPath 3.1 sequence
+     * type KindTest expressions.
+     */
     
     public static int ELEMENT_KIND = 101;
     
@@ -138,6 +146,7 @@ public class SequenceTypeSupport {
     
     public static String PLUS = "+";
     
+    
     /**
      * This method converts/casts an XPath 3.1 xdm source value represented by an
      * XObject object instance, to a value of another xdm data type.
@@ -394,26 +403,19 @@ public class SequenceTypeSupport {
     }
     
     /**
-     * Check whether an XObject object instance conforms to an XPath sequence 
-     * type expression.
+     * Check whether, two XML namespace uris are equal.
      */
-    public static boolean isInstanceOf(XObject srcValue, SequenceTypeData sequenceTypeData) {
-       boolean isInstanceOf = true;
-       
-       XObject resultObj = null;
-       
-       try {
-          resultObj = convertXDMValueToAnotherType(srcValue, null, sequenceTypeData, null);
-       } 
-       catch (TransformerException ex) {        
-          isInstanceOf = false;
-       }
-       
-       if (resultObj == null) {
-          isInstanceOf = false; 
-       }
-       
-       return isInstanceOf; 
+    public static boolean isTwoXmlNamespacesEqual(String nsUr1, String nsUri2) {
+        boolean xmlNamespacesEqual = false;
+        
+        if ((nsUr1 == null) && (nsUri2 == null)) {
+           xmlNamespacesEqual = true; 
+        }
+        else if ((nsUr1 != null) && (nsUri2 != null)) {
+           xmlNamespacesEqual = nsUr1.equals(nsUri2);  
+        }
+        
+        return xmlNamespacesEqual; 
     }
     
     /**
@@ -631,22 +633,6 @@ public class SequenceTypeSupport {
         return result;
     }
     
-    /**
-     * Check whether, two XML namespace uris are equal.
-     */
-    private static boolean isTwoXmlNamespacesEqual(String nsUr1, String nsUri2) {
-        boolean xmlNamespacesEqual = false;
-        
-        if ((nsUr1 == null) && (nsUri2 == null)) {
-           xmlNamespacesEqual = true; 
-        }
-        else if ((nsUr1 != null) && (nsUri2 != null)) {
-           xmlNamespacesEqual = nsUr1.equals(nsUri2);  
-        }
-        
-        return xmlNamespacesEqual; 
-    }
-    
     /**
      * This method helps to support following XSL transformation actions,
      * 
diff --git a/src/org/apache/xpath/functions/FuncData.java b/src/org/apache/xpath/functions/FuncData.java
new file mode 100644
index 00000000..18ee945b
--- /dev/null
+++ b/src/org/apache/xpath/functions/FuncData.java
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+/*
+ * $Id$
+ */
+package org.apache.xpath.functions;
+
+import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMIterator;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.ResultSequence;
+import org.apache.xpath.objects.XBoolean;
+import org.apache.xpath.objects.XNodeSet;
+import org.apache.xpath.objects.XNumber;
+import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XString;
+import org.apache.xpath.xs.types.XSAnyAtomicType;
+import org.apache.xpath.xs.types.XSString;
+import org.apache.xpath.xs.types.XSUntyped;
+import org.apache.xpath.xs.types.XSUntypedAtomic;
+
+/**
+ * Implementation of an XPath 3.1 function data().
+ * 
+ * Ref : https://www.w3.org/TR/xpath-functions-31/#func-data
+ * 
+ * This implementation of function fn:data() assumes that,
+ * an XML input document (whose xdm information has been
+ * constructed) has not been validated with an XML schema.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FuncData extends FunctionDef1Arg
+{
+
+  private static final long serialVersionUID = 1734069066834829751L;
+
+  /**
+   * Execute the function. The function must return
+   * a valid object.
+   * @param xctxt The current execution context.
+   * @return A valid XObject.
+   *
+   * @throws javax.xml.transform.TransformerException
+   */
+  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
+  {
+      ResultSequence result = new ResultSequence();
+      
+      XObject fnDataEffectiveArgValue = null;
+      
+      if (m_arg0 == null) {
+         // Handles fn:data function call of the form, fn:data()
+         XObject xpath3ContextItem = xctxt.getXPath3ContextItem();
+         if (xpath3ContextItem != null) {
+            fnDataEffectiveArgValue = xpath3ContextItem;  
+         }
+         else {
+            int contextNodeDtmHandle = xctxt.getContextNode();
+            fnDataEffectiveArgValue = new XNodeSet(contextNodeDtmHandle, xctxt); 
+         }
+      }
+      else {
+         // An explicit argument was provided, to the fn:data 
+         // function call.
+         fnDataEffectiveArgValue = m_arg0.execute(xctxt); 
+      }
+      
+      if (fnDataEffectiveArgValue instanceof XNodeSet) {
+         XNodeSet xNodeSet = (XNodeSet)fnDataEffectiveArgValue;
+         
+         int nextNodeDtmHandle;
+         DTMIterator dtmIter = xNodeSet.iterRaw();
+         while ((nextNodeDtmHandle = dtmIter.nextNode()) != DTM.NULL) {
+            XNodeSet inpNode = new XNodeSet(nextNodeDtmHandle, xctxt.getDTMManager());
+            DTM nodeDtm = inpNode.getDTM(nextNodeDtmHandle);
+            if (nodeDtm.getNodeType(nextNodeDtmHandle) == DTM.DOCUMENT_NODE) {
+               // REVISIT
+               XSUntyped xsUntypedVal = new XSUntyped(inpNode.str());
+               result.add(xsUntypedVal); 
+            }
+            else if (nodeDtm.getNodeType(nextNodeDtmHandle) == DTM.ELEMENT_NODE) {
+               XSUntyped xsUntypedVal = new XSUntyped(inpNode.str());
+               result.add(xsUntypedVal);
+            }
+            else if ((nodeDtm.getNodeType(nextNodeDtmHandle) == DTM.ATTRIBUTE_NODE) ||
+                     (nodeDtm.getNodeType(nextNodeDtmHandle) == DTM.TEXT_NODE)) {
+               XSUntypedAtomic xsUntypedAtomicVal = new XSUntypedAtomic(inpNode.str());
+               result.add(xsUntypedAtomicVal);
+            }
+            else {
+               result.add(new XSString(inpNode.str())); 
+            }
+         }
+      }
+      else if (fnDataEffectiveArgValue instanceof ResultSequence) {
+         ResultSequence inpResultSeq = (ResultSequence)fnDataEffectiveArgValue;
+         ResultSequence expandedResultSeq = new ResultSequence();
+         XslTransformEvaluationHelper.expandResultSequence(inpResultSeq, expandedResultSeq);
+         for (int idx = 0; idx < expandedResultSeq.size(); idx++) {
+            XObject xdmItem = expandedResultSeq.item(idx);
+            if ((xdmItem instanceof XBoolean) || (xdmItem instanceof XNumber) || 
+                (xdmItem instanceof XString) || (xdmItem instanceof XSAnyAtomicType) || 
+                (xdmItem instanceof XSUntypedAtomic) || (xdmItem instanceof XSUntyped)) {
+               result.add(xdmItem); 
+            }
+            else if (xdmItem instanceof XNodeSet) {
+               XNodeSet xdmNode = (XNodeSet)xdmItem;               
+               int nodeDtmHandle = (xdmNode.iterRaw()).item(0);
+               DTM nodeDtm = xdmNode.getDTM(nodeDtmHandle);
+               if (nodeDtm.getNodeType(nodeDtmHandle) == DTM.DOCUMENT_NODE) {
+                  // REVISIT
+                  XSUntyped xsUntypedVal = new XSUntyped(xdmNode.str());
+                  result.add(xsUntypedVal); 
+               }
+               else if (nodeDtm.getNodeType(nodeDtmHandle) == DTM.ELEMENT_NODE) {
+                  XSUntyped xsUntypedVal = new XSUntyped(xdmNode.str());
+                  result.add(xsUntypedVal);
+               }
+               else if ((nodeDtm.getNodeType(nodeDtmHandle) == DTM.ATTRIBUTE_NODE) ||
+                        (nodeDtm.getNodeType(nodeDtmHandle) == DTM.TEXT_NODE)) {
+                  XSUntypedAtomic xsUntypedAtomicVal = new XSUntypedAtomic(xdmNode.str());
+                  result.add(xsUntypedAtomicVal);
+               }
+               else {
+                  result.add(new XSString(xdmNode.str())); 
+               }
+            }
+         }
+      }
+      else {
+         result.add(fnDataEffectiveArgValue); 
+      }
+      
+      return result; 
+   }
+}
diff --git a/src/org/apache/xpath/operations/InstanceOf.java b/src/org/apache/xpath/operations/InstanceOf.java
index f11dce1f..5fa716f3 100644
--- a/src/org/apache/xpath/operations/InstanceOf.java
+++ b/src/org/apache/xpath/operations/InstanceOf.java
@@ -20,10 +20,37 @@
  */
 package org.apache.xpath.operations;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMIterator;
 import org.apache.xpath.composite.SequenceTypeData;
+import org.apache.xpath.composite.SequenceTypeKindTest;
 import org.apache.xpath.composite.SequenceTypeSupport;
+import org.apache.xpath.composite.SequenceTypeSupport.OccurenceIndicator;
+import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XBoolean;
+import org.apache.xpath.objects.XNodeSet;
+import org.apache.xpath.objects.XNumber;
 import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XString;
+import org.apache.xpath.xs.types.XSBoolean;
+import org.apache.xpath.xs.types.XSDate;
+import org.apache.xpath.xs.types.XSDateTime;
+import org.apache.xpath.xs.types.XSDayTimeDuration;
+import org.apache.xpath.xs.types.XSDecimal;
+import org.apache.xpath.xs.types.XSDouble;
+import org.apache.xpath.xs.types.XSDuration;
+import org.apache.xpath.xs.types.XSFloat;
+import org.apache.xpath.xs.types.XSInt;
+import org.apache.xpath.xs.types.XSInteger;
+import org.apache.xpath.xs.types.XSLong;
+import org.apache.xpath.xs.types.XSString;
+import org.apache.xpath.xs.types.XSTime;
+import org.apache.xpath.xs.types.XSUntyped;
+import org.apache.xpath.xs.types.XSUntypedAtomic;
+import org.apache.xpath.xs.types.XSYearMonthDuration;
 
 /**
  * The XPath 3.1 "instance of" operation.
@@ -50,8 +77,238 @@ public class InstanceOf extends Operation
   public XObject operate(XObject left, XObject right) 
                                                  throws javax.xml.transform.TransformerException
   {
-      boolean isInstanceOf = SequenceTypeSupport.isInstanceOf(left, (SequenceTypeData)right);
+      boolean isInstanceOf = false;
+      
+      SequenceTypeData seqTypedData = (SequenceTypeData)right;
+      
+      isInstanceOf = isInstanceOf(left, seqTypedData);
       
       return isInstanceOf ? XBoolean.S_TRUE : XBoolean.S_FALSE;
   }
+
+  /**
+   * This method checks whether, an xdm value is an instance of 
+   * a specific type.
+   */
+  private boolean isInstanceOf(XObject xdmValue, SequenceTypeData seqTypedData) {
+    
+    boolean isInstanceOf = false;
+      
+    if ((xdmValue instanceof XSUntypedAtomic) && 
+          (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_UNTYPED_ATOMIC) && 
+          ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                     (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;  
+      }
+      else if ((xdmValue instanceof XSUntyped) && 
+              (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_UNTYPED) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XString || xdmValue instanceof XSString) && 
+              (seqTypedData.getSequenceType() == SequenceTypeSupport.STRING) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XBoolean || xdmValue instanceof XSBoolean) && 
+              (seqTypedData.getSequenceType() == SequenceTypeSupport.BOOLEAN) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XNumber) && ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                             (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {          
+          if ((seqTypedData.getSequenceType() == SequenceTypeSupport.XS_DOUBLE) || (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_DECIMAL)) {
+             isInstanceOf = true; 
+          }
+          else {
+             double doubleVal = ((XNumber)xdmValue).num();
+             if ((doubleVal == (int)doubleVal) && ((seqTypedData.getSequenceType() == SequenceTypeSupport.XS_INTEGER) || 
+                                                   (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_LONG) ||
+                                                   (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_INT))) {
+                 isInstanceOf = true; 
+             }
+          }
+      }
+      else if ((xdmValue instanceof XSDouble) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_DOUBLE) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                      (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+         isInstanceOf = true; 
+      }
+      else if ((xdmValue instanceof XSFloat) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_FLOAT) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSInt) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_INT) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSLong) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_LONG) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSInteger) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_INTEGER) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSDecimal) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_DECIMAL) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSDate) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_DATE) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSDateTime) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_DATETIME) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSTime) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_TIME) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSDuration) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_DURATION) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSDayTimeDuration) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_DAYTIME_DURATION) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if ((xdmValue instanceof XSYearMonthDuration) && (seqTypedData.getSequenceType() == SequenceTypeSupport.XS_YEARMONTH_DURATION) && 
+              ((seqTypedData.getItemTypeOccurrenceIndicator() == 0) || 
+                                                         (seqTypedData.getItemTypeOccurrenceIndicator() == SequenceTypeSupport.OccurenceIndicator.ZERO_OR_ONE))) {
+          isInstanceOf = true;
+      }
+      else if (xdmValue instanceof XNodeSet) {
+          XNodeSet xdmNodeSet = (XNodeSet)xdmValue;          
+          int nodeSetLen = xdmNodeSet.getLength();          
+          int itemTypeOccurenceIndicator = seqTypedData.getItemTypeOccurrenceIndicator();
+          SequenceTypeKindTest seqTypeKindTest = seqTypedData.getSequenceTypeKindTest();
+          
+          if ((nodeSetLen > 1) && ((itemTypeOccurenceIndicator == 0) || (itemTypeOccurenceIndicator == OccurenceIndicator.ZERO_OR_ONE))) {
+             isInstanceOf = false; 
+          }
+          else {
+             DTMIterator dtmIter = xdmNodeSet.iterRaw();
+                          
+             List<Boolean> nodeSetSequenceTypeKindTestResultList = new ArrayList<Boolean>();
+             
+             int nextNodeDtmHandle;
+             while ((nextNodeDtmHandle = dtmIter.nextNode()) != DTM.NULL) {                 
+                 DTM dtm = dtmIter.getDTM(nextNodeDtmHandle);
+                 java.lang.String nodeName = dtm.getNodeName(nextNodeDtmHandle);
+                 java.lang.String nodeNsUri = dtm.getNamespaceURI(nextNodeDtmHandle);
+                 
+                 if (dtm.getNodeType(nextNodeDtmHandle) == DTM.ELEMENT_NODE) {
+                    if (seqTypeKindTest != null) {
+                       java.lang.String elemNodeKindTestNodeName = seqTypeKindTest.getNodeLocalName();
+                       if (elemNodeKindTestNodeName == null || "".equals(elemNodeKindTestNodeName) || 
+                                                                      SequenceTypeSupport.STAR.equals(elemNodeKindTestNodeName)) {
+                           elemNodeKindTestNodeName = nodeName;  
+                       }
+                       
+                       if ((seqTypeKindTest.getKindVal() == SequenceTypeSupport.ELEMENT_KIND) && (nodeName.equals(elemNodeKindTestNodeName)) 
+                                                    && (SequenceTypeSupport.isTwoXmlNamespacesEqual(nodeNsUri, seqTypeKindTest.getNodeNsUri()))) {
+                           nodeSetSequenceTypeKindTestResultList.add(Boolean.valueOf(true));  
+                       }
+                       else if ((seqTypeKindTest.getKindVal() == SequenceTypeSupport.NODE_KIND) || 
+                                (seqTypeKindTest.getKindVal() == SequenceTypeSupport.ITEM_KIND)) {
+                           nodeSetSequenceTypeKindTestResultList.add(Boolean.valueOf(true)); 
+                       }
+                    }
+                    else {
+                       isInstanceOf = false;
+                       break;
+                    }
+                 }
+                 else if (dtm.getNodeType(nextNodeDtmHandle) == DTM.ATTRIBUTE_NODE) {
+                    if (seqTypeKindTest != null) {
+                       java.lang.String attrNodeKindTestNodeName = seqTypeKindTest.getNodeLocalName();
+                       if (attrNodeKindTestNodeName == null || "".equals(attrNodeKindTestNodeName) || 
+                                                                                                SequenceTypeSupport.STAR.equals(attrNodeKindTestNodeName)) {
+                           attrNodeKindTestNodeName = nodeName;  
+                       }
+                        
+                       if ((seqTypeKindTest.getKindVal() == SequenceTypeSupport.ATTRIBUTE_KIND) && (nodeName.equals(attrNodeKindTestNodeName)) 
+                                                                              && (SequenceTypeSupport.isTwoXmlNamespacesEqual(nodeNsUri, seqTypeKindTest.getNodeNsUri()))) {
+                           nodeSetSequenceTypeKindTestResultList.add(Boolean.valueOf(true));    
+                       }
+                       else if ((seqTypeKindTest.getKindVal() == SequenceTypeSupport.NODE_KIND) || (seqTypeKindTest.getKindVal() == SequenceTypeSupport.ITEM_KIND)) {
+                           nodeSetSequenceTypeKindTestResultList.add(Boolean.valueOf(true));   
+                       }   
+                    }
+                    else {
+                       isInstanceOf = false;
+                       break;
+                    } 
+                 }
+                 else if (dtm.getNodeType(nextNodeDtmHandle) == DTM.TEXT_NODE) {
+                    if (seqTypeKindTest.getKindVal() == SequenceTypeSupport.TEXT_KIND) {
+                       nodeSetSequenceTypeKindTestResultList.add(Boolean.valueOf(true)); 
+                    }
+                 }
+                 else if (dtm.getNodeType(nextNodeDtmHandle) == DTM.NAMESPACE_NODE) {
+                    if (seqTypeKindTest.getKindVal() == SequenceTypeSupport.NAMESPACE_NODE_KIND) {
+                       nodeSetSequenceTypeKindTestResultList.add(Boolean.valueOf(true)); 
+                    }
+                 }
+             }
+             
+             if (nodeSetSequenceTypeKindTestResultList.size() > 0 && (nodeSetSequenceTypeKindTestResultList.size() == nodeSetLen)) {
+                isInstanceOf = true; 
+             }
+          }
+      }
+      else if (xdmValue instanceof ResultSequence) {
+          ResultSequence srcResultSeq = (ResultSequence)xdmValue;
+          
+          int seqLen = srcResultSeq.size();
+          
+          if ((seqLen == 0) && (seqTypedData.getItemTypeOccurrenceIndicator() == OccurenceIndicator.ONE_OR_MANY)) {
+             isInstanceOf = false;  
+          }
+          else if ((seqLen > 0) && (seqTypedData.getSequenceType() == SequenceTypeSupport.EMPTY_SEQUENCE)) {
+             isInstanceOf = false;  
+          }
+          else if ((seqLen > 1) && (seqTypedData.getItemTypeOccurrenceIndicator() == OccurenceIndicator.ZERO_OR_ONE)) {
+             isInstanceOf = false;
+          }
+          
+          SequenceTypeData sequenceTypeDataNew = new SequenceTypeData();          
+          if (seqTypedData.getSequenceTypeKindTest() != null) {
+             sequenceTypeDataNew.setSequenceTypeKindTest(seqTypedData.getSequenceTypeKindTest()); 
+          }
+          else {
+             sequenceTypeDataNew.setSequenceType(seqTypedData.getSequenceType()); 
+          }
+          
+          boolean isInstanceOfOnSeqItem = true;
+          
+          for (int idx = 0; idx < srcResultSeq.size(); idx++) {
+             XObject seqItem = (XObject)(srcResultSeq.item(idx));
+             // Recursive call to this function
+             if (!isInstanceOf(seqItem, sequenceTypeDataNew)) {
+                isInstanceOfOnSeqItem = false;
+                break;
+             }
+          }
+          
+          isInstanceOf = isInstanceOfOnSeqItem; 
+      }
+    
+      return isInstanceOf;
+  }
 }
diff --git a/src/org/apache/xpath/xs/types/XSTime.java b/src/org/apache/xpath/xs/types/XSTime.java
index ab7d770c..7c508f9d 100644
--- a/src/org/apache/xpath/xs/types/XSTime.java
+++ b/src/org/apache/xpath/xs/types/XSTime.java
@@ -20,6 +20,8 @@ import java.util.Calendar;
 import java.util.GregorianCalendar;
 import java.util.TimeZone;
 
+import javax.xml.transform.TransformerException;
+
 import org.apache.xpath.objects.ResultSequence;
 
 /**
@@ -73,9 +75,36 @@ public class XSTime extends XSCalendarType {
     }
 
     @Override
-    public ResultSequence constructor(ResultSequence arg) {
-        // TO DO
-        return null;
+    public ResultSequence constructor(ResultSequence arg) throws TransformerException {
+        ResultSequence resultSeq = new ResultSequence();
+        
+        if (arg.size() == 0) {
+           return resultSeq;     
+        }
+        
+        XSAnyType xsAnyType = (XSAnyType)arg.item(0);        
+        XSTime xsTime = castToTime(xsAnyType);
+        
+        resultSeq.add(xsTime);
+        
+        return resultSeq;
+    }
+    
+    /**
+     * Parse a string representation of a time value, and construct an new 
+     * XSTime object.
+     */
+    public static XSTime parseTime(String strVal) throws TransformerException {
+
+        String refDate = "1955-07-12T";
+        
+        XSDateTime xsDateTime = XSDateTime.parseDateTime(refDate + strVal);
+        if (xsDateTime == null) {
+           throw new TransformerException("XTTE0570 : The supplied string value '" + strVal + "' "
+                                                                       + "cannot be parsed to a xs:time value.");
+        }
+
+        return new XSTime(xsDateTime.getCalendar(), xsDateTime.getTimezone());
     }
     
     /**
@@ -109,7 +138,27 @@ public class XSTime extends XSCalendarType {
     }
     
     /**
-     * Get the seconds value as an integer stored within this 
+     * Get the hour value stored as an integer within this
+     * XSTime object.
+     * 
+     * @return   the hour value stored
+     */
+    public int hour() {
+        return _calendar.get(Calendar.HOUR_OF_DAY);
+    }
+
+    /**
+     * Get the minute value stored as an integer within this
+     * XSTime object.
+     * 
+     * @return   the minute value stored
+     */
+    public int minute() {
+        return _calendar.get(Calendar.MINUTE);
+    }
+    
+    /**
+     * Get the second value stored as an integer within this
      * XSTime object.
      * 
      * @return    the seconds value stored
@@ -190,5 +239,26 @@ public class XSTime extends XSCalendarType {
     public int getType() {
         return CLASS_XS_TIME;
     }
+    
+    /**
+     * Do a data type cast, of an XSAnyType argument passed to this method, to
+     * an XSTime object.
+     */
+    private XSTime castToTime(XSAnyType xsAnyType) throws TransformerException {        
+        XSTime xsTime = null;
+        
+        if (xsAnyType instanceof XSTime) {
+           xsTime = (XSTime)xsAnyType;
+        }        
+        else if (xsAnyType instanceof XSDateTime) {
+           XSDateTime xsDateTime = (XSDateTime)xsAnyType;
+           xsTime = new XSTime(xsDateTime.getCalendar(), xsDateTime.getTimezone());
+        }
+        else {
+           xsTime = parseTime(xsAnyType.stringValue());
+        }
+        
+        return xsTime;
+    }
 
 }
diff --git a/tests/fn_data/gold/test1.out b/tests/fn_data/gold/test1.out
new file mode 100644
index 00000000..4f798e91
--- /dev/null
+++ b/tests/fn_data/gold/test1.out
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <one size="5">
+    1
+    a1
+   
+    2
+    a2
+   
+    3
+    a3
+   
+    4
+    a4
+   
+    5
+    a5
+  </one>
+  <two size="6">5 3.2 2 3.2 7 3</two>
+</result>
diff --git a/tests/fn_data/gold/test2.out b/tests/fn_data/gold/test2.out
new file mode 100644
index 00000000..cc31cbf7
--- /dev/null
+++ b/tests/fn_data/gold/test2.out
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <info count="8">
+    <val type="untypedAtomic">5</val>
+    <val type="untypedAtomic">3.2</val>
+    <val type="untypedAtomic">2</val>
+    <val type="untypedAtomic">3.2</val>
+    <val type="untypedAtomic">7</val>
+    <val type="untypedAtomic">3</val>
+    <val type="date">
+      <date_val/>
+    </val>
+    <val type="integer">5</val>
+  </info>
+</result>
diff --git a/tests/fn_data/test1.xsl b/tests/fn_data/test1.xsl
new file mode 100644
index 00000000..f90d5848
--- /dev/null
+++ b/tests/fn_data/test1.xsl
@@ -0,0 +1,45 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+  <!-- Author: mukulg@apache.org -->
+  
+  <!-- use with test1_a.xml -->
+  
+  <!-- An XSLT stylesheet test case, to test XPath 3.1 
+       function fn:data. 
+  -->                                               
+                
+  <xsl:output method="xml" indent="yes"/>
+
+  <xsl:template match="/products">
+     <result>        
+        <xsl:variable name="seq1" select="data(product)"/>
+        <xsl:variable name="seq2" select="data(.//@*)"/>
+        <one size="{count($seq1)}">
+           <xsl:copy-of select="$seq1"/>
+        </one>
+        <two size="{count($seq2)}">
+           <xsl:copy-of select="$seq2"/>
+        </two>
+     </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_data/test1_a.xml b/tests/fn_data/test1_a.xml
new file mode 100644
index 00000000..ed88f09c
--- /dev/null
+++ b/tests/fn_data/test1_a.xml
@@ -0,0 +1,22 @@
+<products>
+  <product price="5">
+    <id>1</id>
+    <desc>a1</desc>
+  </product>
+  <product cost="3.2">
+    <id>2</id>
+    <desc>a2</desc>
+  </product>
+  <product price="2">
+    <id>3</id>
+    <desc>a3</desc>
+  </product>
+  <product cost="3.2" price="7">
+    <id>4</id>
+    <desc>a4</desc>
+  </product>
+  <product price="3">
+    <id>5</id>
+    <desc>a5</desc>
+  </product>
+</products>
\ No newline at end of file
diff --git a/tests/fn_data/test2.xsl b/tests/fn_data/test2.xsl
new file mode 100644
index 00000000..4914d4d7
--- /dev/null
+++ b/tests/fn_data/test2.xsl
@@ -0,0 +1,59 @@
+<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_a.xml -->
+  
+  <!-- An XSLT stylesheet test case, to test XPath 3.1 
+       function fn:data. 
+  -->                                                  
+                
+  <xsl:output method="xml" indent="yes"/>
+
+  <xsl:template match="/products">
+     <result>        
+        <xsl:variable name="seq1" select="(data(.//@*), current-date(), xs:integer(5))"/>
+        <info count="{count($seq1)}">
+           <xsl:for-each select="$seq1">
+               <xsl:variable name="ctxItem" select="."/>
+               <xsl:choose>
+                  <xsl:when test="$ctxItem instance of xs:date">
+                     <val type="date"><date_val/></val>
+                  </xsl:when>
+                  <xsl:when test="$ctxItem instance of xs:integer">
+	                 <val type="integer"><xsl:value-of select="$ctxItem"/></val>
+                  </xsl:when>
+                  <xsl:when test="$ctxItem instance of xs:untypedAtomic">
+	                 <val type="untypedAtomic"><xsl:value-of select="$ctxItem"/></val>
+                  </xsl:when>
+                  <xsl:otherwise>
+                     <val type="other"><xsl:value-of select="$ctxItem"/></val>
+                  </xsl:otherwise>
+               </xsl:choose>
+            </xsl:for-each>
+        </info>
+     </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/FnDataTests.java b/tests/org/apache/xalan/xpath3/FnDataTests.java
new file mode 100644
index 00000000..4ea60dfd
--- /dev/null
+++ b/tests/org/apache/xalan/xpath3/FnDataTests.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xalan.xpath3;
+
+import org.apache.xalan.util.XslTransformTestsUtil;
+import org.apache.xalan.xslt3.XSLConstants;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * XPath 3.1 function fn:data test cases.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FnDataTests extends XslTransformTestsUtil {        
+    
+    private static final String XSL_TRANSFORM_INPUT_DIRPATH = XSLConstants.XSL_TRANSFORM_INPUT_DIRPATH_PREFIX + 
+                                                                                                           "fn_data/";
+    
+    private static final String XSL_TRANSFORM_GOLD_DIRPATH = XSLConstants.XSL_TRANSFORM_GOLD_DIRPATH_PREFIX + 
+                                                                                                          "fn_data/gold/";
+
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+        // no op
+    }
+
+    @AfterClass
+    public static void tearDownAfterClass() throws Exception {        
+        xmlDocumentBuilderFactory = null;
+        xmlDocumentBuilder = null;
+        xslTransformerFactory = null;
+    }
+
+    @Test
+    public void xslFnDataTest1() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_a.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test1.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslFnDataTest2() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_a.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test2.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test2.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+
+}
diff --git a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
index de2b18a4..aede2310 100644
--- a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
+++ b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
@@ -24,6 +24,7 @@ import org.apache.xalan.xpath3.FnCodepointEqualTests;
 import org.apache.xalan.xpath3.FnCodepointsToStringTests;
 import org.apache.xalan.xpath3.FnCompareTests;
 import org.apache.xalan.xpath3.FnContainsTokenTests;
+import org.apache.xalan.xpath3.FnDataTests;
 import org.apache.xalan.xpath3.FnDistinctValuesTests;
 import org.apache.xalan.xpath3.FnDocTests;
 import org.apache.xalan.xpath3.FnFilterTests;
@@ -96,7 +97,8 @@ import org.junit.runners.Suite.SuiteClasses;
                 SequenceFunctionTests.class, FnParseXmlTests.class, FnParseXmlFragmentTests.class,
                 TemplateTests.class, FnAvgTests.class, FnMaxTests.class, FnMinTests.class, FnContainsTokenTests.class,
                 XslVariableAttributeAsTests.class, InstanceOfExprTests.class, XslTemplateAttributeAsTests.class,
-                XslFunctionTests.class, FnRoundTests.class, XslSequenceInstTests.class, FnDocTests.class })
+                XslFunctionTests.class, FnRoundTests.class, XslSequenceInstTests.class, FnDocTests.class,
+                FnDataTests.class })
 public class AllXsl3Tests {
 
 }


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