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/03 12:16:57 UTC

(xalan-java) branch xalan-j_xslt3.0_mvn updated: committing improvements to implementation of xpath function fn:transform. implementing fn:transform options base-output-uri and delivery-format. also adding few working new related test cases.

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 f95496c13 committing improvements to implementation of xpath function fn:transform. implementing fn:transform options base-output-uri and delivery-format. also adding few working new related test cases.
f95496c13 is described below

commit f95496c13b4d968db0f5acddaca2761216b8dbba
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Thu Apr 3 17:46:42 2025 +0530

    committing improvements to implementation of xpath function fn:transform. implementing fn:transform options base-output-uri and delivery-format. also adding few working new related test cases.
---
 README                                             |   4 +-
 .../org/apache/xpath/composite/XPathLetExpr.java   |   4 +-
 .../org/apache/xpath/functions/FuncTransform.java  | 331 +++++++++++++++------
 .../xalan/tests/xpath3/FnTransformTests.java       |  20 ++
 src/test/resources/fn_transform/gold/test8.out     |   9 +
 src/test/resources/fn_transform/gold/test9.out     |   9 +
 src/test/resources/fn_transform/test8.xsl          |  41 +++
 src/test/resources/fn_transform/test9.xsl          |  41 +++
 8 files changed, 358 insertions(+), 101 deletions(-)

diff --git a/README b/README
index 828b64189..9e5975ee7 100644
--- a/README
+++ b/README
@@ -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: 971, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 21.949 s - in 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]
 [INFO] Results:
 [INFO]
-[INFO] Tests run: 971, Failures: 0, Errors: 0, Skipped: 0
+[INFO] Tests run: 973, Failures: 0, Errors: 0, Skipped: 0
 [INFO]
 [INFO] ------------------------------------------------------------------------
 [INFO] BUILD SUCCESS
diff --git a/src/main/java/org/apache/xpath/composite/XPathLetExpr.java b/src/main/java/org/apache/xpath/composite/XPathLetExpr.java
index 5fce579bd..6de49093c 100644
--- a/src/main/java/org/apache/xpath/composite/XPathLetExpr.java
+++ b/src/main/java/org/apache/xpath/composite/XPathLetExpr.java
@@ -39,8 +39,6 @@ import org.apache.xpath.objects.XObject;
 
 /**
  * An implementation of XPath 3.1 'let' expression.
- *    
- * Ref : https://www.w3.org/TR/xpath-31/#id-let-expressions
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
@@ -94,7 +92,7 @@ public class XPathLetExpr extends Expression {
           }
           
           XPath letExprVarBindingXPath = new XPath(varResultXPathExprStr, srcLocator, xctxt.getNamespaceContext(), 
-                                                                                             XPath.SELECT, null);
+        		                                                                                             XPath.SELECT, null);
           if (m_vars != null) {
              letExprVarBindingXPath.fixupVariables(m_vars, m_globals_size);
           }
diff --git a/src/main/java/org/apache/xpath/functions/FuncTransform.java b/src/main/java/org/apache/xpath/functions/FuncTransform.java
index cd8bdf4d1..738647f82 100644
--- a/src/main/java/org/apache/xpath/functions/FuncTransform.java
+++ b/src/main/java/org/apache/xpath/functions/FuncTransform.java
@@ -30,6 +30,7 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.transform.SourceLocator;
 import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMResult;
 import javax.xml.transform.dom.DOMSource;
@@ -64,9 +65,35 @@ public class FuncTransform extends FunctionDef1Arg
 
 	private static final long serialVersionUID = 4109927115539483019L;
 	
+	/**
+	 * Definition of various class, constant field definitions. 
+	 */
+	
     private static final String XSLT_TRANSFORMER_FACTORY_KEY = "javax.xml.transform.TransformerFactory";
     
     private static final String XSLT_TRANSFORMER_FACTORY_VALUE = "org.apache.xalan.processor.XSL3TransformerFactoryImpl";
+    
+    private static final String STYLESHEET_LOCATION = "stylesheet-location";    
+    
+    private static final String STYLESHEET_NODE = "stylesheet-node";
+    
+    private static final String STYLESHEET_TEXT = "stylesheet-text";
+    
+    private static final String SOURCE_NODE = "source-node";
+    
+    private static final String BASE_OUTPUT_URI = "base-output-uri";
+    
+    private static final String DELIVERY_FORMAT = "delivery-format";
+    
+    private static final String SERLIALIZATION_PARAMS = "serialization-params";
+    
+    private static final String DOCUMENT = "document";
+    
+    private static final String SERIALIZED = "serialized";
+    
+    private static final String RAW = "raw";
+    
+    private static final String OUTPUT = "output";
 
 	/**
 	 * Execute the function. The function must return a valid object.
@@ -85,6 +112,9 @@ public class FuncTransform extends FunctionDef1Arg
 		Expression arg0 = m_arg0;
 		XObject arg0Obj = arg0.execute(xctxt);
 		
+		System.setProperty(Constants.XML_DOCUMENT_BUILDER_FACTORY_KEY, Constants.XML_DOCUMENT_BUILDER_FACTORY_VALUE);
+    	System.setProperty(XSLT_TRANSFORMER_FACTORY_KEY, XSLT_TRANSFORMER_FACTORY_VALUE);
+		
 		if (!(arg0Obj instanceof XPathMap)) {
 			throw new javax.xml.transform.TransformerException("FODC0005 : The 1st argument to function call fn:transform "
 					                                                                                  + "is not an XDM map.", srcLocator);
@@ -94,9 +124,9 @@ public class FuncTransform extends FunctionDef1Arg
 		   
 		   // An XSL stylesheet input document, for fn:transform function call 
 		   // may be provided with one of following ways.
-		   XObject xslStylesheetLocObj = mapArg.get(new XSString("stylesheet-location"));
-		   XObject xslStylesheetNodeObj = mapArg.get(new XSString("stylesheet-node"));
-		   XObject xslStylesheetTxtObj = mapArg.get(new XSString("stylesheet-text"));
+		   XObject xslStylesheetLocObj = mapArg.get(new XSString(STYLESHEET_LOCATION));
+		   XObject xslStylesheetNodeObj = mapArg.get(new XSString(STYLESHEET_NODE));
+		   XObject xslStylesheetTxtObj = mapArg.get(new XSString(STYLESHEET_TEXT));
 		   
 		   boolean xslStylesheetSrcInpErr = false;
 		   
@@ -110,7 +140,7 @@ public class FuncTransform extends FunctionDef1Arg
 			   xslStylesheetSrcInpErr = true; 
 		   }
 		   
-           XObject sourceInpDocNodeObj = mapArg.get(new XSString("source-node"));
+           XObject sourceInpDocNodeObj = mapArg.get(new XSString(SOURCE_NODE));
 		   
 		   if (sourceInpDocNodeObj == null) {
 			   throw new javax.xml.transform.TransformerException("FODC0005 : For the fn:transform function call, an argument's map key 'source-node' "
@@ -124,66 +154,54 @@ public class FuncTransform extends FunctionDef1Arg
 			   		                                                                            + "'stylesheet-node' or 'stylesheet-text'. This identifies an XSL "
 			   		                                                                            + "stylesheet document, that will transform an XML input document source.", srcLocator); 
 		   }
-		   else if (xslStylesheetLocObj != null) {
-			   String hrefStrVal = XslTransformEvaluationHelper.getStrVal(xslStylesheetLocObj);
-			   
-			   URL xslStylesheetResolvedUrl = null;
-			   
-			   try {
-		        	URI xslStylesheetUri = new URI(hrefStrVal);        	
-
-		        	if (xslStylesheetUri.isAbsolute()) {
-		        		xslStylesheetResolvedUrl = new URL(hrefStrVal); 
-		        	}
-		        	else {
-		        		String stylesheetSystemId = null;
-		            	
-		        		if (srcLocator != null) {
-		            		stylesheetSystemId = srcLocator.getSystemId();
-		            	}
-		            	else {
-		            		ExpressionNode expressionNode = getExpressionOwner();
-		            		stylesheetSystemId = expressionNode.getSystemId(); 
-		            	}
-		            	
-		        		if (stylesheetSystemId != null) {
-		        			URI resolvedUriArg = (new URI(stylesheetSystemId)).resolve(hrefStrVal);
-		        			xslStylesheetResolvedUrl = resolvedUriArg.toURL();
-		        		}
-		        		else {
-		        			xslStylesheetResolvedUrl = new URL(hrefStrVal);
-		        		}
-		        	}
-		        }
-		        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); 
-		        }
-			   
-			    // Perform XPath function fn:transform's XSL transformation.
+		   
+		   // The following optional, function fn:transform's 'map' argument entry 
+		   // keys (along, with corresponding map entry values as well).
+		   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();
+		   }
+		   
+		   String deliverFormatStrValue = ((deliveryFormat != null) ? XslTransformEvaluationHelper.getStrVal(
+				                                                                                            deliveryFormat) : null);
+		   if (deliverFormatStrValue != null) {
+			   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);			   
+			   }
+		   }
+		   
+		   if (xslStylesheetLocObj != null) {
+			    // XPath function fn:transform's XSL transformation, using XSL stylesheet 
+			    // information provided by fn:transform's map key 'stylesheet-location'.
 			   
-			    XMLNodeCursorImpl xmlNodeCursorImpl = (XMLNodeCursorImpl)sourceInpDocNodeObj;
-			    DTMCursorIterator dtmCursorIter = xmlNodeCursorImpl.iterRaw();
-			    int xmlInpNodeHandle = dtmCursorIter.nextNode();
-			    DTM dtm = xctxt.getDTM(xmlInpNodeHandle);			    
-			    Node xmlInpDocNode = dtm.getNode(xmlInpNodeHandle);
-			    
 			    try {
-			    	String xmlInpDocStr = XslTransformEvaluationHelper.serializeXmlDomElementNode(xmlInpDocNode);			    
-			    	String xslStylesheetUrlStr = xslStylesheetResolvedUrl.toString();
+			    	String hrefStrVal = XslTransformEvaluationHelper.getStrVal(xslStylesheetLocObj);
 
-			    	System.setProperty(Constants.XML_DOCUMENT_BUILDER_FACTORY_KEY, Constants.XML_DOCUMENT_BUILDER_FACTORY_VALUE);
-			    	System.setProperty(XSLT_TRANSFORMER_FACTORY_KEY, XSLT_TRANSFORMER_FACTORY_VALUE);                
+			    	URL xslSecondaryStylesheetAbsUrl = getAbsoluteUrlValue(hrefStrVal, srcLocator);			   			    
+
+			    	XMLNodeCursorImpl xmlNodeCursorImpl = (XMLNodeCursorImpl)sourceInpDocNodeObj;
+			    	DTMCursorIterator dtmCursorIter = xmlNodeCursorImpl.iterRaw();
+			    	int xmlInpNodeHandle = dtmCursorIter.nextNode();
+			    	DTM dtm = xctxt.getDTM(xmlInpNodeHandle);			    
+			    	Node xmlInpDocNode = dtm.getNode(xmlInpNodeHandle);
+
+			    	String xmlInpDocStr = XslTransformEvaluationHelper.serializeXmlDomElementNode(xmlInpDocNode);			    
+			    	String xslStylesheetUrlStr = xslSecondaryStylesheetAbsUrl.toString();			    	                
 
 			    	DocumentBuilderFactory xmlDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
 			    	xmlDocumentBuilderFactory.setNamespaceAware(true);
 
 			    	DocumentBuilder xmlDocumentBuilder = xmlDocumentBuilderFactory.newDocumentBuilder();
-			    	
+
 			    	Document document = xmlDocumentBuilder.parse(new InputSource(new StringReader(xmlInpDocStr)));
 
 			    	TransformerFactory xslTransformerFactory = TransformerFactory.newInstance();
@@ -191,52 +209,105 @@ public class FuncTransform extends FunctionDef1Arg
 
 			    	DOMResult domResult = new DOMResult();		        
 			    	transformer.transform(new DOMSource(document), domResult);
-			    	
+
 			    	DTMManager dtmManager = xctxt.getDTMManager();
 			    	DTM dtmResult = dtmManager.getDTM(new DOMSource(domResult.getNode()), true, null, false, false);
 			    	int resultDocHandle = dtmResult.getDocument();			    	
 			    	XMLNodeCursorImpl xdmNodeCursorImpl = new XMLNodeCursorImpl(resultDocHandle, dtmManager); 
-			    	
-			    	result.put(new XSString("output"), xdmNodeCursorImpl);
+
+			    	if ((deliverFormatStrValue == null) || DOCUMENT.equals(deliverFormatStrValue)) {
+			    		if (baseOutputUriStrValue != null) {
+			    			result.put(new XSString(baseOutputUriStrValue), xdmNodeCursorImpl);	
+			    		}
+			    		else {
+			    			result.put(new XSString(OUTPUT), xdmNodeCursorImpl);
+			    		}
+			    	}
+			    	else if (SERIALIZED.equals(deliverFormatStrValue)) {
+			    		DTMCursorIterator dtmIter = xdmNodeCursorImpl.iterRaw();
+			    		int nodeHandle = dtmIter.nextNode();
+			    		DTM dtm1 = xctxt.getDTM(nodeHandle);
+			    		Node node = dtm1.getNode(nodeHandle);
+			    		String xmlStrValue = XslTransformEvaluationHelper.serializeXmlDomElementNode(node);
+			    		if (baseOutputUriStrValue != null) {
+			    			result.put(new XSString(baseOutputUriStrValue), new XSString(xmlStrValue));	
+			    		}
+			    		else {
+			    			result.put(new XSString(OUTPUT), new XSString(xmlStrValue));
+			    		}
+			    	}
+			    	else if (RAW.equals(deliverFormatStrValue)) {
+			    		// TO DO
+			    	}
 			    }
 			    catch (Exception ex) {
 			    	throw new javax.xml.transform.TransformerException("FODC0005 : An error occured while evaluating "
-			    			                                                                     + "fn:transform function. Following exception occured : " + 
-			    			                                                                         ex.getMessage() + ".", srcLocator);
+			    			                                                   + "fn:transform function. Following exception occured : " + 
+			    			                                                   ex.getMessage() + ".", srcLocator);
 			    }
 		   }
 		   else if (xslStylesheetNodeObj != null) {
-			    // Perform XPath function fn:transform's XSL transformation.
+			    // XPath function fn:transform's XSL transformation, using XSL stylesheet 
+			    // information provided by fn:transform's map key 'stylesheet-node'.
 			   
-			    XMLNodeCursorImpl xmlNodeCursorImpl = (XMLNodeCursorImpl)sourceInpDocNodeObj;
-			    DTMCursorIterator dtmCursorIter = xmlNodeCursorImpl.iterRaw();
-			    int xmlInpNodeHandle = dtmCursorIter.nextNode();
-			    DTM dtm = xctxt.getDTM(xmlInpNodeHandle);			    
-			    Node xmlInpDocNode = dtm.getNode(xmlInpNodeHandle);
-			    
-			    XMLNodeCursorImpl xslNodeCursorImpl = (XMLNodeCursorImpl)xslStylesheetNodeObj;
-			    dtmCursorIter = xslNodeCursorImpl.iterRaw();
-			    int xslNodeHandle = dtmCursorIter.nextNode();
-			    dtm = xctxt.getDTM(xslNodeHandle);			    
-			    Node xslDocNode = dtm.getNode(xslNodeHandle);
-			    
-		    	System.setProperty(XSLT_TRANSFORMER_FACTORY_KEY, XSLT_TRANSFORMER_FACTORY_VALUE);
-		    	
-		    	TransformerFactory xslTransformerFactory = TransformerFactory.newInstance();
-		    	Transformer transformer = xslTransformerFactory.newTransformer(new DOMSource(xslDocNode));
-
-		    	DOMResult domResult = new DOMResult();		        
-		    	transformer.transform(new DOMSource(xmlInpDocNode), domResult);
-		    	
-		    	DTMManager dtmManager = xctxt.getDTMManager();
-		    	DTM dtmResult = dtmManager.getDTM(new DOMSource(domResult.getNode()), true, null, false, false);
-		    	int resultDocHandle = dtmResult.getDocument();			    	
-		    	XMLNodeCursorImpl xdmNodeCursorImpl = new XMLNodeCursorImpl(resultDocHandle, dtmManager); 
-		    	
-		    	result.put(new XSString("output"), xdmNodeCursorImpl);
+			    try  {
+			    	XMLNodeCursorImpl xmlNodeCursorImpl = (XMLNodeCursorImpl)sourceInpDocNodeObj;
+			    	DTMCursorIterator dtmCursorIter = xmlNodeCursorImpl.iterRaw();
+			    	int xmlInpNodeHandle = dtmCursorIter.nextNode();
+			    	DTM dtm = xctxt.getDTM(xmlInpNodeHandle);			    
+			    	Node xmlInpDocNode = dtm.getNode(xmlInpNodeHandle);
+
+			    	XMLNodeCursorImpl xslNodeCursorImpl = (XMLNodeCursorImpl)xslStylesheetNodeObj;
+			    	dtmCursorIter = xslNodeCursorImpl.iterRaw();
+			    	int xslNodeHandle = dtmCursorIter.nextNode();
+			    	dtm = xctxt.getDTM(xslNodeHandle);			    
+			    	Node xslDocNode = dtm.getNode(xslNodeHandle);
+
+			    	TransformerFactory xslTransformerFactory = TransformerFactory.newInstance();
+			    	Transformer transformer = xslTransformerFactory.newTransformer(new DOMSource(xslDocNode));
+
+			    	DOMResult domResult = new DOMResult();		        
+			    	transformer.transform(new DOMSource(xmlInpDocNode), domResult);
+
+			    	DTMManager dtmManager = xctxt.getDTMManager();
+			    	DTM dtmResult = dtmManager.getDTM(new DOMSource(domResult.getNode()), true, null, false, false);
+			    	int resultDocHandle = dtmResult.getDocument();			    	
+			    	XMLNodeCursorImpl xdmNodeCursorImpl = new XMLNodeCursorImpl(resultDocHandle, dtmManager); 
+
+			    	if ((deliverFormatStrValue == null) || DOCUMENT.equals(deliverFormatStrValue)) {
+			    		if (baseOutputUriStrValue != null) {
+			    			result.put(new XSString(baseOutputUriStrValue), xdmNodeCursorImpl);	
+			    		}
+			    		else {
+			    			result.put(new XSString(OUTPUT), xdmNodeCursorImpl);
+			    		}
+			    	}
+			    	else if (SERIALIZED.equals(deliverFormatStrValue)) {
+			    		DTMCursorIterator dtmIter = xdmNodeCursorImpl.iterRaw();
+			    		int nodeHandle = dtmIter.nextNode();
+			    		DTM dtm1 = xctxt.getDTM(nodeHandle);
+			    		Node node = dtm1.getNode(nodeHandle);
+			    		String xmlStrValue = XslTransformEvaluationHelper.serializeXmlDomElementNode(node);
+			    		if (baseOutputUriStrValue != null) {
+			    			result.put(new XSString(baseOutputUriStrValue), new XSString(xmlStrValue));	
+			    		}
+			    		else {
+			    			result.put(new XSString(OUTPUT), new XSString(xmlStrValue));
+			    		}		    		
+			    	}
+			    	else if (RAW.equals(deliverFormatStrValue)) {
+			    		// TO DO
+			    	}
+			    }
+		    	catch (Exception ex) {
+	    			throw new javax.xml.transform.TransformerException("FODC0005 : An error occured while evaluating fn:transform "
+	    					                                                   + "function. Following exception occured : " + 
+	    					                                                   ex.getMessage() + ".", srcLocator);
+	    		}
 		   }
            else {
-        	   // Perform XPath function fn:transform's XSL transformation.
+        	   // XPath function fn:transform's XSL transformation, using XSL stylesheet 
+			   // information provided by fn:transform's map key 'stylesheet-text'.
         	   
         	   try {
         		   String xslStylesheetStrValue = XslTransformEvaluationHelper.getStrVal(xslStylesheetTxtObj);
@@ -245,10 +316,7 @@ public class FuncTransform extends FunctionDef1Arg
         		   DTMCursorIterator dtmCursorIter = xmlNodeCursorImpl.iterRaw();
         		   int xmlInpNodeHandle = dtmCursorIter.nextNode();
         		   DTM dtm = xctxt.getDTM(xmlInpNodeHandle);			    
-        		   Node xmlInpDocNode = dtm.getNode(xmlInpNodeHandle);
-
-        		   System.setProperty(Constants.XML_DOCUMENT_BUILDER_FACTORY_KEY, Constants.XML_DOCUMENT_BUILDER_FACTORY_VALUE);
-        		   System.setProperty(XSLT_TRANSFORMER_FACTORY_KEY, XSLT_TRANSFORMER_FACTORY_VALUE);                
+        		   Node xmlInpDocNode = dtm.getNode(xmlInpNodeHandle);               
 
         		   DocumentBuilderFactory xmlDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
         		   xmlDocumentBuilderFactory.setNamespaceAware(true);
@@ -267,16 +335,87 @@ public class FuncTransform extends FunctionDef1Arg
         		   int resultDocHandle = dtmResult.getDocument();			    	
         		   XMLNodeCursorImpl xdmNodeCursorImpl = new XMLNodeCursorImpl(resultDocHandle, dtmManager); 
 
-        		   result.put(new XSString("output"), xdmNodeCursorImpl);
+        		   if ((deliverFormatStrValue == null) || DOCUMENT.equals(deliverFormatStrValue)) {
+        			   if (baseOutputUriStrValue != null) {
+        				   result.put(new XSString(baseOutputUriStrValue), xdmNodeCursorImpl);	
+        			   }
+        			   else {
+        				   result.put(new XSString(OUTPUT), xdmNodeCursorImpl);
+        			   }
+        		   }
+        		   else if (SERIALIZED.equals(deliverFormatStrValue)) {
+        			   DTMCursorIterator dtmIter = xdmNodeCursorImpl.iterRaw();
+        			   int nodeHandle = dtmIter.nextNode();
+        			   DTM dtm1 = xctxt.getDTM(nodeHandle);
+        			   Node node = dtm1.getNode(nodeHandle);
+        			   String xmlStrValue = XslTransformEvaluationHelper.serializeXmlDomElementNode(node);
+        			   if (baseOutputUriStrValue != null) {
+        				   result.put(new XSString(baseOutputUriStrValue), new XSString(xmlStrValue));	
+        			   }
+        			   else {
+        				   result.put(new XSString(OUTPUT), new XSString(xmlStrValue));
+        			   }        			   
+        		   }
+        		   else if (RAW.equals(deliverFormatStrValue)) {
+        			   // TO DO
+        		   }
 		       } 
 		       catch (Exception ex) {            
 		    	   throw new javax.xml.transform.TransformerException("FODC0005 : An error occured while evaluating "
-																	                           + "fn:transform function. Following exception occured : " + 
-																	                               ex.getMessage() + ".", srcLocator);
+																	          + "fn:transform function. Following exception occured : " + 
+		    			                                                      ex.getMessage() + ".", srcLocator);
 		       }
 		   }		   		   		   
 		}
 
 		return result;
 	}
+
+	/**
+	 * Function definition to get absolute url object value, given either a relative
+	 * url or an absolute url string value as argument.
+	 */
+	private URL getAbsoluteUrlValue(String hrefStrVal, SourceLocator srcLocator) throws TransformerException {		
+		
+		URL absUrlValue = null;
+
+		try {
+			URI xslStylesheetUri = new URI(hrefStrVal);        	
+
+			if (xslStylesheetUri.isAbsolute()) {
+				absUrlValue = new URL(hrefStrVal); 
+			}
+			else {
+				String stylesheetSystemId = null;
+
+				if (srcLocator != null) {
+					stylesheetSystemId = srcLocator.getSystemId();
+				}
+				else {
+					ExpressionNode expressionNode = getExpressionOwner();
+					stylesheetSystemId = expressionNode.getSystemId(); 
+				}
+
+				if (stylesheetSystemId != null) {
+					URI resolvedUriArg = (new URI(stylesheetSystemId)).resolve(hrefStrVal);
+					absUrlValue = resolvedUriArg.toURL();
+				}
+				else {
+					absUrlValue = new URL(hrefStrVal);
+				}
+			}
+		}
+		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); 
+		}
+		
+		return absUrlValue;
+		
+	}
+	
 }
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 8c04772d8..8e4601da5 100644
--- a/src/test/java/org/apache/xalan/tests/xpath3/FnTransformTests.java
+++ b/src/test/java/org/apache/xalan/tests/xpath3/FnTransformTests.java
@@ -116,5 +116,25 @@ public class FnTransformTests extends XSLTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslFnTransformTest8() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test8.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test8.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test8.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslFnTransformTest9() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test9.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test9.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test9.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
 
 }
diff --git a/src/test/resources/fn_transform/gold/test8.out b/src/test/resources/fn_transform/gold/test8.out
new file mode 100644
index 000000000..59ee6aa11
--- /dev/null
+++ b/src/test/resources/fn_transform/gold/test8.out
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?><details>
+  <a>1</a>
+  <b>2</b>
+  <c>3</c>
+  <d>4</d>
+  <e>5</e>
+  <f>6</f>
+  <g>7</g>
+</details>
diff --git a/src/test/resources/fn_transform/gold/test9.out b/src/test/resources/fn_transform/gold/test9.out
new file mode 100644
index 000000000..d20401caa
--- /dev/null
+++ b/src/test/resources/fn_transform/gold/test9.out
@@ -0,0 +1,9 @@
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;details&gt;&#13;
+   &lt;a&gt;1&lt;/a&gt;&#13;
+   &lt;b&gt;2&lt;/b&gt;&#13;
+   &lt;c&gt;3&lt;/c&gt;&#13;
+   &lt;d&gt;4&lt;/d&gt;&#13;
+   &lt;e&gt;5&lt;/e&gt;&#13;
+   &lt;f&gt;6&lt;/f&gt;&#13;
+   &lt;g&gt;7&lt;/g&gt;&#13;
+&lt;/details&gt;&#13;
diff --git a/src/test/resources/fn_transform/test8.xsl b/src/test/resources/fn_transform/test8.xsl
new file mode 100644
index 000000000..4b1914021
--- /dev/null
+++ b/src/test/resources/fn_transform/test8.xsl
@@ -0,0 +1,41 @@
+<?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 test case, to test XPath 3.1 function 
+       fn:transform. -->			    									
+
+  <xsl:output method="xml" indent="yes"/>
+
+  <xsl:template match="/">
+	  <xsl:variable name="result" select="transform(
+	                                                map {
+													   'stylesheet-location' : 'render.xsl',
+													   'source-node' : doc('test1.xml'),
+													   'delivery-format' : 'document'
+												    })" as="map(*)"/>
+      <xsl:copy-of select="$result?output"/>													
+  </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/test9.xsl b/src/test/resources/fn_transform/test9.xsl
new file mode 100644
index 000000000..85d1fd0a9
--- /dev/null
+++ b/src/test/resources/fn_transform/test9.xsl
@@ -0,0 +1,41 @@
+<?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 test case, to test XPath 3.1 function 
+       fn:transform. -->			    									
+
+  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
+
+  <xsl:template match="/">
+	  <xsl:variable name="result" select="transform(
+	                                                map {
+													   'stylesheet-location' : 'render.xsl',
+													   'source-node' : doc('test1.xml'),
+													   'delivery-format' : 'serialized'
+												    })" as="map(*)"/>
+      <xsl:copy-of select="$result?output"/>													
+  </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