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 2024/07/25 17:03:48 UTC

(xalan-java) branch xalan-j_xslt3.0 updated: implementing xpath3.1 array information lookup using function call syntax, and few conformance test cases as well

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

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


The following commit(s) were added to refs/heads/xalan-j_xslt3.0 by this push:
     new 2e8189226 implementing xpath3.1 array information lookup using function call syntax, and few conformance test cases as well
2e8189226 is described below

commit 2e8189226fb666404922130afeddd13672a19355
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Thu Jul 25 22:33:33 2024 +0530

    implementing xpath3.1 array information lookup using function call syntax, and few conformance test cases as well
---
 .../xpath/functions/XPathDynamicFunctionCall.java  | 149 +++++++++++++++------
 tests/org/apache/xalan/xpath3/XPathArrayTests.java |  10 ++
 tests/org/apache/xalan/xpath3/XPathMapTests.java   |  10 ++
 tests/xpath_array/gold/test26.out                  |   8 ++
 tests/xpath_array/test26.xsl                       |  43 ++++++
 tests/xpath_maps/gold/test24.out                   |   5 +
 tests/xpath_maps/test24.xsl                        |  43 ++++++
 7 files changed, 226 insertions(+), 42 deletions(-)

diff --git a/src/org/apache/xpath/functions/XPathDynamicFunctionCall.java b/src/org/apache/xpath/functions/XPathDynamicFunctionCall.java
index d61298468..dc4f7482a 100644
--- a/src/org/apache/xpath/functions/XPathDynamicFunctionCall.java
+++ b/src/org/apache/xpath/functions/XPathDynamicFunctionCall.java
@@ -42,18 +42,16 @@ import org.apache.xpath.composite.SequenceTypeData;
 import org.apache.xpath.composite.SequenceTypeSupport;
 import org.apache.xpath.objects.InlineFunctionParameter;
 import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XPathArray;
 import org.apache.xpath.objects.XPathInlineFunction;
 import org.apache.xpath.objects.XPathMap;
 import org.apache.xpath.objects.XString;
 
 import xml.xpath31.processor.types.XSString;
 
-/*
- * This class implements XPath 3.1 dynamic function calls and map
- * lookup expressions.
- * 
- * Ref : https://www.w3.org/TR/xpath-31/#id-dynamic-function-invocation,
- *       https://www.w3.org/TR/xpath-31/#id-map-lookup
+/**
+ * This class implements XPath 3.1 dynamic function calls, and
+ * map/array information lookup using function call syntax.
  * 
  * @author Mukul Gandhi <mu...@apache.org>
  * 
@@ -70,8 +68,8 @@ public class XPathDynamicFunctionCall extends Expression {
     // The following two fields of this class, are used during 
     // XPath.fixupVariables(..) action as performed within object of 
     // this class.    
-    private Vector fVars;    
-    private int fGlobalsSize;
+    private Vector m_vars;    
+    private int m_globals_size;
 
     public String getFuncRefVarName() {
         return m_funcRefVarName;
@@ -133,37 +131,13 @@ public class XPathDynamicFunctionCall extends Expression {
        
        if (functionRef != null) {
     	    ElemTemplateElement elemTemplateElement = (ElemTemplateElement)xctxt.getNamespaceContext();
-            List<XMLNSDecl> prefixTable = null;
+            
+    	    List<XMLNSDecl> prefixTable = null;
             if (elemTemplateElement != null) {
                prefixTable = (List<XMLNSDecl>)elemTemplateElement.getPrefixTable();
             }
-    	    if (functionRef instanceof XPathMap) {
-    		   XPathMap xpathMap = (XPathMap)functionRef;
-    		   if (m_argList.size() != 1) {
-    			   throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for map value lookup, should have only "
-    			   		                                                     + "one argument which needs to be one of map key name.", xctxt.getSAXLocator()); 
-    		   }
-    		   else {
-    			  String argXPathStr = m_argList.get(0);
-    			  if (prefixTable != null) {
- 	                 argXPathStr = XslTransformEvaluationHelper.replaceNsUrisWithPrefixesOnXPathStr(argXPathStr, 
- 	                                                                                                      prefixTable);
- 	              }
-    			   
-    			  XPath argXPath = new XPath(argXPathStr, srcLocator, xctxt.getNamespaceContext(), XPath.SELECT, null);
-                  if (fVars != null) {
-                     argXPath.fixupVariables(fVars, fGlobalsSize);
-                  }
-
-                  XObject argValue = argXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
-                  if (argValue instanceof XString) {
-                	 argValue = new XSString(((XString)argValue).str());  
-                  }
-                  
-                  evalResult = xpathMap.get(argValue); 
-    		   }    		   
-    	   }
-    	   else if (functionRef instanceof XPathInlineFunction) {
+                	    
+    	    if (functionRef instanceof XPathInlineFunction) {
 	           XPathInlineFunction inlineFunction = (XPathInlineFunction)functionRef;
 	           
 	           String inlineFnXPathStr = inlineFunction.getFuncBodyXPathExprStr();
@@ -189,8 +163,8 @@ public class XPathDynamicFunctionCall extends Expression {
 	              
 	              XPath argXPath = new XPath(argXPathStr, srcLocator, xctxt.getNamespaceContext(), 
 	                                                                                        XPath.SELECT, null);
-	              if (fVars != null) {
-	                 argXPath.fixupVariables(fVars, fGlobalsSize);
+	              if (m_vars != null) {
+	                 argXPath.fixupVariables(m_vars, m_globals_size);
 	              }
 	              
 	              XObject argValue = argXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
@@ -228,8 +202,8 @@ public class XPathDynamicFunctionCall extends Expression {
 	           
 	           XPath inlineFnXPath = new XPath(inlineFnXPathStr, srcLocator, xctxt.getNamespaceContext(), 
 	                                                                                       XPath.SELECT, null);
-	           if (fVars != null) {
-	              inlineFnXPath.fixupVariables(fVars, fGlobalsSize);
+	           if (m_vars != null) {
+	              inlineFnXPath.fixupVariables(m_vars, m_globals_size);
 	           }
 	                      
 	           evalResult = inlineFnXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
@@ -256,6 +230,68 @@ public class XPathDynamicFunctionCall extends Expression {
 	        	  inlineFunctionVarMap.remove(key);
 	           }
 	        }
+    	    else if (functionRef instanceof XPathMap) {
+     		   XPathMap xpathMap = (XPathMap)functionRef;
+     		   if (m_argList.size() != 1) {
+     			   throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for map information lookup, needs to have "
+     			   		                                                     + "1 argument which should be one of map's key name.", 
+     			   		                                                     xctxt.getSAXLocator()); 
+     		   }
+     		   else {
+     			  String argXPathStr = m_argList.get(0);
+     			  if (".".equals(argXPathStr)) {
+     				 XObject contextItem = xctxt.getXPath3ContextItem();
+     				 evalResult = xpathMap.get(contextItem);
+     			  }
+     			  else {
+     				  if (prefixTable != null) {
+     					  argXPathStr = XslTransformEvaluationHelper.replaceNsUrisWithPrefixesOnXPathStr(argXPathStr, 
+     							  prefixTable);
+     				  }
+
+     				  XPath argXPath = new XPath(argXPathStr, srcLocator, xctxt.getNamespaceContext(), XPath.SELECT, null);
+     				  if (m_vars != null) {
+     					  argXPath.fixupVariables(m_vars, m_globals_size);
+     				  }
+
+     				  XObject argValue = argXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
+     				  if (argValue instanceof XString) {
+     					  argValue = new XSString(((XString)argValue).str());  
+     				  }
+
+     				  evalResult = xpathMap.get(argValue);
+     			  }
+     		   }    		   
+     	    }
+    	    else if (functionRef instanceof XPathArray) {
+    	       XPathArray xpathArr = (XPathArray)functionRef;    	       
+    	       if (m_argList.size() != 1) {
+    	    	   throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for array information lookup, needs to have "
+                                                                             + "1 argument which should be position within an array.", 
+                                                                             xctxt.getSAXLocator()); 
+     		   }
+     		   else {
+     			  String argXPathStr = m_argList.get(0);     			  
+     			  if (".".equals(argXPathStr)) {
+     				  XObject contextItem = xctxt.getXPath3ContextItem();     				  
+     				  evalResult = getArrayLookupResult(xctxt, xpathArr, contextItem);
+     			  }
+     			  else {
+	     			  if (prefixTable != null) {
+	  	                 argXPathStr = XslTransformEvaluationHelper.replaceNsUrisWithPrefixesOnXPathStr(argXPathStr, 
+	  	                                                                                                      prefixTable);
+	  	              }
+	     			   
+	     			  XPath argXPath = new XPath(argXPathStr, srcLocator, xctxt.getNamespaceContext(), XPath.SELECT, null);
+	                  if (m_vars != null) {
+	                     argXPath.fixupVariables(m_vars, m_globals_size);
+	                  }
+	
+	                  XObject argValue = argXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
+	                  evalResult = getArrayLookupResult(xctxt, xpathArr, argValue);
+     			  }
+     		   }
+    	    }
       }
       else {
          throw new javax.xml.transform.TransformerException("XPST0008 : Variable '" + m_funcRefVarName + "' has "
@@ -268,13 +304,42 @@ public class XPathDynamicFunctionCall extends Expression {
 
     @Override
     public void fixupVariables(Vector vars, int globalsSize) {
-        fVars = (Vector)(vars.clone());
-        fGlobalsSize = globalsSize; 
+        m_vars = (Vector)(vars.clone());
+        m_globals_size = globalsSize; 
     }
 
     @Override
     public boolean deepEquals(Expression expr) {
         return false;
     }
+    
+    /**
+     * Given an xdm array object, get array item at a specified index position.
+     */
+    private XObject getArrayLookupResult(XPathContext xctxt, XPathArray xpathArr, XObject indexVal)
+			                                                                                      throws TransformerException {
+    	XObject evalResult;
+    	
+    	String argValStr = XslTransformEvaluationHelper.getStrVal(indexVal);     				  
+
+    	Integer intVal = null;     				  
+    	try {
+    		intVal = Integer.valueOf(argValStr);
+    		if (!(intVal > 0 && (intVal <= xpathArr.size()))) {
+    			throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for array information lookup, "
+    					                                                  + "needs to have 1 numeric argument >= 1 specifying position "
+    					                                                  + "within an array.", xctxt.getSAXLocator()); 
+    		}
+    	}
+    	catch (NumberFormatException ex) {
+    		throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for array information lookup, "
+    				                                                  + "needs to have 1 numeric argument >= 1 specifying position "
+    				                                                  + "within an array.", xctxt.getSAXLocator()); 
+    	}
+
+    	evalResult = xpathArr.get(intVal-1);
+    	
+    	return evalResult;
+	}
 
 }
diff --git a/tests/org/apache/xalan/xpath3/XPathArrayTests.java b/tests/org/apache/xalan/xpath3/XPathArrayTests.java
index fe9b0f78b..12cfe7f8b 100644
--- a/tests/org/apache/xalan/xpath3/XPathArrayTests.java
+++ b/tests/org/apache/xalan/xpath3/XPathArrayTests.java
@@ -297,5 +297,15 @@ public class XPathArrayTests extends XSLTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslArrayTest26() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test26.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test26.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test26.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
 
 }
diff --git a/tests/org/apache/xalan/xpath3/XPathMapTests.java b/tests/org/apache/xalan/xpath3/XPathMapTests.java
index 195a42b0d..40d7cc9d6 100644
--- a/tests/org/apache/xalan/xpath3/XPathMapTests.java
+++ b/tests/org/apache/xalan/xpath3/XPathMapTests.java
@@ -277,5 +277,15 @@ public class XPathMapTests extends XSLTransformTestsUtil {
         
         runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
     }
+    
+    @Test
+    public void xslMapTest24() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test24.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test24.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test24.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
 
 }
diff --git a/tests/xpath_array/gold/test26.out b/tests/xpath_array/gold/test26.out
new file mode 100644
index 000000000..7af5b1460
--- /dev/null
+++ b/tests/xpath_array/gold/test26.out
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?><array>
+  <item>5</item>
+  <item>6</item>
+  <item>7</item>
+  <item>8</item>
+  <item>9</item>
+  <item>10</item>
+</array>
diff --git a/tests/xpath_array/test26.xsl b/tests/xpath_array/test26.xsl
new file mode 100644
index 000000000..836c628b3
--- /dev/null
+++ b/tests/xpath_array/test26.xsl
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"				
+				xmlns:array="http://www.w3.org/2005/xpath-functions/array"
+                exclude-result-prefixes="array"                
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- An XSLT test case to test, XPath 3.1 array information lookup 
+        using function call syntax. -->                			
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/">
+	  <xsl:variable name="arr1" select="[5,6,7,8,9,10]" as="array(*)"/>
+      <array>
+		 <xsl:for-each select="1 to array:size($arr1)">
+		   <item>
+			 <xsl:value-of select="$arr1(.)"/>
+		   </item>
+		 </xsl:for-each>
+	  </array>
+   </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>
diff --git a/tests/xpath_maps/gold/test24.out b/tests/xpath_maps/gold/test24.out
new file mode 100644
index 000000000..4c814503a
--- /dev/null
+++ b/tests/xpath_maps/gold/test24.out
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?><map>
+  <item key="a">2</item>
+  <item key="b">3</item>
+  <item key="c">4</item>
+</map>
diff --git a/tests/xpath_maps/test24.xsl b/tests/xpath_maps/test24.xsl
new file mode 100644
index 000000000..3c0751e98
--- /dev/null
+++ b/tests/xpath_maps/test24.xsl
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"				
+				xmlns:map="http://www.w3.org/2005/xpath-functions/map"
+                exclude-result-prefixes="map"                
+                version="3.0">
+                
+   <!-- Author: mukulg@apache.org -->
+   
+   <!-- An XSLT test case to test, XPath 3.1 map information lookup 
+        using function call syntax. -->                			
+
+   <xsl:output method="xml" indent="yes"/>
+
+   <xsl:template match="/">
+	  <xsl:variable name="map1" select="map {'a' : 2, 'b' : 3, 'c' : 4}" as="map(*)"/>
+      <map>
+		 <xsl:for-each select="sort(map:keys($map1))">
+		   <item key="{.}">
+			 <xsl:value-of select="$map1(.)"/>
+		   </item>
+		 </xsl:for-each>
+	  </map>
+   </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>


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