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/16 14:27:26 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing implementation of xpath 3.1 function fn:doc, and a related working new test case. also committing few minor codebase improvements on this xalanj 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 962bab95 committing implementation of xpath 3.1 function fn:doc, and a related working new test case. also committing few minor codebase improvements on this xalanj branch.
     new 0de3c604 Merge pull request #86 from mukulga/xalan-j_xslt3.0_mukul
962bab95 is described below

commit 962bab951fa40e7e753e2ffb9e39659c4a8b18ba
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sat Sep 16 19:54:16 2023 +0530

    committing implementation of xpath 3.1 function fn:doc, and a related working new test case. also committing few minor codebase improvements on this xalanj branch.
---
 src/org/apache/xpath/compiler/FunctionTable.java   |  10 +-
 src/org/apache/xpath/compiler/Keywords.java        |   3 +
 src/org/apache/xpath/functions/FuncDoc.java        | 113 +++++++++++++++++++++
 src/org/apache/xpath/functions/FuncParseXml.java   |  47 ++++-----
 .../xpath/functions/FuncParseXmlFragment.java      |  10 +-
 .../apache/xpath/functions/FuncUnparsedText.java   |  81 ++++++++-------
 .../apache/xpath/operations/NodeComparisonIs.java  |   2 +-
 tests/fn_doc/gold/test1.out                        |  27 +++++
 tests/fn_doc/test1.xsl                             |  50 +++++++++
 tests/fn_doc/test1_a.xml                           |  22 ++++
 tests/fn_doc/test1_b.xml                           |  22 ++++
 tests/org/apache/xalan/xpath3/FnDocTests.java      |  60 +++++++++++
 tests/org/apache/xalan/xslt3/AllXsl3Tests.java     |   3 +-
 13 files changed, 378 insertions(+), 72 deletions(-)

diff --git a/src/org/apache/xpath/compiler/FunctionTable.java b/src/org/apache/xpath/compiler/FunctionTable.java
index 0b72faac..78b58f4e 100644
--- a/src/org/apache/xpath/compiler/FunctionTable.java
+++ b/src/org/apache/xpath/compiler/FunctionTable.java
@@ -320,6 +320,9 @@ public class FunctionTable
   
   /** The 'contains-token()' id. */
   public static final int FUNC_CONTAINS_TOKEN = 98;
+  
+  /** The 'doc()' id. */
+  public static final int FUNC_DOC = 99;
 
   // Proprietary
 
@@ -377,7 +380,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 = 99;
+  private static final int NUM_BUILT_IN_FUNCS = 100;
 
   /**
    * Number of built-in functions that may be added.
@@ -574,6 +577,8 @@ public class FunctionTable
     m_functions[FUNC_AVG] = org.apache.xpath.functions.FuncAvg.class;
     m_functions[FUNC_MAX] = org.apache.xpath.functions.FuncMax.class;
     m_functions[FUNC_MIN] = org.apache.xpath.functions.FuncMin.class;
+    
+    m_functions[FUNC_DOC] = org.apache.xpath.functions.FuncDoc.class;
   }
 
   static{
@@ -780,6 +785,9 @@ public class FunctionTable
                          new Integer(FunctionTable.FUNC_MAX));
          m_functionID.put(Keywords.FUNC_MIN,
                          new Integer(FunctionTable.FUNC_MIN));
+         
+         m_functionID.put(Keywords.FUNC_DOC,
+                         new Integer(FunctionTable.FUNC_DOC));
   }
   
   public FunctionTable(){
diff --git a/src/org/apache/xpath/compiler/Keywords.java b/src/org/apache/xpath/compiler/Keywords.java
index cf7a46dc..8169df1a 100644
--- a/src/org/apache/xpath/compiler/Keywords.java
+++ b/src/org/apache/xpath/compiler/Keywords.java
@@ -434,6 +434,9 @@ public class Keywords
   /** min function string. */
   public static final String FUNC_MIN = "min";
   
+  /** doc function string. */
+  public static final String FUNC_DOC = "doc";
+  
   // Proprietary, built in functions
 
   /** current function string (Proprietary). */
diff --git a/src/org/apache/xpath/functions/FuncDoc.java b/src/org/apache/xpath/functions/FuncDoc.java
new file mode 100644
index 00000000..99d7d6a5
--- /dev/null
+++ b/src/org/apache/xpath/functions/FuncDoc.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xpath.functions;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import javax.xml.transform.SourceLocator;
+
+import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
+import org.apache.xpath.ExpressionNode;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.XObject;
+
+/**
+ * Implementation of the doc() function.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FuncDoc extends FunctionOneArg {
+
+    private static final long serialVersionUID = -7132184569695971726L;
+
+    /**
+     * 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 {        
+        
+        XObject result = null;
+        
+        SourceLocator srcLocator = xctxt.getSAXLocator();
+
+        XObject xObject0 = m_arg0.execute(xctxt);
+            
+        String hrefStrVal = XslTransformEvaluationHelper.getStrVal(xObject0);
+            
+        // If the first argument is a relative uri reference, then 
+        // resolve that relative uri with base uri of the stylesheet
+        URL resolvedArg0Url = null;
+
+        try {
+           URI arg0Uri = new URI(hrefStrVal);
+           String stylesheetSystemId = null;
+           if (srcLocator != null) {
+              stylesheetSystemId = srcLocator.getSystemId();
+           }
+           else {
+              ExpressionNode expressionNode = getExpressionOwner();
+              stylesheetSystemId = expressionNode.getSystemId(); 
+           }
+                        
+           if (!arg0Uri.isAbsolute() && (stylesheetSystemId != null)) {
+              URI resolvedUriArg = (new URI(stylesheetSystemId)).resolve(hrefStrVal);
+              resolvedArg0Url = resolvedUriArg.toURL(); 
+           }
+                
+            if (resolvedArg0Url == null) {
+               resolvedArg0Url = new URL(hrefStrVal);   
+            }
+                
+            String urlStrContents = FuncUnparsedText.readStrDataFromUrl(resolvedArg0Url);
+                
+            result = FuncParseXml.getNodeSetFromStr(urlStrContents, xctxt);
+        }
+        catch (URISyntaxException ex) {
+           throw new javax.xml.transform.TransformerException("FODC0005 : The uri '" + hrefStrVal + "' is not a valid absolute uri, "
+                                                                                                + "or cannot be resolved to an absolute uri.", srcLocator); 
+        }
+        catch (MalformedURLException ex) {
+           throw new javax.xml.transform.TransformerException("FODC0005 : The uri '" + hrefStrVal + "' is not a valid absolute uri, "
+                                                                                                + "or cannot be resolved to an absolute uri.", srcLocator); 
+        }
+        catch (IOException ex) {
+           throw new javax.xml.transform.TransformerException("FODC0002 : The data from uri '" + hrefStrVal + "' cannot be "
+                                                                                                                      + "retrieved.", srcLocator);
+        }
+        catch (javax.xml.transform.TransformerException ex) {
+           throw new javax.xml.transform.TransformerException("FODC0002 : The data from uri '" + hrefStrVal + "' cannot be successfully "
+                                                                                                                      + "parsed as an XML document.", srcLocator); 
+        }
+        catch (Exception ex) {
+           throw new javax.xml.transform.TransformerException("FODC0002 : The data from uri '" + hrefStrVal + "' cannot be successfully "
+                                                                                                                      + "parsed as an XML document.", srcLocator); 
+        }
+        
+        return result;
+    }
+
+}
diff --git a/src/org/apache/xpath/functions/FuncParseXml.java b/src/org/apache/xpath/functions/FuncParseXml.java
index f862493f..e40fd240 100644
--- a/src/org/apache/xpath/functions/FuncParseXml.java
+++ b/src/org/apache/xpath/functions/FuncParseXml.java
@@ -57,15 +57,17 @@ public class FuncParseXml extends FunctionOneArg {
         
         SourceLocator srcLocator = xctxt.getSAXLocator();
 
-        try {
-            XObject xObject0 = m_arg0.execute(xctxt);
+        XObject xObject0 = m_arg0.execute(xctxt);
             
-            String argStrVal = XslTransformEvaluationHelper.getStrVal(xObject0);
+        String argStrVal = XslTransformEvaluationHelper.getStrVal(xObject0);
             
-            result = getNodeSetFromStr(argStrVal, xctxt);
-        }
-        catch (javax.xml.transform.TransformerException ex) {
-            throw new javax.xml.transform.TransformerException(ex.getMessage(), srcLocator);   
+        try {
+           result = getNodeSetFromStr(argStrVal, xctxt);
+        } 
+        catch (Exception ex) {
+           throw new javax.xml.transform.TransformerException("FODC0002 : The string value supplied as an "
+                                                                                  + "argument to function fn:parse-xml(), cannot be "
+                                                                                  + "successfully parsed as an XML document.", srcLocator);
         }
         
         return result;
@@ -74,31 +76,24 @@ public class FuncParseXml extends FunctionOneArg {
     /**
      * Get an XDM nodeset corresponding to an XML string value.
      */
-    private XNodeSet getNodeSetFromStr(String strVal, XPathContext xctxt) throws 
-                                                          javax.xml.transform.TransformerException {
+    public static XNodeSet getNodeSetFromStr(String strVal, XPathContext xctxt) throws Exception {
         XNodeSet nodeSet = null;
-        
-        try {
-            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
             
-            // Make the XML namespace processing active, on an XML parse 
-            // of the string value.
-            dbf.setNamespaceAware(true);         
+        // Enable the XML namespace processing, on an XML parse 
+        // of the string value.
+        dbf.setNamespaceAware(true);         
             
-            DocumentBuilder dBuilder = dbf.newDocumentBuilder();
+        DocumentBuilder dBuilder = dbf.newDocumentBuilder();
             
-            InputStream inpStream = new ByteArrayInputStream(strVal.getBytes(
-                                                                      StandardCharsets.UTF_8));
-            Document xmlDocument = dBuilder.parse(inpStream);
+        InputStream inpStream = new ByteArrayInputStream(strVal.getBytes(StandardCharsets.UTF_8));
+        Document xmlDocument = dBuilder.parse(inpStream);
             
-            DTM dtm = xctxt.getDTM(new DOMSource(xmlDocument), true, null, false, false);            
-            int documentNodeHandleVal = dtm.getDocument();
+        DTM dtm = xctxt.getDTM(new DOMSource(xmlDocument), true, null, false, false);            
+        int documentNodeHandleVal = dtm.getDocument();
             
-            nodeSet = new XNodeSet(documentNodeHandleVal, xctxt.getDTMManager());
-        }
-        catch (Exception ex) {
-           throw new javax.xml.transform.TransformerException("FODC0006 : " + ex.getMessage()); 
-        }
+        nodeSet = new XNodeSet(documentNodeHandleVal, xctxt.getDTMManager());
         
         return nodeSet;
     }
diff --git a/src/org/apache/xpath/functions/FuncParseXmlFragment.java b/src/org/apache/xpath/functions/FuncParseXmlFragment.java
index fe773d3e..70975e62 100644
--- a/src/org/apache/xpath/functions/FuncParseXmlFragment.java
+++ b/src/org/apache/xpath/functions/FuncParseXmlFragment.java
@@ -83,7 +83,7 @@ public class FuncParseXmlFragment extends FunctionOneArg {
         try {
             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
             
-            // Make the XML namespace processing active, on an XML parse 
+            // Enable the XML namespace processing, on an XML parse 
             // of the string value.
             dbf.setNamespaceAware(true);         
             
@@ -93,8 +93,8 @@ public class FuncParseXmlFragment extends FunctionOneArg {
             // string value), with a temporary XML outer element.
             String currentTimeMillisec = String.valueOf(System.currentTimeMillis());
             String tempOuterWrapperElementName = "t0_" + currentTimeMillisec;            
-            String wrappedXmlStrVal = "<"+tempOuterWrapperElementName+">" + strVal + 
-                                                                              "</"+tempOuterWrapperElementName+">"; 
+            String wrappedXmlStrVal = "<" + tempOuterWrapperElementName + ">" + strVal + 
+                                                                                     "</" + tempOuterWrapperElementName+">"; 
             
             InputStream inpStream = new ByteArrayInputStream(wrappedXmlStrVal.getBytes(
                                                                                     StandardCharsets.UTF_8));
@@ -113,7 +113,9 @@ public class FuncParseXmlFragment extends FunctionOneArg {
             nodeSet = new XNodeSet(documentNodeHandleVal, xctxt.getDTMManager());
         }
         catch (Exception ex) {
-           throw new javax.xml.transform.TransformerException("FODC0006 : " + ex.getMessage()); 
+           throw new javax.xml.transform.TransformerException("FODC0002 : The string value supplied as an argument to function "
+                                                                                         + "fn:parse-xml-fragment(), cannot be successfully "
+                                                                                         + "parsed as an XML document fragment."); 
         }
         
         return nodeSet;
diff --git a/src/org/apache/xpath/functions/FuncUnparsedText.java b/src/org/apache/xpath/functions/FuncUnparsedText.java
index 11e60f80..fbd6257d 100644
--- a/src/org/apache/xpath/functions/FuncUnparsedText.java
+++ b/src/org/apache/xpath/functions/FuncUnparsedText.java
@@ -24,6 +24,7 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -31,18 +32,14 @@ import java.net.URL;
 import javax.xml.transform.SourceLocator;
 
 import org.apache.xalan.res.XSLMessages;
-import org.apache.xml.utils.XMLString;
+import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
 import org.apache.xpath.XPathContext;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XString;
 import org.apache.xpath.res.XPATHErrorResources;
 
 /**
- * Execute the unparsed-text() function.
- * 
- * This function is designed, to read from an external resource 
- * (for example, a file) and returns a string representation 
- * of the resource.
+ * Implementation of the unparsed-text() function.
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
@@ -65,61 +62,67 @@ public class FuncUnparsedText extends Function2Args {
       XObject result = null;
       
       SourceLocator srcLocator = xctxt.getSAXLocator();
+      
+      XObject arg0Result = m_arg0.execute(xctxt);
         
-      XMLString href = m_arg0.execute(xctxt).xstr();
+      String hrefStrVal = XslTransformEvaluationHelper.getStrVal(arg0Result);
       
       String encodingStr = null;
         
       if (m_arg1 != null) {
-         XMLString encoding = m_arg1.execute(xctxt).xstr();
-         encodingStr = encoding.toString();
+         XObject arg1Result = m_arg1.execute(xctxt);
+         encodingStr = XslTransformEvaluationHelper.getStrVal(arg1Result);
          if (!("utf-8".equalsIgnoreCase(encodingStr) || "utf-16".equalsIgnoreCase(encodingStr))) {
              throw new javax.xml.transform.TransformerException("FOUT1190 : The value of the 'encoding' argument "
-                                                   + "is not a valid encoding name. Allowed encoding names are "
-                                                   + "UTF-8 and UTF-16.", srcLocator);    
+                                                                                    + "is not a valid encoding name. Allowed encoding names are "
+                                                                                    + "UTF-8 and UTF-16.", srcLocator);    
          }
       }
-        
-     try {                                                           
-          // if the first argument is a, relative uri reference, then 
-          // resolve that relative uri with base uri of the stylesheet
-          URL resolvedArg0Url = null;
-          
-          try {
-              URI arg0Uri = new URI(href.toString());
-              String stylesheetSystemId = srcLocator.getSystemId();  // base uri of stylesheet, if available
-              
-              if (!arg0Uri.isAbsolute() && stylesheetSystemId != null) {
-                  URI resolvedUriArg = (new URI(stylesheetSystemId)).resolve(href.toString());
-                  resolvedArg0Url = resolvedUriArg.toURL(); 
-              }
-          }
-          catch (URISyntaxException ex) {
-              throw new javax.xml.transform.TransformerException(ex.getMessage(), srcLocator);    
+                                                         
+      // If the first argument is a relative uri reference, then 
+      // resolve that relative uri with base uri of the stylesheet
+      URL resolvedArg0Url = null;
+
+      try {
+          URI arg0Uri = new URI(hrefStrVal);
+          String stylesheetSystemId = srcLocator.getSystemId();  // base uri of stylesheet, if available
+                  
+          if (!arg0Uri.isAbsolute() && (stylesheetSystemId != null)) {
+             URI resolvedUriArg = (new URI(stylesheetSystemId)).resolve(hrefStrVal);
+             resolvedArg0Url = resolvedUriArg.toURL(); 
           }
-          
+              
           if (resolvedArg0Url == null) {
-              resolvedArg0Url = new URL(href.toString());   
+             resolvedArg0Url = new URL(hrefStrVal);   
           }
-          
-          String urlContents = readDataFromUrl(resolvedArg0Url);
-          
+              
+          String urlStrContents = readStrDataFromUrl(resolvedArg0Url);
+              
           String resultStr = null;
           if (encodingStr != null) {
-              resultStr = new String(urlContents.getBytes(), encodingStr.toUpperCase());              
+             resultStr = new String(urlStrContents.getBytes(), encodingStr.toUpperCase());              
           }
           else {
-              resultStr = urlContents;  
+             resultStr = urlStrContents;  
           }
-          
+              
           result = new XString(resultStr);
       }
+      catch (URISyntaxException ex) {
+          throw new javax.xml.transform.TransformerException("FODC0005 : The uri '" + hrefStrVal + "' is not a valid absolute uri, "
+                                                                                              + "or cannot be resolved to an absolute uri.", srcLocator);  
+      }
+      catch (MalformedURLException ex) {
+          throw new javax.xml.transform.TransformerException("FODC0005 : The uri '" + hrefStrVal + "' is not a valid absolute uri, "
+                                                                                              + "or cannot be resolved to an absolute uri.", srcLocator);
+      }
       catch (IOException ex) {
-         throw new javax.xml.transform.TransformerException(ex.getMessage(), srcLocator);  
+          throw new javax.xml.transform.TransformerException("FODC0002 : The data from uri '" + hrefStrVal + "' cannot be "
+                                                                                                                     + "retrieved.", srcLocator);
       }
         
       return result;
-
+      
   }
   
   
@@ -152,7 +155,7 @@ public class FuncUnparsedText extends Function2Args {
   /*
    * Read the string contents from a url.
    */
-  private String readDataFromUrl(URL url) throws IOException {
+  public static String readStrDataFromUrl(URL url) throws IOException {
       StringBuilder strBuilder = new StringBuilder();
       
       InputStream inpStream = url.openStream();
diff --git a/src/org/apache/xpath/operations/NodeComparisonIs.java b/src/org/apache/xpath/operations/NodeComparisonIs.java
index f631a847..ea073b5b 100644
--- a/src/org/apache/xpath/operations/NodeComparisonIs.java
+++ b/src/org/apache/xpath/operations/NodeComparisonIs.java
@@ -86,7 +86,7 @@ public class NodeComparisonIs extends Operation
           result = (lNodeHandle == rNodeHandle) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
        }
        else {
-          // as per XPath 3.1 spec for the node comparison "is" operator, if either operand 
+          // As per XPath 3.1 spec for the node comparison "is" operator, if either operand 
           // is an empty sequence the result of the comparison is an empty sequence.
           result = new ResultSequence();  
        }
diff --git a/tests/fn_doc/gold/test1.out b/tests/fn_doc/gold/test1.out
new file mode 100644
index 00000000..f57c988b
--- /dev/null
+++ b/tests/fn_doc/gold/test1.out
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?><products>
+  <product price="5">
+    <id>1</id>
+    <desc>a1</desc>
+    <material>iron</material>
+  </product>
+  <product cost="3.2">
+    <id>2</id>
+    <desc>a2</desc>
+    <material>copper</material>
+  </product>
+  <product price="2">
+    <id>3</id>
+    <desc>a3</desc>
+    <material>wood</material>
+  </product>
+  <product price="7">
+    <id>4</id>
+    <desc>a4</desc>
+    <material>chromium</material>
+  </product>
+  <product price="3">
+    <id>5</id>
+    <desc>a5</desc>
+    <material>iron</material>
+  </product>
+</products>
diff --git a/tests/fn_doc/test1.xsl b/tests/fn_doc/test1.xsl
new file mode 100644
index 00000000..8ab4668e
--- /dev/null
+++ b/tests/fn_doc/test1.xsl
@@ -0,0 +1,50 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- use with test1_a.xml -->
+   
+   <!-- Test for the XPath 3.1 fn:doc() function.
+        This stylesheet does join of XML document data
+        from two XML documents, based on product data's 
+        'id' value.
+   -->                                                
+                
+   <xsl:output method="xml" indent="yes"/>
+  
+   <xsl:variable name="doc2" select="doc('test1_b.xml')"/>
+
+   <xsl:template match="/products">
+      <products>        
+         <xsl:apply-templates select="product"/>
+      </products>
+   </xsl:template>
+  
+   <xsl:template match="product">    
+      <product>
+         <xsl:copy-of select="@*"/>
+         <xsl:copy-of select="*"/>
+         <xsl:copy-of select="$doc2/products/product[id = current()/id]/material"/>
+      </product>
+   </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_doc/test1_a.xml b/tests/fn_doc/test1_a.xml
new file mode 100644
index 00000000..518fcd98
--- /dev/null
+++ b/tests/fn_doc/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 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_doc/test1_b.xml b/tests/fn_doc/test1_b.xml
new file mode 100644
index 00000000..155a1fbf
--- /dev/null
+++ b/tests/fn_doc/test1_b.xml
@@ -0,0 +1,22 @@
+<products>
+  <product>
+    <id>1</id>
+    <material>iron</material>
+  </product>
+  <product>
+    <id>2</id>
+    <material>copper</material>
+  </product>
+  <product>
+    <id>3</id>
+    <material>wood</material>
+  </product>
+  <product>
+    <id>4</id>
+    <material>chromium</material>
+  </product>
+  <product>
+    <id>5</id>
+    <material>iron</material>
+  </product>
+</products>
\ No newline at end of file
diff --git a/tests/org/apache/xalan/xpath3/FnDocTests.java b/tests/org/apache/xalan/xpath3/FnDocTests.java
new file mode 100644
index 00000000..5d07bf3b
--- /dev/null
+++ b/tests/org/apache/xalan/xpath3/FnDocTests.java
@@ -0,0 +1,60 @@
+/*
+ * 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:doc test cases.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FnDocTests extends XslTransformTestsUtil {        
+    
+    private static final String XSL_TRANSFORM_INPUT_DIRPATH = XSLConstants.XSL_TRANSFORM_INPUT_DIRPATH_PREFIX + "fn_doc/";
+    
+    private static final String XSL_TRANSFORM_GOLD_DIRPATH = XSLConstants.XSL_TRANSFORM_GOLD_DIRPATH_PREFIX + "fn_doc/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 xslFnDocTest1() {
+        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);
+    }
+
+}
diff --git a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
index e636536c..de2b18a4 100644
--- a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
+++ b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
@@ -25,6 +25,7 @@ import org.apache.xalan.xpath3.FnCodepointsToStringTests;
 import org.apache.xalan.xpath3.FnCompareTests;
 import org.apache.xalan.xpath3.FnContainsTokenTests;
 import org.apache.xalan.xpath3.FnDistinctValuesTests;
+import org.apache.xalan.xpath3.FnDocTests;
 import org.apache.xalan.xpath3.FnFilterTests;
 import org.apache.xalan.xpath3.FnFoldLeftTests;
 import org.apache.xalan.xpath3.FnFoldRightTests;
@@ -95,7 +96,7 @@ 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 })
+                XslFunctionTests.class, FnRoundTests.class, XslSequenceInstTests.class, FnDocTests.class })
 public class AllXsl3Tests {
 
 }


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