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/10/02 10:52:36 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing improvements to implementation of xsl:function instruction, along with minor changes to comments within one of xalanj class on this dev repos 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 e52d7f36 committing improvements to implementation of xsl:function instruction, along with minor changes to comments within one of xalanj class on this dev repos branch.
     new d542237b Merge pull request #95 from mukulga/xalan-j_xslt3.0_mukul
e52d7f36 is described below

commit e52d7f364ad5d80fc0e4555049a3e9bebe02e089
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Mon Oct 2 16:16:04 2023 +0530

    committing improvements to implementation of xsl:function instruction, along with minor changes to comments within one of xalanj class on this dev repos branch.
---
 src/org/apache/xalan/templates/ElemFunction.java | 197 +++++++++++++++--------
 src/org/apache/xalan/templates/ElemParam.java    |  56 +++----
 src/org/apache/xalan/templates/ElemTemplate.java |   3 +-
 src/org/apache/xalan/templates/ElemVariable.java |   4 +-
 src/org/apache/xpath/VariableStack.java          |   2 +-
 5 files changed, 161 insertions(+), 101 deletions(-)

diff --git a/src/org/apache/xalan/templates/ElemFunction.java b/src/org/apache/xalan/templates/ElemFunction.java
index cb5bf133..c268347d 100644
--- a/src/org/apache/xalan/templates/ElemFunction.java
+++ b/src/org/apache/xalan/templates/ElemFunction.java
@@ -17,12 +17,18 @@
  */
 package org.apache.xalan.templates;
 
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
 import javax.xml.transform.SourceLocator;
 import javax.xml.transform.TransformerException;
 
 import org.apache.xalan.transformer.TransformerImpl;
 import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
 import org.apache.xml.dtm.ref.DTMNodeList;
+import org.apache.xml.utils.PrefixResolver;
 import org.apache.xml.utils.QName;
 import org.apache.xpath.VariableStack;
 import org.apache.xpath.XPath;
@@ -64,11 +70,6 @@ public class ElemFunction extends ElemTemplate
 {
 
   private static final long serialVersionUID = 4973132678982467288L;
-  
-  /**
-   * The value of the "name" attribute.
-   */
-  private static QName m_name;
 
   /**
    * Class constructor.
@@ -82,7 +83,6 @@ public class ElemFunction extends ElemTemplate
   public void setName(QName qName)
   {      
       super.setName(qName);
-      m_name = qName;
   }
 
   /**
@@ -124,69 +124,133 @@ public class ElemFunction extends ElemTemplate
                                                              ResultSequence argSequence) throws TransformerException {
       XObject result = null;
       
-      XPathContext xctxt = transformer.getXPathContext();
-      
-      SourceLocator srcLocator = xctxt.getSAXLocator(); 
-      
-      VariableStack varStack = xctxt.getVarStack();
-      
-      int thisframe = varStack.getStackFrame();
-      int nextFrame = varStack.link(m_frameSize);
+      XPathContext xctxt = transformer.getXPathContext();            
       
-      varStack.setStackFrame(thisframe);
+      SourceLocator srcLocator = xctxt.getSAXLocator();
       
       String funcLocalName = m_name.getLocalName();
-      String funcNameSpaceUri = m_name.getNamespaceURI(); 
+      String funcNameSpaceUri = m_name.getNamespaceURI();
       
-      int paramCount = 0;
-      for (ElemTemplateElement elem = getFirstChildElem(); elem != null; 
-                                                              elem = elem.getNextSiblingElem()) {
-          if (elem.getXSLToken() == Constants.ELEMNAME_PARAMVARIABLE) {
-             if (argSequence.size() < (paramCount + 1)) {
-                 throw new TransformerException("XPST0017 : Cannot find a " + argSequence.size() + " argument function named "
-                                                                            + "{" + funcNameSpaceUri + "}" + funcLocalName + "() within a stylesheet scope. "
-                                                                            + "The function name was recognized, but number of arguments is wrong.", srcLocator); 
-             }
-             XObject argValue = argSequence.item(paramCount);
-             XObject argConvertedVal = argValue;
-             String paramAsAttrStrVal = ((ElemParam)elem).getAs();              
-             if (paramAsAttrStrVal != null) {
-                try {
-                   argConvertedVal = SequenceTypeSupport.convertXDMValueToAnotherType(argValue, paramAsAttrStrVal, null, xctxt);
-                   if (argConvertedVal == null) {
-                      throw new TransformerException("XPTY0004 : Function call argument at position " + (paramCount + 1) + " for "
-                                                                        + "function {" + funcNameSpaceUri + "}" + funcLocalName + "(), doesn't "
-                                                                        + "match the declared parameter type " + paramAsAttrStrVal + ".", srcLocator); 
-                   }
+      // Validate few of the information of xsl:function's xsl:param declarations.         
+      Map<QName, Integer> xslParamMap = new HashMap<QName, Integer>();
+      int idx = 0;
+      PrefixResolver prefixResolver = xctxt.getNamespaceContext();
+      for (ElemTemplateElement elem = getFirstChildElem(); elem != null; elem = elem.getNextSiblingElem()) {
+         String nodeName = elem.getNodeName();         
+         if (nodeName.contains(":")) {
+            String nsPrefix = nodeName.substring(0, nodeName.indexOf(':'));
+            String namespaceUri = prefixResolver.getNamespaceForPrefix(nsPrefix);
+            String nodeLocalName = nodeName.substring(nodeName.indexOf(':') + 1);
+            if ((Constants.ELEMNAME_PARAMVARIABLE_STRING).equals(nodeLocalName) && 
+                                                                             (Constants.S_XSLNAMESPACEURL).equals(namespaceUri)) {
+                String xslParamName = elem.getAttribute(Constants.ATTRNAME_NAME);
+                if (xslParamMap.get(new QName(xslParamName)) == null) {
+                   xslParamMap.put(new QName(xslParamName), Integer.valueOf(idx)); 
                 }
-                catch (TransformerException ex) {
-                   throw new TransformerException("XPTY0004 : Function call argument at position " + (paramCount + 1) + " for "
-                                                                     + "function {" + funcNameSpaceUri + "}" + funcLocalName + "(), doesn't "
-                                                                     + "match the declared parameter type " + paramAsAttrStrVal + ".", srcLocator); 
-                }
-             }
-             
-             if (argConvertedVal instanceof ResultSequence) {                
-                XNodeSet nodeSet = XslTransformEvaluationHelper.getXNodeSetFromResultSequence((ResultSequence)argConvertedVal, 
-                                                                                                                            xctxt);
-                if (nodeSet != null) {
-                   argConvertedVal = nodeSet;  
+                else {
+                   throw new TransformerException("XPST0017 : The xsl:function " + "{" + funcNameSpaceUri + "}" + funcLocalName + 
+                                                                             "(), has more than one xsl:param '" + xslParamName + "' declaration.", srcLocator); 
                 }
+            }
+         }
+         else if (elem instanceof ElemParam) {
+             ElemParam elemParam = (ElemParam)elem;
+             QName elemParamQName = elemParam.getName();
+             if (xslParamMap.get(elemParamQName) == null) {
+                xslParamMap.put(elemParamQName, Integer.valueOf(idx)); 
              }
-             
-             varStack.setLocalVariable(paramCount, argConvertedVal, nextFrame);
-             paramCount++;
-          }
-          else {
-             break; 
-          }
+             else {
+                throw new TransformerException("XPST0017 : The xsl:function " + "{" + funcNameSpaceUri + "}" + funcLocalName + 
+                                                                          "(), has more than one xsl:param '" + elemParamQName + "' declaration.", srcLocator); 
+             } 
+         }
+         
+         idx++;
+      }
+      
+      if (xslParamMap.size() != argSequence.size()) {
+         throw new TransformerException("XPST0017 : For the xsl:function " + "{" + funcNameSpaceUri + "}" + funcLocalName + 
+                                                                       "(), the number of arguments provided with function call is not equal "
+                                                                       + "to number of function's xsl:param declarations.", srcLocator);  
+      }
+      
+      Collection<Integer> xslParamIdxs = xslParamMap.values();
+      Object[] idxArr = xslParamIdxs.toArray();
+      if (idxArr.length > 0) {
+         Arrays.sort(idxArr);
+         int currVal = ((Integer)idxArr[0]).intValue();
+         if (currVal != 0) {
+            throw new TransformerException("XPST0017 : For the xsl:function " + "{" + funcNameSpaceUri + "}" + funcLocalName + 
+                                                                          "(), there's a non xsl:param declaration as first child "
+                                                                          + "element of xsl:function.", srcLocator); 
+         }
+         
+         for (int idx1 = 1; idx1 < idxArr.length; idx1++) {
+            int nextVal = ((Integer)idxArr[idx1]).intValue();
+            if (nextVal != (currVal + 1)) {
+               throw new TransformerException("XPST0017 : For the xsl:function " + "{" + funcNameSpaceUri + "}" + funcLocalName + 
+                                                                             "(), there's a non xsl:param declaration between two "
+                                                                             + "xsl:param declarations.", srcLocator); 
+            }
+            else {
+               currVal = nextVal;  
+            }
+         }
       }
       
-      varStack.setStackFrame(nextFrame);
+      // end, Validate few of the information of xsl:function's xsl:param declarations                        
       
-      int df = transformer.transformToGlobalRTF(this);
+      if (xslParamMap.size() > 0) {
+          // Set all xsl:function parameters to xpath context's variable stack,
+          // so that XSL instructions after xsl:param declarations can dereference
+          // those parameters.
+          
+          VariableStack varStack = xctxt.getVarStack();
+          int argsFrame = varStack.link(xslParamMap.size());            
+                    
+          int paramIdx = 0;
+          for (ElemTemplateElement elem = getFirstChildElem(); elem != null; 
+                                                                  elem = elem.getNextSiblingElem()) {
+              if (elem.getXSLToken() == Constants.ELEMNAME_PARAMVARIABLE) {
+                 XObject argValue = argSequence.item(paramIdx);
+                 XObject argConvertedVal = argValue;
+                 String paramAsAttrStrVal = ((ElemParam)elem).getAs();              
+                 if (paramAsAttrStrVal != null) {
+                    try {
+                       argConvertedVal = SequenceTypeSupport.convertXDMValueToAnotherType(argValue, paramAsAttrStrVal, null, xctxt);
+                       if (argConvertedVal == null) {
+                          throw new TransformerException("XPTY0004 : Function call argument at position " + (paramIdx + 1) + " for "
+                                                                            + "function {" + funcNameSpaceUri + "}" + funcLocalName + "(), doesn't "
+                                                                            + "match the declared parameter type " + paramAsAttrStrVal + ".", srcLocator); 
+                       }
+                    }
+                    catch (TransformerException ex) {
+                       throw new TransformerException("XPTY0004 : Function call argument at position " + (paramIdx + 1) + " for "
+                                                                         + "function {" + funcNameSpaceUri + "}" + funcLocalName + "(), doesn't "
+                                                                         + "match the declared parameter type " + paramAsAttrStrVal + ".", srcLocator); 
+                    }
+                 }
+                 
+                 if (argConvertedVal instanceof ResultSequence) {                
+                    XNodeSet nodeSet = XslTransformEvaluationHelper.getXNodeSetFromResultSequence((ResultSequence)argConvertedVal, 
+                                                                                                                                xctxt);
+                    if (nodeSet != null) {
+                       argConvertedVal = nodeSet;  
+                    }
+                 }
+                  
+                 varStack.setLocalVariable(paramIdx, argConvertedVal, argsFrame);
+                 paramIdx++;
+              }
+              else {
+                 break; 
+              }
+          }     
+      }            
       
-      NodeList nodeList = (new XRTreeFrag(df, xctxt, this)).convertToNodeset();     
+      int nodeDtmHandle = transformer.transformToGlobalRTF(this);
+      
+      NodeList nodeList = (new XRTreeFrag(nodeDtmHandle, xctxt, this)).convertToNodeset();     
       
       result = new XNodeSetForDOM(nodeList, xctxt);
                         
@@ -257,7 +321,7 @@ public class ElemFunction extends ElemTemplate
   }
   
   /**
-   * This method helps us solve, xsl:function and xsl:variable instruction use cases,
+   * This method helps us to implement xsl:function and xsl:variable instructions,
    * when the XSL child contents of xsl:function or xsl:variable instructions contain 
    * xsl:sequence instruction(s).
    * 
@@ -265,9 +329,9 @@ public class ElemFunction extends ElemTemplate
    * instructions, and the function's or variable's expected data type, cast an input data
    * value to the supplied expected data type.
    */
-  public static ResultSequence preprocessXslFunctionOrAVariableResult(XNodeSetForDOM xNodeSetForDOM,
-                                                                      String sequenceTypeXPathExprStr,
-                                                                      XPathContext xctxt, QName varQName) throws TransformerException {
+  public ResultSequence preprocessXslFunctionOrAVariableResult(XNodeSetForDOM xNodeSetForDOM,
+                                                                                     String sequenceTypeXPathExprStr,
+                                                                                     XPathContext xctxt, QName varQName) throws TransformerException {
      ResultSequence resultSequence = null;
      
      DTMNodeList dtmNodeList = (DTMNodeList)(xNodeSetForDOM.object());
@@ -336,12 +400,19 @@ public class ElemFunction extends ElemTemplate
      return resultSequence;
   }
   
+  /**
+   * A method that returns a default instance of this class.
+   */
+  public static ElemFunction getXSLFunctionService() {
+     return new ElemFunction();  
+  }
+  
   /**
    * Given XalanJ's integer code value of, an XML Schema built-in data type and a 
    * string representation of a data value, construct XalanJ's typed data object 
    * corresponding to the data type's integer code value. 
    */
-  private static XObject getXSTypedAtomicValue(String strVal, int sequenceType) throws TransformerException {
+  private XObject getXSTypedAtomicValue(String strVal, int sequenceType) throws TransformerException {
       
       XObject result = null;
      
diff --git a/src/org/apache/xalan/templates/ElemParam.java b/src/org/apache/xalan/templates/ElemParam.java
index d9273360..93a01cd2 100644
--- a/src/org/apache/xalan/templates/ElemParam.java
+++ b/src/org/apache/xalan/templates/ElemParam.java
@@ -123,15 +123,7 @@ public class ElemParam extends ElemVariable
     
     SourceLocator srcLocator = xctx.getSAXLocator();
     
-    boolean isChildElemOfXslElemIterate = false;
-    if (getParentElem() instanceof ElemIterate) {
-       isChildElemOfXslElemIterate = true; 
-    }
-    
-    if (!vars.isLocalSet(m_index) || (isChildElemOfXslElemIterate && (xslIterateIterationIdx == 0))) {
-        // The caller of an stylesheet callable component (associated with this xsl:param element), 
-        // didn't provide xsl:param's value via xsl:with-param instruction.
-        
+    if (!vars.isLocalSet(m_index) || ((getParentElem() instanceof ElemIterate) && (xslIterateIterationIdx == 0))) {
         int sourceNode = transformer.getXPathContext().getCurrentNode();
         
         try {
@@ -151,31 +143,27 @@ public class ElemParam extends ElemVariable
                                                                            + "stylesheet context, or parameter's value cannot be cast to an expected type.", srcLocator);   
         }
     }
-    else {
-        // The caller of an stylesheet callable component (associated with this xsl:param element), 
-        // has provided xsl:param's value via xsl:with-param instruction.
-        
-        // If the xsl:param instruction has an 'as' attribute, we check below
-        // whether xsl:param's value conforms to the sequence type specified by
-        // xsl:param's 'as' attribute.
-        String asAttrVal = getAs();
-        
-        if (asAttrVal != null) {
-          try {
-             XObject var = transformer.getXPathContext().getVarStack().getLocalVariable(xctx, m_index);
-             var = SequenceTypeSupport.convertXDMValueToAnotherType(var, asAttrVal, null, 
-                                                                               transformer.getXPathContext());
-             if (var == null) {
-                throw new TransformerException("XTTE0590 : The required item type of the value of parameter " + 
-                                                                               m_qname.toString() + " is " + asAttrVal + ". The supplied value "
-                                                                               + "doesn't match the expected item type.", srcLocator);  
-             }
-          }
-          catch (TransformerException ex) {
-             throw new TransformerException("XTTE0590 : The required item type of the value of parameter " + 
-                                                                               m_qname.toString() + " is " + asAttrVal + ". The supplied value "
-                                                                               + "doesn't match the expected item type.", srcLocator); 
-          }
+    else {        
+        if (!(getParentElem() instanceof ElemFunction)) {
+            String asAttrVal = getAs();
+            
+            if (asAttrVal != null) {
+              try {
+                 XObject var = transformer.getXPathContext().getVarStack().getLocalVariable(xctx, m_index);
+                 var = SequenceTypeSupport.convertXDMValueToAnotherType(var, asAttrVal, null, 
+                                                                                   transformer.getXPathContext());
+                 if (var == null) {
+                    throw new TransformerException("XTTE0590 : The required item type of the value of parameter " + 
+                                                                                   m_qname.toString() + " is " + asAttrVal + ". The supplied value "
+                                                                                   + "doesn't match the expected item type.", srcLocator);  
+                 }
+              }
+              catch (TransformerException ex) {
+                 throw new TransformerException("XTTE0590 : The required item type of the value of parameter " + 
+                                                                                   m_qname.toString() + " is " + asAttrVal + ". The supplied value "
+                                                                                   + "doesn't match the expected item type.", srcLocator); 
+              }
+           }
        }
     }
     
diff --git a/src/org/apache/xalan/templates/ElemTemplate.java b/src/org/apache/xalan/templates/ElemTemplate.java
index 3b996461..82a7efba 100644
--- a/src/org/apache/xalan/templates/ElemTemplate.java
+++ b/src/org/apache/xalan/templates/ElemTemplate.java
@@ -190,9 +190,8 @@ public class ElemTemplate extends ElemTemplateElement
 
   /**
    * An xsl:template element with a name attribute specifies a named template.
-   * @serial
    */
-  private QName m_name = null;
+  protected QName m_name = null;
 
   /**
    * Set the "name" attribute.
diff --git a/src/org/apache/xalan/templates/ElemVariable.java b/src/org/apache/xalan/templates/ElemVariable.java
index c08010c3..9d2a55f3 100644
--- a/src/org/apache/xalan/templates/ElemVariable.java
+++ b/src/org/apache/xalan/templates/ElemVariable.java
@@ -559,7 +559,9 @@ public class ElemVariable extends ElemTemplateElement
           XObject variableConvertedVal = null;
           
           try {
-             variableConvertedVal = ElemFunction.preprocessXslFunctionOrAVariableResult((XNodeSetForDOM)var, m_asAttr, xctxt, m_qname);
+             ElemFunction elemFunction = ElemFunction.getXSLFunctionService();
+             variableConvertedVal = elemFunction.preprocessXslFunctionOrAVariableResult((XNodeSetForDOM)var, 
+                                                                                                m_asAttr, xctxt, m_qname);
           }
           catch (TransformerException ex) {
              throw new TransformerException(ex.getMessage(), srcLocator); 
diff --git a/src/org/apache/xpath/VariableStack.java b/src/org/apache/xpath/VariableStack.java
index 26416586..4b5ce395 100644
--- a/src/org/apache/xpath/VariableStack.java
+++ b/src/org/apache/xpath/VariableStack.java
@@ -201,7 +201,7 @@ public class VariableStack implements Cloneable
    * <a href="http://math.millikin.edu/mprogers/Courses/currentCourses/CS481-ComputerArchitecture/cs481.Motorola68000.html">
    * Motorola 68000 assembler</a> memories.</p>
    *
-   * @param size The size of the stack frame allocation.  This ammount should
+   * @param size The size of the stack frame allocation. This amount should
    * normally be the maximum number of variables that you can have allocated
    * at one time in the new stack frame.
    *


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