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 2025/04/04 11:41:41 UTC

(xalan-java) branch xalan-j_xslt3.0_mvn updated: committing implementation improvements to xalan-j xpath 3.1 function fn:transform, along with a working related test case

This is an automated email from the ASF dual-hosted git repository.

mukulg pushed a commit to branch xalan-j_xslt3.0_mvn
in repository https://gitbox.apache.org/repos/asf/xalan-java.git


The following commit(s) were added to refs/heads/xalan-j_xslt3.0_mvn by this push:
     new b05b03d50 committing implementation improvements to xalan-j xpath 3.1 function fn:transform, along with a working related test case
b05b03d50 is described below

commit b05b03d50516d423c74c11a3896111849e8bb8cc
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Fri Apr 4 17:11:27 2025 +0530

    committing implementation improvements to xalan-j xpath 3.1 function fn:transform, along with a working related test case
---
 README                                             |   6 +-
 .../org/apache/xalan/templates/ElemCopyOf.java     |  21 ++-
 .../apache/xalan/templates/ElemResultDocument.java | 171 ++++++++++++++++++---
 .../org/apache/xalan/templates/ElemVariable.java   |   3 +-
 .../apache/xalan/transformer/TransformerImpl.java  |   3 -
 .../xalan/transformer/TreeWalker2Result.java       |   5 +-
 .../org/apache/xpath/functions/FuncTransform.java  |  51 +++---
 .../apache/xpath/objects/XMLNodeCursorImpl.java    |  15 ++
 .../xalan/tests/xpath3/FnTransformTests.java       |  10 ++
 src/test/resources/fn_transform/gold/test10.out    |  18 +++
 src/test/resources/fn_transform/render.xsl         |  23 +++
 src/test/resources/fn_transform/render2.xsl        |  52 +++++++
 src/test/resources/fn_transform/test10.xsl         |  68 ++++++++
 13 files changed, 393 insertions(+), 53 deletions(-)

diff --git a/README b/README
index 9e5975ee7..5d1b8dd43 100644
--- a/README
+++ b/README
@@ -17,7 +17,7 @@
 
 Copyright 1999-2025 The Apache Software Foundation
 
-Document last modified : 2025-04-03
+Document last modified : 2025-04-04
 
 Authors:
    Gary Gregory <gg...@apache.org>
@@ -59,11 +59,11 @@ This produces Maven build output with trailing information like following:
 [INFO]  T E S T S
 [INFO] -------------------------------------------------------
 [INFO] Running org.apache.xalan.tests.main.AllXsl3Tests
-[INFO] Tests run: 973, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 25.413 s - in org.apache.xalan.tests.main.AllXsl3Tests
+[INFO] Tests run: 974, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 27.743 s - in org.apache.xalan.tests.main.AllXsl3Tests
 [INFO]
 [INFO] Results:
 [INFO]
-[INFO] Tests run: 973, Failures: 0, Errors: 0, Skipped: 0
+[INFO] Tests run: 974, Failures: 0, Errors: 0, Skipped: 0
 [INFO]
 [INFO] ------------------------------------------------------------------------
 [INFO] BUILD SUCCESS
diff --git a/src/main/java/org/apache/xalan/templates/ElemCopyOf.java b/src/main/java/org/apache/xalan/templates/ElemCopyOf.java
index d98030718..cad0525b4 100644
--- a/src/main/java/org/apache/xalan/templates/ElemCopyOf.java
+++ b/src/main/java/org/apache/xalan/templates/ElemCopyOf.java
@@ -66,8 +66,6 @@ import xml.xpath31.processor.types.XSUntypedAtomic;
 /**
  * Implementation of XSLT xsl:copy-of instruction.
  * 
- * Ref : https://www.w3.org/TR/xslt-30/#element-copy-of
- * 
  * @author Scott Boag <sc...@us.ibm.com>
  * @author Morris Kwan <mk...@apache.org>
  * @author Christine Li <jy...@apache.org>
@@ -332,14 +330,25 @@ public class ElemCopyOf extends ElemTemplateElement
   public static void copyOfActionOnNodeSet(XMLNodeCursorImpl nodeSet, TransformerImpl transformer, 
                                                                       SerializationHandler serializationHandler, XPathContext xctxt) 
                                                                                throws TransformerException, SAXException {
-      DTMCursorIterator dtmIter = nodeSet.iter();
+	  DTMCursorIterator dtmIter = nodeSet.iter();
 
       DTMTreeWalker tw = new TreeWalker2Result(transformer, serializationHandler);
       int pos;
+      
+      DTM dtm1 = nodeSet.getDtm();
 
-      while ((pos = dtmIter.nextNode()) != DTM.NULL) {
-          DTM dtm = xctxt.getDTMManager().getDTM(pos);
-          short nodeType = dtm.getNodeType(pos);
+      while ((pos = dtmIter.nextNode()) != DTM.NULL) {    	  
+          DTM dtm = null;
+          
+          if (dtm1 == null) {
+        	  dtm = (xctxt.getDTMManager()).getDTM(pos);  
+          }
+          else {
+        	  dtm = dtm1;
+        	  tw.setDTM(dtm);
+          }                                        
+    	  
+          short nodeType = dtm.getNodeType(pos);  
 
           if (nodeType == DTM.DOCUMENT_NODE) {
         	 // From the 1st XML element node child of document node, validate all 
diff --git a/src/main/java/org/apache/xalan/templates/ElemResultDocument.java b/src/main/java/org/apache/xalan/templates/ElemResultDocument.java
index b95fa3f68..8a64b7062 100644
--- a/src/main/java/org/apache/xalan/templates/ElemResultDocument.java
+++ b/src/main/java/org/apache/xalan/templates/ElemResultDocument.java
@@ -21,37 +21,47 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.StringReader;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.Properties;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.SourceLocator;
 import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
 
 import org.apache.xalan.transformer.TransformerImpl;
 import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
 import org.apache.xml.dtm.DTM;
 import org.apache.xml.dtm.DTMCursorIterator;
+import org.apache.xml.dtm.DTMManager;
 import org.apache.xml.utils.QName;
 import org.apache.xpath.Expression;
 import org.apache.xpath.ExpressionOwner;
 import org.apache.xpath.XPathContext;
+import org.apache.xpath.functions.FuncTransform;
 import org.apache.xpath.objects.XMLNodeCursorImpl;
 import org.apache.xpath.objects.XNodeSetForDOM;
+import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XPathMap;
 import org.apache.xpath.objects.XRTreeFrag;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import xml.xpath31.processor.types.XSString;
 
 /**
  * Implementation of the XSLT 3.0 xsl:result-document instruction.
  * 
- * Ref : https://www.w3.org/TR/xslt-30/#element-result-document
- * 
  * @author Mukul Gandhi <mu...@apache.org>
  *  
  * @xsl.usage advanced
@@ -76,6 +86,24 @@ public class ElemResultDocument extends ElemTemplateElement
    */
   private boolean m_omitXmlDeclaration;
   
+  /**
+   * This URI string value may be set from fn:transform 
+   * function call.
+   */
+  public static String m_BaseOutputUriStrAbsValue = null;
+  
+  /**
+   * Class field representing reference to, function fn:transform's 
+   * return value which is of type XDM map.
+   */
+  public static XPathMap m_fnTransformResult = null;
+  
+  /**
+   * Class field representing reference to, function fn:transform's 
+   * 'delivery-format' parameter specification.
+   */
+  public static String m_fnTransformDeliveryFormat = null;
+  
   /**
    * The class constructor.
    */
@@ -210,9 +238,15 @@ public class ElemResultDocument extends ElemTemplateElement
 				URI url = new URI(hrefStrVal);
 				String stylesheetSystemId = srcLocator.getSystemId();      // base uri of stylesheet, if available
 
-				if (!url.isAbsolute() && (stylesheetSystemId != null)) {
-					URI resolvedUriArg = (new URI(stylesheetSystemId)).resolve(hrefStrVal);
-					resolvedHrefUrl = resolvedUriArg.toURL(); 
+				if (!url.isAbsolute()) {
+					if (m_BaseOutputUriStrAbsValue != null) {
+						URI resolvedUriArg = (new URI(m_BaseOutputUriStrAbsValue)).resolve(hrefStrVal);
+						resolvedHrefUrl = resolvedUriArg.toURL();
+					}				
+					else if (stylesheetSystemId != null) {
+						URI resolvedUriArg = (new URI(stylesheetSystemId)).resolve(hrefStrVal);
+						resolvedHrefUrl = resolvedUriArg.toURL(); 
+					}
 				}
 
 				if (resolvedHrefUrl == null) {
@@ -230,7 +264,8 @@ public class ElemResultDocument extends ElemTemplateElement
 																					+ "an absolute uri.", srcLocator);
 			}
 	    	
-	    	QName methodQname = m_method;												// Optional, with default value "xml"	    	
+	    	QName methodQname = m_method;												// Optional, with default value "xml"
+	    	
 	    	boolean omitXmlDeclarationAttr = m_omitXmlDeclaration;   					// Optional, with default value "false"
 	    	
 	    	String resolvedHrefStrVal = resolvedHrefUrl.toString();
@@ -251,12 +286,43 @@ public class ElemResultDocument extends ElemTemplateElement
 	    			xmlStrValue = xmlStrValue.substring(xmlPrologEndStrIndex + 2); 
 	    		}
 	    		
-	    		writeStringContentsToFile(resolvedHrefStrVal, xmlStrValue);
+	    		if (m_fnTransformResult != null) {
+	    			if (m_BaseOutputUriStrAbsValue != null) {
+	    				int lastIndexOfSlsh = m_BaseOutputUriStrAbsValue.lastIndexOf('/');
+	    				String hrefUriPrefix = m_BaseOutputUriStrAbsValue.substring(0, lastIndexOfSlsh + 1);
+	    				URI url = new URI(hrefStrVal);
+	    				String effectAbsUri = null;
+	    				if (!url.isAbsolute()) {
+	    					effectAbsUri = hrefUriPrefix + url.toString(); 
+	    				}
+	    				else {
+	    					effectAbsUri = url.toString(); 
+	    				}
+	    				
+	    				m_fnTransformResult.put(new XSString(effectAbsUri), getFnTransformResultComponent(xctxt, xmlStrValue));
+	    			}
+	    			else {
+	    				m_fnTransformResult.put(new XSString(resolvedHrefStrVal), getFnTransformResultComponent(xctxt, xmlStrValue));	
+	    			}
+	    		}
+	    		else {
+	    			writeStringContentsToFile(resolvedHrefStrVal, xmlStrValue);
+	    		}
 	    	}
 	    	else if ((Constants.ATTRVAL_OUTPUT_METHOD_TEXT).equals(methodQname.toString())) {
 	    		String textStrValue = transformer.transformToString(this);
 	    		
-	    		writeStringContentsToFile(resolvedHrefStrVal, textStrValue);
+	    		if (m_fnTransformResult != null) {
+	    			if (m_BaseOutputUriStrAbsValue != null) {
+	    				m_fnTransformResult.put(new XSString(m_BaseOutputUriStrAbsValue), getFnTransformResultComponent(xctxt, textStrValue));
+	    			}
+	    			else {
+	    				m_fnTransformResult.put(new XSString(resolvedHrefStrVal), getFnTransformResultComponent(xctxt, textStrValue));	
+	    			}
+	    		}
+	    		else {
+	    			writeStringContentsToFile(resolvedHrefStrVal, textStrValue);
+	    		}
 	    	}
 	    	else if ((Constants.ATTRVAL_OUTPUT_METHOD_JSON).equals(methodQname.toString())) {
 	    		String jsonStrValue = transformer.transformToString(this);
@@ -269,13 +335,23 @@ public class ElemResultDocument extends ElemTemplateElement
 	    		}
 	    		catch (JSONException ex) {
 	    		   throw new TransformerException("XPTY0004 : An xsl:result-document instruction within a stylesheet has attribute "
-	    		   		                                			+ "\"method\" with value 'json'. There's a JSON syntax error within "
-	    		   		                                			+ "an input string provided to the JSON parser, or there was a duplicate "
-	    		   		                                			+ "JSON object key. Following run-time error occured : " + 
-	    		   		                                			ex.getMessage() + ".", srcLocator);
+	    		   		                                										+ "\"method\" with value 'json'. There's a JSON syntax error within "
+	    		   		                                										+ "an input string provided to the JSON parser, or there was a duplicate "
+	    		   		                                										+ "JSON object key. Following run-time error occured : " + 
+	    		   		                                										ex.getMessage() + ".", srcLocator);
 	    		}
 	    		
-	    		writeStringContentsToFile(resolvedHrefStrVal, jsonStrValue.trim());
+	    		if (m_fnTransformResult != null) {
+	    			if (m_BaseOutputUriStrAbsValue != null) {
+	    				m_fnTransformResult.put(new XSString(m_BaseOutputUriStrAbsValue), getFnTransformResultComponent(xctxt, jsonStrValue.trim()));
+	    			}
+	    			else {
+	    				m_fnTransformResult.put(new XSString(resolvedHrefStrVal), getFnTransformResultComponent(xctxt, jsonStrValue.trim()));	
+	    			}
+	    		}
+	    		else {
+	    			writeStringContentsToFile(resolvedHrefStrVal, jsonStrValue.trim());
+	    		}
 	    	}
 	    	else if ((Constants.ATTRVAL_OUTPUT_METHOD_HTML).equals(methodQname.toString())) {	    		
 	    		ElemTemplateElement t = this.m_firstChild;
@@ -311,13 +387,34 @@ public class ElemResultDocument extends ElemTemplateElement
 	    		   String htmlStrValue = XslTransformEvaluationHelper.serializeXmlDomElementNode(node);
 	    		   int xmlPrologSuffixIdx = htmlStrValue.indexOf("?>");
 	    		   htmlStrValue = htmlStrValue.substring(xmlPrologSuffixIdx + 2);
+	    		   
+	    		   if (m_fnTransformResult != null) {
+	    			   if (m_BaseOutputUriStrAbsValue != null) {
+	    				   int lastIndexOfSlsh = m_BaseOutputUriStrAbsValue.lastIndexOf('/');
+	    				   String hrefUriPrefix = m_BaseOutputUriStrAbsValue.substring(0, lastIndexOfSlsh + 1);
+	    				   URI url = new URI(hrefStrVal);
+	    				   String effectAbsUri = null;
+	    				   if (!url.isAbsolute()) {
+	    					   effectAbsUri = hrefUriPrefix + url.toString(); 
+	    				   }
+	    				   else {
+	    					   effectAbsUri = url.toString(); 
+	    				   }
 
-	    		   writeStringContentsToFile(resolvedHrefStrVal, htmlStrValue);
+	    				   m_fnTransformResult.put(new XSString(effectAbsUri), getFnTransformResultComponent(xctxt, htmlStrValue));
+	    			   }
+	    			   else {
+	    				   m_fnTransformResult.put(new XSString(resolvedHrefStrVal), getFnTransformResultComponent(xctxt, htmlStrValue));	
+	    			   }
+	    		   }
+	    		   else {
+	    			   writeStringContentsToFile(resolvedHrefStrVal, htmlStrValue);
+	    		   }
 
 	    		   /**
 	    		    * This is an original xsl:output information that has to be restored
 	    		    * on stylesheetRoot object for any further XSL transformation work, after
-	    		    * this xsl:result-document instruction instance has completed executing.
+	    		    * this xsl:result-document instruction instance has completed its processing.
 	    		    */
 	    		   Properties prevOutputProperties = stylesheetRoot.getDefaultOutputProps();
 
@@ -330,8 +427,8 @@ public class ElemResultDocument extends ElemTemplateElement
 	    }	    
 	    catch (Exception ex) {
 	    	throw new TransformerException("XPTY0004 : An exception occured while evaluating an "
-	    			                                    + "xsl:result-document instruction. Following "
-	    			                                    + "run-time error occured : " + ex.getMessage() + ".", srcLocator);
+	    			                                    								+ "xsl:result-document instruction. Following "
+	    			                                    								+ "run-time error occured : " + ex.getMessage() + ".", srcLocator);
 	    }
         finally {
             if (transformer.getDebug()) {
@@ -375,8 +472,8 @@ public class ElemResultDocument extends ElemTemplateElement
   }
   
   /**
-   * This method creates a physical file specified by its name within 
-   * local file system store, and writes a string value to the file.
+   * This method creates a file specified by its name within local file system 
+   * store, and writes a string value to the file.
    * 
    * @param hrefStr						local url of the file, with "file:/" scheme.
    *                                    this url may point to any location within 
@@ -397,5 +494,41 @@ public class ElemResultDocument extends ElemTemplateElement
 	  fos.flush();
 	  fos.close();
   }
+  
+  /**
+   * This method definition gets details for the, result of xsl:result-document 
+   * instruction.
+   */
+  private XObject getFnTransformResultComponent(XPathContext xctxt, String resultStrValue) throws Exception {	  
+	  
+	  XObject result = null;
+	  
+	  if ((m_fnTransformDeliveryFormat == null) || (FuncTransform.DOCUMENT).equals(m_fnTransformDeliveryFormat)) {
+		  System.setProperty(Constants.XML_DOCUMENT_BUILDER_FACTORY_KEY, Constants.XML_DOCUMENT_BUILDER_FACTORY_VALUE);
+	      System.setProperty(FuncTransform.XSLT_TRANSFORMER_FACTORY_KEY, FuncTransform.XSLT_TRANSFORMER_FACTORY_VALUE);
+		  
+	      DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+		  DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
+		  StringReader strReader = new StringReader(resultStrValue);
+		  Document document = docBuilder.parse(new InputSource(strReader));
+		  
+		  DTMManager dtmManager = xctxt.getDTMManager();
+		  DTM resultDtm = dtmManager.getDTM(new DOMSource(document), true, null, false, false);
+		  int resultDtmHandle = resultDtm.getDocument();			    	
+		  
+		  XMLNodeCursorImpl resultNode = new XMLNodeCursorImpl(resultDtmHandle, dtmManager);		  
+		  resultNode.setDtm(resultDtm);
+		  
+		  result = resultNode;
+	  }
+	  else if ((FuncTransform.SERIALIZED).equals(m_fnTransformDeliveryFormat)) {
+		  result = new XSString(resultStrValue);
+	  }
+      else if ((FuncTransform.RAW).equals(m_fnTransformDeliveryFormat)) {
+		 // TO DO  
+	  }
+	  
+	  return result;
+  }
 
 }
diff --git a/src/main/java/org/apache/xalan/templates/ElemVariable.java b/src/main/java/org/apache/xalan/templates/ElemVariable.java
index 5a3b6784c..e4d70cf9a 100644
--- a/src/main/java/org/apache/xalan/templates/ElemVariable.java
+++ b/src/main/java/org/apache/xalan/templates/ElemVariable.java
@@ -411,7 +411,8 @@ public class ElemVariable extends ElemTemplateElement
             XObject evalResult = ((Function)selectExpression).execute(xctxt);            
             if ((evalResult instanceof ResultSequence) || (evalResult instanceof XPathMap) || 
             		                                      (evalResult instanceof XPathArray) || 
-                                                          (evalResult instanceof XSAnyType)) {
+                                                          (evalResult instanceof XSAnyType) ||
+                                                          (evalResult instanceof XMLNodeCursorImpl)) {
                 if (m_asAttr != null) {
                    evalResult = SequenceTypeSupport.castXdmValueToAnotherType(evalResult, m_asAttr, null, xctxt);
                    if (evalResult == null) {
diff --git a/src/main/java/org/apache/xalan/transformer/TransformerImpl.java b/src/main/java/org/apache/xalan/transformer/TransformerImpl.java
index f49f17bc7..9542e0413 100644
--- a/src/main/java/org/apache/xalan/transformer/TransformerImpl.java
+++ b/src/main/java/org/apache/xalan/transformer/TransformerImpl.java
@@ -2552,9 +2552,6 @@ public class TransformerImpl extends Transformer
       xctxt.popSAXLocator();
     }
 
-    // Check for infinite loops if we have to
-//    if (check)
-//      getStackGuard().pop();
   }
   
   /**
diff --git a/src/main/java/org/apache/xalan/transformer/TreeWalker2Result.java b/src/main/java/org/apache/xalan/transformer/TreeWalker2Result.java
index fc180ec7e..8377c5b3a 100644
--- a/src/main/java/org/apache/xalan/transformer/TreeWalker2Result.java
+++ b/src/main/java/org/apache/xalan/transformer/TreeWalker2Result.java
@@ -70,7 +70,10 @@ public class TreeWalker2Result extends DTMTreeWalker
    */
   public void traverse(int pos) throws org.xml.sax.SAXException
   {
-    m_dtm = m_transformer.getXPathContext().getDTM(pos);
+	if (m_dtm == null) {
+       m_dtm = m_transformer.getXPathContext().getDTM(pos);
+    }
+	
     m_startNode = pos;
 
     super.traverse(pos);
diff --git a/src/main/java/org/apache/xpath/functions/FuncTransform.java b/src/main/java/org/apache/xpath/functions/FuncTransform.java
index 738647f82..c7de3e77e 100644
--- a/src/main/java/org/apache/xpath/functions/FuncTransform.java
+++ b/src/main/java/org/apache/xpath/functions/FuncTransform.java
@@ -36,6 +36,7 @@ import javax.xml.transform.dom.DOMResult;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamSource;
 
+import org.apache.xalan.templates.ElemResultDocument;
 import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
 import org.apache.xml.dtm.DTM;
 import org.apache.xml.dtm.DTMCursorIterator;
@@ -69,31 +70,32 @@ public class FuncTransform extends FunctionDef1Arg
 	 * Definition of various class, constant field definitions. 
 	 */
 	
-    private static final String XSLT_TRANSFORMER_FACTORY_KEY = "javax.xml.transform.TransformerFactory";
+    public static final String XSLT_TRANSFORMER_FACTORY_KEY = "javax.xml.transform.TransformerFactory";
     
-    private static final String XSLT_TRANSFORMER_FACTORY_VALUE = "org.apache.xalan.processor.XSL3TransformerFactoryImpl";
+    public static final String XSLT_TRANSFORMER_FACTORY_VALUE = "org.apache.xalan.processor.XSL3TransformerFactoryImpl";
     
-    private static final String STYLESHEET_LOCATION = "stylesheet-location";    
+    public static final String STYLESHEET_LOCATION = "stylesheet-location";    
     
-    private static final String STYLESHEET_NODE = "stylesheet-node";
+    public static final String STYLESHEET_NODE = "stylesheet-node";
     
-    private static final String STYLESHEET_TEXT = "stylesheet-text";
+    public static final String STYLESHEET_TEXT = "stylesheet-text";
     
-    private static final String SOURCE_NODE = "source-node";
+    public static final String SOURCE_NODE = "source-node";
     
-    private static final String BASE_OUTPUT_URI = "base-output-uri";
+    public static final String BASE_OUTPUT_URI = "base-output-uri";
     
-    private static final String DELIVERY_FORMAT = "delivery-format";
+    public static final String DELIVERY_FORMAT = "delivery-format";
     
-    private static final String SERLIALIZATION_PARAMS = "serialization-params";
+    public static final String SERLIALIZATION_PARAMS = "serialization-params";
     
-    private static final String DOCUMENT = "document";
+    public static final String DOCUMENT = "document";
     
-    private static final String SERIALIZED = "serialized";
+    public static final String SERIALIZED = "serialized";
     
-    private static final String RAW = "raw";
+    public static final String RAW = "raw";
+    
+    public static final String OUTPUT = "output";
     
-    private static final String OUTPUT = "output";
 
 	/**
 	 * Execute the function. The function must return a valid object.
@@ -112,6 +114,9 @@ public class FuncTransform extends FunctionDef1Arg
 		Expression arg0 = m_arg0;
 		XObject arg0Obj = arg0.execute(xctxt);
 		
+		// Reference of result object instance of, function fn:transform's evaluation.
+		ElemResultDocument.m_fnTransformResult = result;
+		
 		System.setProperty(Constants.XML_DOCUMENT_BUILDER_FACTORY_KEY, Constants.XML_DOCUMENT_BUILDER_FACTORY_VALUE);
     	System.setProperty(XSLT_TRANSFORMER_FACTORY_KEY, XSLT_TRANSFORMER_FACTORY_VALUE);
 		
@@ -155,17 +160,19 @@ public class FuncTransform extends FunctionDef1Arg
 			   		                                                                            + "stylesheet document, that will transform an XML input document source.", srcLocator); 
 		   }
 		   
-		   // The following optional, function fn:transform's 'map' argument entry 
-		   // keys (along, with corresponding map entry values as well).
+		   // The following are optional, function fn:transform's 'map' argument entry 
+		   // key values.
 		   XObject baseOutputUri = mapArg.get(new XSString(BASE_OUTPUT_URI));		   		   
 		   XObject deliveryFormat = mapArg.get(new XSString(DELIVERY_FORMAT));
 		   XObject serializationParams = mapArg.get(new XSString(SERLIALIZATION_PARAMS));  // TO DO
 		   
 		   String baseOutputUriStrValue = ((baseOutputUri != null) ? XslTransformEvaluationHelper.getStrVal(
 				   																							baseOutputUri) : null);
+		   
 		   if (baseOutputUriStrValue != null) {
 			   URL baseOutputUrl = getAbsoluteUrlValue(baseOutputUriStrValue, srcLocator);
-			   baseOutputUriStrValue = baseOutputUrl.toString();
+			   
+			   ElemResultDocument.m_BaseOutputUriStrAbsValue = baseOutputUrl.toString(); 
 		   }
 		   
 		   String deliverFormatStrValue = ((deliveryFormat != null) ? XslTransformEvaluationHelper.getStrVal(
@@ -174,11 +181,13 @@ public class FuncTransform extends FunctionDef1Arg
 			   if (!(DOCUMENT.equals(deliverFormatStrValue) || SERIALIZED.equals(deliverFormatStrValue) || 
 					   																				 RAW.equals(deliverFormatStrValue))) {
 				   throw new javax.xml.transform.TransformerException("FODC0005 : An XPath function fn:transform map argument "
-						   																+ "entry with key \"delivery-format\" can have value either "
-						   																+ "'document', 'serialized' or 'raw'.", srcLocator);			   
+						   																		          + "entry with key \"delivery-format\" can have value either "
+						   																                  + "'document', 'serialized' or 'raw'.", srcLocator);			   
 			   }
 		   }
 		   
+		   ElemResultDocument.m_fnTransformDeliveryFormat = deliverFormatStrValue;		   		   
+		   
 		   if (xslStylesheetLocObj != null) {
 			    // XPath function fn:transform's XSL transformation, using XSL stylesheet 
 			    // information provided by fn:transform's map key 'stylesheet-location'.
@@ -207,7 +216,7 @@ public class FuncTransform extends FunctionDef1Arg
 			    	TransformerFactory xslTransformerFactory = TransformerFactory.newInstance();
 			    	Transformer transformer = xslTransformerFactory.newTransformer(new StreamSource(xslStylesheetUrlStr));
 
-			    	DOMResult domResult = new DOMResult();		        
+			    	DOMResult domResult = new DOMResult();    			    	
 			    	transformer.transform(new DOMSource(document), domResult);
 
 			    	DTMManager dtmManager = xctxt.getDTMManager();
@@ -266,7 +275,7 @@ public class FuncTransform extends FunctionDef1Arg
 			    	TransformerFactory xslTransformerFactory = TransformerFactory.newInstance();
 			    	Transformer transformer = xslTransformerFactory.newTransformer(new DOMSource(xslDocNode));
 
-			    	DOMResult domResult = new DOMResult();		        
+			    	DOMResult domResult = new DOMResult();			    	
 			    	transformer.transform(new DOMSource(xmlInpDocNode), domResult);
 
 			    	DTMManager dtmManager = xctxt.getDTMManager();
@@ -367,6 +376,8 @@ public class FuncTransform extends FunctionDef1Arg
 		       }
 		   }		   		   		   
 		}
+		
+		ElemResultDocument.m_BaseOutputUriStrAbsValue = null;
 
 		return result;
 	}
diff --git a/src/main/java/org/apache/xpath/objects/XMLNodeCursorImpl.java b/src/main/java/org/apache/xpath/objects/XMLNodeCursorImpl.java
index 1861977f4..8432d736a 100644
--- a/src/main/java/org/apache/xpath/objects/XMLNodeCursorImpl.java
+++ b/src/main/java/org/apache/xpath/objects/XMLNodeCursorImpl.java
@@ -82,6 +82,13 @@ public class XMLNodeCursorImpl extends NodeCursor
    * validating this xdm node object.
    */
   private String m_validation = null;
+  
+  /**
+   * Class field that supports XPath function fn:transform evaluation,
+   * that invokes an XSL secondary stylesheet having one or more
+   * xsl:result-document instructions.
+   */
+  private DTM m_dtm = null;
 
   /**
    * Construct a XMLNodeCursorImpl object.
@@ -1003,6 +1010,14 @@ public class XMLNodeCursorImpl extends NodeCursor
   public String getValidationAttrForValidation() {
      return m_validation;  
   }
+
+  public DTM getDtm() {
+	 return m_dtm;
+  }
+
+  public void setDtm(DTM dtm) {
+	 this.m_dtm = dtm;
+  }
   
 }
 
diff --git a/src/test/java/org/apache/xalan/tests/xpath3/FnTransformTests.java b/src/test/java/org/apache/xalan/tests/xpath3/FnTransformTests.java
index 8e4601da5..20faa4e7d 100644
--- a/src/test/java/org/apache/xalan/tests/xpath3/FnTransformTests.java
+++ b/src/test/java/org/apache/xalan/tests/xpath3/FnTransformTests.java
@@ -136,5 +136,15 @@ public class FnTransformTests extends XSLTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslFnTransformTest10() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test10.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test10.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test10.out"; 
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
 
 }
diff --git a/src/test/resources/fn_transform/gold/test10.out b/src/test/resources/fn_transform/gold/test10.out
new file mode 100644
index 000000000..953e8d733
--- /dev/null
+++ b/src/test/resources/fn_transform/gold/test10.out
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <doc resultOuputRelativeUri="result1.xml">
+    <result1>
+   <a>1</a>
+   <b>2</b>
+   <c>3</c>
+</result1>
+  </doc>
+  <doc resultOuputRelativeUri="result2.xml">
+    <result2>
+   <d>4</d>
+   <e>5</e>
+   <f>6</f>
+   <g>7</g>
+</result2>
+  </doc>
+  <doc resultOuputRelativeUri="trfout"/>
+</result>
diff --git a/src/test/resources/fn_transform/render.xsl b/src/test/resources/fn_transform/render.xsl
index 93625c84d..d9bd2884a 100644
--- a/src/test/resources/fn_transform/render.xsl
+++ b/src/test/resources/fn_transform/render.xsl
@@ -1,6 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"				
 			    version="3.0">
+			    
+    <!-- Author: mukulg@apache.org -->
+    
+    <!-- An XSL stylesheet that serves as, secondary stylesheet for XPath 
+         function fn:transform. -->			    
 				
     <xsl:output method="xml" indent="yes"/>				
 	
@@ -13,6 +18,24 @@
           </xsl:for-each>
 	   </details>
     </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/src/test/resources/fn_transform/render2.xsl b/src/test/resources/fn_transform/render2.xsl
new file mode 100644
index 000000000..820c762f4
--- /dev/null
+++ b/src/test/resources/fn_transform/render2.xsl
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"				
+			    version="3.0">
+			    
+    <!-- Author: mukulg@apache.org -->
+    
+    <!-- An XSL stylesheet that serves as, secondary stylesheet for XPath 
+         function fn:transform. -->				    
+				
+    <xsl:output method="xml" omit-xml-declaration="yes"/>				
+	
+    <xsl:template match="/info">
+	   <xsl:result-document href="result1.xml" method="xml">
+		  <result1>
+			 <xsl:for-each select="*[position() lt 4]">
+			    <xsl:element name="{name()}">
+				   <xsl:value-of select="position()"/>
+			    </xsl:element>
+			 </xsl:for-each>
+		  </result1>
+	   </xsl:result-document>
+	   <xsl:result-document href="result2.xml" method="xml">
+		  <result2>
+		     <xsl:for-each select="*[position() ge 4]">
+			    <xsl:element name="{name()}">
+				   <xsl:value-of select="position() + 3"/>
+			    </xsl:element>
+		     </xsl:for-each>
+		  </result2>
+	   </xsl:result-document>
+    </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/src/test/resources/fn_transform/test10.xsl b/src/test/resources/fn_transform/test10.xsl
new file mode 100644
index 000000000..daea79285
--- /dev/null
+++ b/src/test/resources/fn_transform/test10.xsl
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                xmlns:map="http://www.w3.org/2005/xpath-functions/map"
+                exclude-result-prefixes="xs map"				
+			    version="3.0">
+			    
+  <!-- Author: mukulg@apache.org -->
+  
+  <!-- An XSL stylesheet test case, to test XPath 3.1 function fn:transform.
+       
+       This stylesheet test case, tests XSL transformation using a secondary 
+       stylesheet (render2.xsl in this example) that has xsl:result-document 
+       instruction. An xsl:result-document instruction's result output 
+       produced via this way, are accumulated within function fn:transform's 
+       XDM result map.       
+  -->			    									
+
+  <xsl:output method="xml" indent="yes"/>
+
+  <xsl:template match="/">
+      <result>
+		  <xsl:variable name="result" select="transform(
+														map {
+														   'stylesheet-location' : 'render2.xsl',
+														   'source-node' : doc('test1.xml'),
+														   'base-output-uri' : 'trfout',
+														   'delivery-format' : 'document'
+														})" as="map(*)"/>          														
+		  <xsl:for-each select="sort(map:keys($result))">
+		     <xsl:choose>
+			    <xsl:when test="contains(., '/')">
+		           <xsl:variable name="urlParts" select="tokenize(xs:string(.), '/')" as="xs:string*"/>
+		           <xsl:variable name="urlSuffixStr" select="$urlParts[count($urlParts)]" as="xs:string"/>
+		           <doc resultOuputRelativeUri="{$urlSuffixStr}">
+                      <xsl:copy-of select="$result(.)"/>
+			       </doc>
+			    </xsl:when>
+			    <xsl:otherwise>
+			       <doc resultOuputRelativeUri="{.}">
+                     <xsl:copy-of select="$result(.)"/>
+			       </doc>
+			    </xsl:otherwise>
+			 </xsl:choose>
+		  </xsl:for-each>
+      </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


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