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/05/08 06:10:39 UTC
(xalan-java) branch xalan-j_xslt3.0_mvn updated: committing few fixes for xpath expression evaluation when xpath path expression string has function call suffix, along with few working 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 f07e362da committing few fixes for xpath expression evaluation when xpath path expression string has function call suffix, along with few working related test cases
f07e362da is described below
commit f07e362da5b5ea5b87fc61fa5d9a0d1a8d1281db
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Thu May 8 11:40:22 2025 +0530
committing few fixes for xpath expression evaluation when xpath path expression string has function call suffix, along with few working related test cases
---
README | 8 +--
.../org/apache/xalan/templates/ElemEvaluate.java | 23 ++++-----
.../org/apache/xalan/templates/ElemForEach.java | 38 ++++++--------
.../org/apache/xalan/templates/ElemIterate.java | 39 +++++++-------
.../xalan/templates/ElemTemplateElement.java | 58 +++++++++++++++++++++
.../org/apache/xalan/templates/ElemValueOf.java | 22 ++++----
.../org/apache/xalan/templates/ElemVariable.java | 34 ++++++------
src/main/java/org/apache/xpath/Expression.java | 60 ++++++++++++++++++++++
.../org/apache/xpath/axes/LocPathIterator.java | 13 ++---
.../org/apache/xpath/composite/XPathForExpr.java | 40 +++++++--------
.../xpath3/XPathExprFunctionCallSuffixTests.java | 40 +++++++++++++++
.../xpath_function_call_suffix/gold/test17.out | 4 ++
.../xpath_function_call_suffix/gold/test18.out | 4 ++
.../xpath_function_call_suffix/gold/test19.out | 4 ++
.../xpath_function_call_suffix/gold/test20.out | 10 ++++
.../xpath_function_call_suffix/test17.xml | 6 +++
.../xpath_function_call_suffix/test17.xsl | 39 ++++++++++++++
.../xpath_function_call_suffix/test18.xml | 6 +++
.../xpath_function_call_suffix/test18.xsl | 39 ++++++++++++++
.../xpath_function_call_suffix/test19.xml | 6 +++
.../xpath_function_call_suffix/test19.xsl | 47 +++++++++++++++++
.../xpath_function_call_suffix/test20.xml | 6 +++
22 files changed, 429 insertions(+), 117 deletions(-)
diff --git a/README b/README
index 4508369af..4e1285047 100644
--- a/README
+++ b/README
@@ -17,7 +17,7 @@
Copyright 1999-2025 The Apache Software Foundation
-Document last modified : 2025-05-07
+Document last modified : 2025-05-08
Authors:
Gary Gregory <gg...@apache.org>
@@ -59,16 +59,16 @@ 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: 1037, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 72.394 s - in org.apache.xalan.tests.main.AllXsl3Tests
+[INFO] Tests run: 1041, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 30.179 s - in org.apache.xalan.tests.main.AllXsl3Tests
[INFO]
[INFO] Results:
[INFO]
-[INFO] Tests run: 1037, Failures: 0, Errors: 0, Skipped: 0
+[INFO] Tests run: 1041, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
-[INFO] Total time: 02:52 min
+[INFO] Total time: 01:30 min
To run Xalan-J's XSL 3 processor for invoking an XSL stylesheet transformation, the jar file xalan-java-3.0.1.jar and other
jar files available within 'libs' folder need to be made available on Java run-time's classpath.
diff --git a/src/main/java/org/apache/xalan/templates/ElemEvaluate.java b/src/main/java/org/apache/xalan/templates/ElemEvaluate.java
index acfdd3c14..9714491db 100644
--- a/src/main/java/org/apache/xalan/templates/ElemEvaluate.java
+++ b/src/main/java/org/apache/xalan/templates/ElemEvaluate.java
@@ -483,21 +483,20 @@ public class ElemEvaluate extends ElemTemplateElement {
ResultSequence resultSeq = new ResultSequence();
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- XObject evalResult = singletonXPathNode;
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
+ XObject evalResult = null;
if (func != null) {
- // Evaluate an XPath path expression like /a/b/funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- evalResult = func.execute(xctxt);
+ // Evaluate an XPath expression like /a/b/funcCall(..).
+ // Find one result item for a sequence of items.
+ evalResult = evaluateXPathSuffixFunction(xctxt, srcLocator, func, xdmNodeObj);
}
else if (dfc != null) {
- // Evaluate an XPath path expression like /a/b/$funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- evalResult = dfc.execute(xctxt);
+ // Evaluate an XPath expression like /a/b/$funcCall(..).
+ // Find one result item for a sequence of items.
+ evalResult = evaluateXPathSuffixDfc(xctxt, dfc, xdmNodeObj);
+ }
+ else {
+ evalResult = xdmNodeObj;
}
resultSeq.add(evalResult);
diff --git a/src/main/java/org/apache/xalan/templates/ElemForEach.java b/src/main/java/org/apache/xalan/templates/ElemForEach.java
index 34af0e6ba..3053f93b4 100644
--- a/src/main/java/org/apache/xalan/templates/ElemForEach.java
+++ b/src/main/java/org/apache/xalan/templates/ElemForEach.java
@@ -326,6 +326,8 @@ public class ElemForEach extends ElemTemplateElement implements ExpressionOwner
final int sourceNode = xctxt.getCurrentNode();
+ SourceLocator srcLocator = xctxt.getSAXLocator();
+
xctxt.setPos(0);
xctxt.setLast(0);
@@ -458,44 +460,40 @@ public class ElemForEach extends ElemTemplateElement implements ExpressionOwner
}
if (dtmIter != null) {
- ResultSequence inpSeq = null;
+ ResultSequence resultSeq = null;
Function func = locPathIterator.getFuncExpr();
XPathDynamicFunctionCall dfc = locPathIterator.getDynamicFuncCallExpr();
if (func != null) {
- inpSeq = new ResultSequence();
+ resultSeq = new ResultSequence();
int nextNode;
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- // Evaluate an XPath path expression like /a/b/funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject funcEvalResult = func.execute(xctxt);
- inpSeq.add(funcEvalResult);
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
+ // Evaluate an XPath expression like /a/b/funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixFunction(xctxt, srcLocator, func, xdmNodeObj);
+ resultSeq.add(evalResult);
}
- processSequenceOrArray(transformer, xctxt, inpSeq);
+ processSequenceOrArray(transformer, xctxt, resultSeq);
return;
}
else if (dfc != null) {
- inpSeq = new ResultSequence();
+ resultSeq = new ResultSequence();
int nextNode;
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- // Evaluate an XPath path expression like /a/b/$funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject dfcEvalResult = dfc.execute(xctxt);
- inpSeq.add(dfcEvalResult);
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
+ // Evaluate an XPath expression like /a/b/$funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixDfc(xctxt, dfc, xdmNodeObj);
+ resultSeq.add(evalResult);
}
- processSequenceOrArray(transformer, xctxt, inpSeq);
+ processSequenceOrArray(transformer, xctxt, resultSeq);
return;
}
@@ -527,8 +525,6 @@ public class ElemForEach extends ElemTemplateElement implements ExpressionOwner
prefixTable);
}
- SourceLocator srcLocator = xctxt.getSAXLocator();
-
XPath xpathObj = new XPath(varRefXPathExprStr, srcLocator,
xctxt.getNamespaceContext(), XPath.SELECT, null);
diff --git a/src/main/java/org/apache/xalan/templates/ElemIterate.java b/src/main/java/org/apache/xalan/templates/ElemIterate.java
index 8f7e2cb79..c8c524c33 100644
--- a/src/main/java/org/apache/xalan/templates/ElemIterate.java
+++ b/src/main/java/org/apache/xalan/templates/ElemIterate.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;
import org.apache.xalan.transformer.TransformerImpl;
@@ -171,10 +172,12 @@ public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
*/
private void transformSelectedNodes(TransformerImpl transformer) throws TransformerException {
- XPathContext xctxt = transformer.getXPathContext();
+ XPathContext xctxt = transformer.getXPathContext();
final int sourceNode = xctxt.getCurrentNode();
+ SourceLocator srcLocator = xctxt.getSAXLocator();
+
xctxt.setPos(0);
xctxt.setLast(0);
@@ -201,38 +204,34 @@ public class ElemIterate extends ElemTemplateElement implements ExpressionOwner
}
if (dtmIter != null) {
- ResultSequence rSeq = null;
+ ResultSequence resultSeq = null;
if (func != null) {
- rSeq = new ResultSequence();
+ resultSeq = new ResultSequence();
int nextNode;
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- // Evaluate an XPath path expression like /a/b/funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject funcEvalResult = func.execute(xctxt);
- rSeq.add(funcEvalResult);
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
+ // Evaluate an XPath expression like /a/b/funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixFunction(xctxt, srcLocator, func, xdmNodeObj);
+ resultSeq.add(evalResult);
}
- inpXObject = rSeq;
+ inpXObject = resultSeq;
}
else if (dfc != null) {
- rSeq = new ResultSequence();
+ resultSeq = new ResultSequence();
int nextNode;
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- // Evaluate an XPath path expression like /a/b/$funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject funcEvalResult = dfc.execute(xctxt);
- rSeq.add(funcEvalResult);
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
+ // Evaluate an XPath expression like /a/b/$funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixDfc(xctxt, dfc, xdmNodeObj);
+ resultSeq.add(evalResult);
}
- inpXObject = rSeq;
+ inpXObject = resultSeq;
}
}
}
diff --git a/src/main/java/org/apache/xalan/templates/ElemTemplateElement.java b/src/main/java/org/apache/xalan/templates/ElemTemplateElement.java
index 4339b4747..19e3875cc 100644
--- a/src/main/java/org/apache/xalan/templates/ElemTemplateElement.java
+++ b/src/main/java/org/apache/xalan/templates/ElemTemplateElement.java
@@ -49,6 +49,8 @@ import org.apache.xpath.WhitespaceStrippingElementMatcher;
import org.apache.xpath.XPath;
import org.apache.xpath.XPathContext;
import org.apache.xpath.composite.SequenceTypeSupport;
+import org.apache.xpath.functions.Function;
+import org.apache.xpath.functions.XPathDynamicFunctionCall;
import org.apache.xpath.objects.ResultSequence;
import org.apache.xpath.objects.XMLNodeCursorImpl;
import org.apache.xpath.objects.XObject;
@@ -2161,4 +2163,60 @@ public class ElemTemplateElement extends UnImplNode
(Constants.XS_VALIDATION_STRIP_STRING).equals(validationStr));
}
+ /**
+ * This method definition, evaluates an XPath expression suffix function call funcCall(..)
+ * within an expression like like /a/b/funcCall(..).
+ *
+ * @param xctxt An XPath context object
+ * @param srcLocator An XPath SourceLocator object
+ * @param func An XPath function compiled expression
+ * @param xdmNodeObj An XDM node object
+ * @return Result of function call evaluation
+ * @throws TransformerException
+ */
+ protected XObject evaluateXPathSuffixFunction(XPathContext xctxt, SourceLocator srcLocator, Function func, XMLNodeCursorImpl
+ xdmNodeObj) throws TransformerException {
+ XObject evalResult = null;
+
+ xctxt.setXPath3ContextItem(xdmNodeObj);
+
+ Expression arg0 = func.getArg0();
+ if (arg0 == null) {
+ XPath argXPath = new XPath(".", srcLocator, xctxt.getNamespaceContext(), XPath.SELECT, null);
+ arg0 = argXPath.getExpression();
+ func.setArg0(arg0);
+ }
+
+ evalResult = func.execute(xctxt);
+
+ return evalResult;
+ }
+
+ /**
+ * This method definition, evaluates an XPath expression suffix dynamic function call
+ * $funcCall(..) within an expression like like /a/b/$funcCall(..).
+ *
+ * @param xctxt An XPath context object
+ * @param dfc An XPath dynamic function call compiled expression
+ * @param xdmNodeObj An XDM node object
+ * @return Result of function call evaluation
+ * @throws TransformerException
+ */
+ protected XObject evaluateXPathSuffixDfc(XPathContext xctxt, XPathDynamicFunctionCall dfc, XMLNodeCursorImpl xdmNodeObj)
+ throws TransformerException {
+ XObject evalResult = null;
+
+ xctxt.setXPath3ContextItem(xdmNodeObj);
+
+ List<String> argList = dfc.getArgList();
+ if (argList.size() == 0) {
+ argList.add(".");
+ dfc.setArgList(argList);
+ }
+
+ evalResult = dfc.execute(xctxt);
+
+ return evalResult;
+ }
+
}
diff --git a/src/main/java/org/apache/xalan/templates/ElemValueOf.java b/src/main/java/org/apache/xalan/templates/ElemValueOf.java
index c85eba7e1..20c67bf20 100644
--- a/src/main/java/org/apache/xalan/templates/ElemValueOf.java
+++ b/src/main/java/org/apache/xalan/templates/ElemValueOf.java
@@ -471,26 +471,22 @@ public class ElemValueOf extends ElemTemplateElement {
StringBuffer strBuff = new StringBuffer();
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
String resultStr = "";
if (func != null) {
- // Evaluate an XPath path expression like /a/b/funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject funcEvalResult = func.execute(xctxt);
- resultStr = XslTransformEvaluationHelper.getStrVal(funcEvalResult);
+ // Evaluate an XPath expression like /a/b/funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixFunction(xctxt, srcLocator, func, xdmNodeObj);
+ resultStr = XslTransformEvaluationHelper.getStrVal(evalResult);
}
else if (dfc != null) {
- // Evaluate an XPath path expression like /a/b/$funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject evalResult = dfc.execute(xctxt);
+ // Evaluate an XPath expression like /a/b/$funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixDfc(xctxt, dfc, xdmNodeObj);
resultStr = XslTransformEvaluationHelper.getStrVal(evalResult);
}
else {
- resultStr = singletonXPathNode.str();
+ resultStr = xdmNodeObj.str();
}
strBuff.append(resultStr + " ");
}
diff --git a/src/main/java/org/apache/xalan/templates/ElemVariable.java b/src/main/java/org/apache/xalan/templates/ElemVariable.java
index de31ed9d5..3918bdf09 100644
--- a/src/main/java/org/apache/xalan/templates/ElemVariable.java
+++ b/src/main/java/org/apache/xalan/templates/ElemVariable.java
@@ -497,38 +497,34 @@ public class ElemVariable extends ElemTemplateElement
}
if (dtmIter != null) {
- ResultSequence rSeq = null;
+ ResultSequence resultSeq = null;
if (func != null) {
- rSeq = new ResultSequence();
+ resultSeq = new ResultSequence();
int nextNode;
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- // Evaluate an XPath path expression like /a/b/funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject funcEvalResult = func.execute(xctxt);
- rSeq.add(funcEvalResult);
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
+ // Evaluate an XPath expression like /a/b/funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixFunction(xctxt, srcLocator, func, xdmNodeObj);
+ resultSeq.add(evalResult);
}
- var = rSeq;
+ var = resultSeq;
}
else if (dfc != null) {
- rSeq = new ResultSequence();
+ resultSeq = new ResultSequence();
int nextNode;
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- // Evaluate an XPath path expression like /a/b/$funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject evalResult = dfc.execute(xctxt);
- rSeq.add(evalResult);
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
+ // Evaluate an XPath expression like /a/b/$funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixDfc(xctxt, dfc, xdmNodeObj);
+ resultSeq.add(evalResult);
}
- var = rSeq;
+ var = resultSeq;
}
else {
var = new XMLNodeCursorImpl(dtmIter);
diff --git a/src/main/java/org/apache/xpath/Expression.java b/src/main/java/org/apache/xpath/Expression.java
index 37e1dd076..9dd4b67ca 100644
--- a/src/main/java/org/apache/xpath/Expression.java
+++ b/src/main/java/org/apache/xpath/Expression.java
@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.List;
import javax.xml.transform.ErrorListener;
+import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;
import org.apache.xalan.res.XSLMessages;
@@ -31,6 +32,8 @@ import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMCursorIterator;
import org.apache.xml.utils.QName;
import org.apache.xml.utils.XMLString;
+import org.apache.xpath.functions.Function;
+import org.apache.xpath.functions.XPathDynamicFunctionCall;
import org.apache.xpath.objects.XMLNodeCursorImpl;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.res.XPATHErrorResources;
@@ -590,4 +593,61 @@ public abstract class Expression implements java.io.Serializable, ExpressionNode
return 0;
return m_parent.getColumnNumber();
}
+
+ /**
+ * This method definition, evaluates an XPath expression suffix function call funcCall(..)
+ * within an expression like like /a/b/funcCall(..).
+ *
+ * @param xctxt An XPath context object
+ * @param srcLocator An XPath SourceLocator object
+ * @param func An XPath function compiled expression
+ * @param xdmNodeObj An XDM node object
+ * @return Result of function call evaluation
+ * @throws TransformerException
+ */
+ protected XObject evaluateXPathSuffixFunction(XPathContext xctxt, SourceLocator srcLocator, Function func, XMLNodeCursorImpl
+ xdmNodeObj) throws TransformerException {
+ XObject evalResult = null;
+
+ xctxt.setXPath3ContextItem(xdmNodeObj);
+
+ Expression arg0 = func.getArg0();
+ if (arg0 == null) {
+ XPath argXPath = new XPath(".", srcLocator, xctxt.getNamespaceContext(), XPath.SELECT, null);
+ arg0 = argXPath.getExpression();
+ func.setArg0(arg0);
+ }
+
+ evalResult = func.execute(xctxt);
+
+ return evalResult;
+ }
+
+ /**
+ * This method definition, evaluates an XPath expression suffix dynamic function call
+ * $funcCall(..) within an expression like like /a/b/$funcCall(..).
+ *
+ * @param xctxt An XPath context object
+ * @param dfc An XPath dynamic function call compiled expression
+ * @param xdmNodeObj An XDM node object
+ * @return Result of function call evaluation
+ * @throws TransformerException
+ */
+ protected XObject evaluateXPathSuffixDfc(XPathContext xctxt, XPathDynamicFunctionCall dfc, XMLNodeCursorImpl xdmNodeObj)
+ throws TransformerException {
+ XObject evalResult = null;
+
+ xctxt.setXPath3ContextItem(xdmNodeObj);
+
+ List<String> argList = dfc.getArgList();
+ if (argList.size() == 0) {
+ argList.add(".");
+ dfc.setArgList(argList);
+ }
+
+ evalResult = dfc.execute(xctxt);
+
+ return evalResult;
+ }
+
}
diff --git a/src/main/java/org/apache/xpath/axes/LocPathIterator.java b/src/main/java/org/apache/xpath/axes/LocPathIterator.java
index 115fa3e61..cd607715e 100644
--- a/src/main/java/org/apache/xpath/axes/LocPathIterator.java
+++ b/src/main/java/org/apache/xpath/axes/LocPathIterator.java
@@ -48,6 +48,7 @@ import org.apache.xpath.res.XPATHErrorResources;
* in the NodeVector, so that previousNode() can easily be done, except in
* the case where the LocPathIterator is "owned" by a UnionPathIterator,
* in which case the UnionPathIterator will cache the nodes.</p>
+ *
* @xsl.usage advanced
*/
public abstract class LocPathIterator extends PredicatedNodeTest
@@ -56,17 +57,17 @@ public abstract class LocPathIterator extends PredicatedNodeTest
static final long serialVersionUID = -4602476357268405754L;
/**
- * If there's a function call suffix at an end of XPath path expression
- * similar to /a/b/func(..), we keep a compiled Function
+ * If there's a function call suffix in an XPath expression
+ * string similar to /a/b/func(..), we keep a compiled Function
* object for func(..) within this class field.
*/
private Function m_func_expr = null;
/**
- * If there's an XPath dynamic function call suffix at an end of
- * XPath path expression similar to /a/b/$func(..), we keep a
- * compiled XPathDynamicFunctionCall object for $func(..) within
- * this class field.
+ * If there's a dynamic function call suffix in an XPath expression
+ * string similar to /a/b/$func(..), we keep a compiled
+ * XPathDynamicFunctionCall object for $func(..) within this class
+ * field.
*/
private XPathDynamicFunctionCall m_dfc_expr = null;
diff --git a/src/main/java/org/apache/xpath/composite/XPathForExpr.java b/src/main/java/org/apache/xpath/composite/XPathForExpr.java
index 139fe1e1e..182e77b35 100644
--- a/src/main/java/org/apache/xpath/composite/XPathForExpr.java
+++ b/src/main/java/org/apache/xpath/composite/XPathForExpr.java
@@ -173,7 +173,7 @@ public class XPathForExpr extends Expression {
Expression xpathExpr = varBindingXPath.getExpression();
- ResultSequence xsObjResultSeq = new ResultSequence();
+ ResultSequence resultSeq2 = new ResultSequence();
if (xpathExpr instanceof LocPathIterator) {
LocPathIterator locPathIterator = (LocPathIterator)xpathExpr;
@@ -194,26 +194,22 @@ public class XPathForExpr extends Expression {
int nextNode;
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- // Evaluate an XPath path expression like /a/b/funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject funcEvalResult = func.execute(xctxt);
- xsObjResultSeq.add(funcEvalResult);
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
+ // Evaluate an XPath expression like /a/b/funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixFunction(xctxt, srcLocator, func, xdmNodeObj);
+ resultSeq2.add(evalResult);
}
}
else if (dfc != null) {
int nextNode;
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
- XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- // Evaluate an XPath path expression like /a/b/$funcCall(..).
- // Find one result item here for a sequence of items,
- // since this is within a loop.
- xctxt.setXPath3ContextItem(singletonXPathNode);
- XObject dfcEvalResult = dfc.execute(xctxt);
- xsObjResultSeq.add(dfcEvalResult);
+ XMLNodeCursorImpl xdmNodeObj = new XMLNodeCursorImpl(nextNode, xctxt);
+ // Evaluate an XPath expression like /a/b/$funcCall(..).
+ // Find one result item for a sequence of items.
+ XObject evalResult = evaluateXPathSuffixDfc(xctxt, dfc, xdmNodeObj);
+ resultSeq2.add(evalResult);
}
}
else {
@@ -221,7 +217,7 @@ public class XPathForExpr extends Expression {
while ((nextNode = dtmIter.nextNode()) != DTM.NULL)
{
XMLNodeCursorImpl singletonXPathNode = new XMLNodeCursorImpl(nextNode, xctxt);
- xsObjResultSeq.add(singletonXPathNode);
+ resultSeq2.add(singletonXPathNode);
}
}
}
@@ -237,21 +233,21 @@ public class XPathForExpr extends Expression {
while ((nextNode = dtmIter.nextNode()) != DTM.NULL) {
XMLNodeCursorImpl node = new XMLNodeCursorImpl(nextNode, xctxt);
- xsObjResultSeq.add(node);
+ resultSeq2.add(node);
}
}
else if (xsObj instanceof ResultSequence) {
ResultSequence rSeq = (ResultSequence)xsObj;
for (int idx = 0; idx < rSeq.size(); idx++) {
- xsObjResultSeq.add(rSeq.item(idx));
+ resultSeq2.add(rSeq.item(idx));
}
}
else {
- xsObjResultSeq.add(xsObj);
+ resultSeq2.add(xsObj);
}
}
- if (xsObjResultSeq.size() == 0) {
+ if (resultSeq2.size() == 0) {
listIter.previous();
return resultSeq;
@@ -262,8 +258,8 @@ public class XPathForExpr extends Expression {
// For each xdm item within sequence object 'xsObjResultSeq' (which is the
// result of variable binding xpath expression's evaluation), bind the 'for'
// expression's binding variable in turn to that item.
- for (int idx = 0; idx < xsObjResultSeq.size(); idx++) {
- XObject xdmItem = xsObjResultSeq.item(idx);
+ for (int idx = 0; idx < resultSeq2.size(); idx++) {
+ XObject xdmItem = resultSeq2.item(idx);
forExprVarBindingMap.put(new QName(varName), xdmItem);
diff --git a/src/test/java/org/apache/xalan/tests/xpath3/XPathExprFunctionCallSuffixTests.java b/src/test/java/org/apache/xalan/tests/xpath3/XPathExprFunctionCallSuffixTests.java
index cdc8da2e8..b88ef64be 100644
--- a/src/test/java/org/apache/xalan/tests/xpath3/XPathExprFunctionCallSuffixTests.java
+++ b/src/test/java/org/apache/xalan/tests/xpath3/XPathExprFunctionCallSuffixTests.java
@@ -207,5 +207,45 @@ public class XPathExprFunctionCallSuffixTests extends XslTransformTestsUtil {
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
}
+
+ @Test
+ public void xpathExprFunctionCallSuffixTest17() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test17.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test17.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test17.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xpathExprFunctionCallSuffixTest18() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test18.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test18.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test18.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xpathExprFunctionCallSuffixTest19() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test19.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test18.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test19.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xpathExprFunctionCallSuffixTest20() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test20.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test19.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test20.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
}
diff --git a/src/test/resources/xpath_function_call_suffix/gold/test17.out b/src/test/resources/xpath_function_call_suffix/gold/test17.out
new file mode 100644
index 000000000..36b38aae1
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/gold/test17.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+ <one>a b c</one>
+ <two>a b c</two>
+</result>
diff --git a/src/test/resources/xpath_function_call_suffix/gold/test18.out b/src/test/resources/xpath_function_call_suffix/gold/test18.out
new file mode 100644
index 000000000..45cf1f174
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/gold/test18.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+ <one>pos1 pos2 pos3</one>
+ <two>pos1 pos2 pos3</two>
+</result>
diff --git a/src/test/resources/xpath_function_call_suffix/gold/test19.out b/src/test/resources/xpath_function_call_suffix/gold/test19.out
new file mode 100644
index 000000000..ee154c4f6
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/gold/test19.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+ <one>pos1 pos2 pos3 pos4 pos5 pos6</one>
+ <two>pos1 pos2 pos3 pos4 pos5 pos6</two>
+</result>
diff --git a/src/test/resources/xpath_function_call_suffix/gold/test20.out b/src/test/resources/xpath_function_call_suffix/gold/test20.out
new file mode 100644
index 000000000..1f2b6347b
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/gold/test20.out
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+ <P>
+ <one>pos1 pos2 pos3 pos4 pos5 pos6</one>
+ <two>pos6 pos5 pos4 pos3 pos2 pos1</two>
+ </P>
+ <Q>
+ <one>pos1 pos2 pos3 pos4 pos5 pos6</one>
+ <two>pos6 pos5 pos4 pos3 pos2 pos1</two>
+ </Q>
+</result>
diff --git a/src/test/resources/xpath_function_call_suffix/test17.xml b/src/test/resources/xpath_function_call_suffix/test17.xml
new file mode 100644
index 000000000..ed08439ca
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/test17.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<temp>
+ <a>1</a>
+ <b>2</b>
+ <c>3</c>
+</temp>
diff --git a/src/test/resources/xpath_function_call_suffix/test17.xsl b/src/test/resources/xpath_function_call_suffix/test17.xsl
new file mode 100644
index 000000000..4d5af9bb5
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/test17.xsl
@@ -0,0 +1,39 @@
+<?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 -->
+
+ <!-- use with test17.xml -->
+
+ <!-- An XSL stylesheet test case, to test XPath function call as
+ suffix of XPath path expression string. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/">
+ <result>
+ <one><xsl:value-of select="/temp/*/name()"/></one>
+ <two><xsl:value-of select="/temp/*/name(.)"/></two>
+ </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>
diff --git a/src/test/resources/xpath_function_call_suffix/test18.xml b/src/test/resources/xpath_function_call_suffix/test18.xml
new file mode 100644
index 000000000..c21faab6e
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/test18.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<temp>
+ <one pos1="1">a</one>
+ <two pos2="2">b</two>
+ <three pos3="3">c</three>
+</temp>
diff --git a/src/test/resources/xpath_function_call_suffix/test18.xsl b/src/test/resources/xpath_function_call_suffix/test18.xsl
new file mode 100644
index 000000000..f592f218b
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/test18.xsl
@@ -0,0 +1,39 @@
+<?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 -->
+
+ <!-- use with test18.xml, test19.xml -->
+
+ <!-- An XSL stylesheet test case, to test XPath function call as
+ suffix of XPath path expression string. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/">
+ <result>
+ <one><xsl:value-of select="/temp/*/@*/name()"/></one>
+ <two><xsl:value-of select="/temp/*/@*/name(.)"/></two>
+ </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>
diff --git a/src/test/resources/xpath_function_call_suffix/test19.xml b/src/test/resources/xpath_function_call_suffix/test19.xml
new file mode 100644
index 000000000..8f2d94c31
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/test19.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<temp>
+ <one pos1="1" pos2="2">a</one>
+ <two pos3="3" pos4="4">b</two>
+ <three pos5="5" pos6="6">c</three>
+</temp>
diff --git a/src/test/resources/xpath_function_call_suffix/test19.xsl b/src/test/resources/xpath_function_call_suffix/test19.xsl
new file mode 100644
index 000000000..551c1a925
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/test19.xsl
@@ -0,0 +1,47 @@
+<?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 -->
+
+ <!-- use with test20.xml -->
+
+ <!-- An XSL stylesheet test case, to test XPath dynamic function
+ call as suffix of XPath path expression string. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/">
+ <result>
+ <P>
+ <xsl:variable name="attrNames" select="/temp/*/@*/name()"/>
+ <one><xsl:value-of select="sort($attrNames)"/></one>
+ <two><xsl:value-of select="reverse(sort($attrNames))"/></two>
+ </P>
+ <Q>
+ <xsl:variable name="attrNames" select="/temp/*/@*/name(.)"/>
+ <one><xsl:value-of select="sort($attrNames)"/></one>
+ <two><xsl:value-of select="reverse(sort($attrNames))"/></two>
+ </Q>
+ </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>
diff --git a/src/test/resources/xpath_function_call_suffix/test20.xml b/src/test/resources/xpath_function_call_suffix/test20.xml
new file mode 100644
index 000000000..bbe93d007
--- /dev/null
+++ b/src/test/resources/xpath_function_call_suffix/test20.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<temp>
+ <one pos5="1" pos6="2">a</one>
+ <two pos1="3" pos2="4">b</two>
+ <three pos3="5" pos4="6">c</three>
+</temp>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org