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/04 09:56:30 UTC
(xalan-java) branch xalan-j_xslt3.0_mvn updated: committing fixes for xsl:for-each-group instruction implementation, for few of w3c xslt 3.0 xsl:for-each-group 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 3b8e534b3 committing fixes for xsl:for-each-group instruction implementation, for few of w3c xslt 3.0 xsl:for-each-group test cases
3b8e534b3 is described below
commit 3b8e534b3514da86b43e70f6d026f353b1fc8610
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sun May 4 15:26:13 2025 +0530
committing fixes for xsl:for-each-group instruction implementation, for few of w3c xslt 3.0 xsl:for-each-group test cases
---
.../apache/xalan/processor/XSLTAttributeDef.java | 7 +-
.../java/org/apache/xalan/templates/Constants.java | 1 +
.../apache/xalan/templates/ElemForEachGroup.java | 82 ++++++++++++++--------
.../org/apache/xpath/functions/FuncPosition.java | 5 +-
.../java/org/apache/xpath/operations/Variable.java | 18 +++--
5 files changed, 77 insertions(+), 36 deletions(-)
diff --git a/src/main/java/org/apache/xalan/processor/XSLTAttributeDef.java b/src/main/java/org/apache/xalan/processor/XSLTAttributeDef.java
index d4beb3125..dab0ba88c 100644
--- a/src/main/java/org/apache/xalan/processor/XSLTAttributeDef.java
+++ b/src/main/java/org/apache/xalan/processor/XSLTAttributeDef.java
@@ -768,7 +768,8 @@ public class XSLTAttributeDef
XPath expr = null;
String normalizedStrValue = null;
- if ((owner instanceof ElemForEachGroup) && (Constants.ATTRNAME_GROUPBY).equals(name)) {
+ if ((owner instanceof ElemForEachGroup) && ((Constants.ATTRNAME_GROUPBY).equals(name) ||
+ (Constants.ATTRNAME_GROUP_ADJACENT).equals(name))) {
if (value != null) {
normalizedStrValue = getForEachGroupAttrNormalizedStrValue(value);
if (normalizedStrValue != null) {
@@ -1391,13 +1392,13 @@ public class XSLTAttributeDef
{
// Is this already checked somewhere else? -sb
- if (!(value.equals("yes") || value.equals("no")))
+ if (!(value.equals("yes") || value.equals("true") || value.equals("no") || value.equals("false")))
{
handleError(handler, XSLTErrorResources.INVALID_BOOLEAN, new Object[] {name,value}, null);
return null;
}
- return new Boolean(value.equals("yes") ? true : false);
+ return new Boolean((value.equals("yes") || value.equals("true")) ? true : false);
}
/**
diff --git a/src/main/java/org/apache/xalan/templates/Constants.java b/src/main/java/org/apache/xalan/templates/Constants.java
index 7cbcb0730..e9aff8e51 100644
--- a/src/main/java/org/apache/xalan/templates/Constants.java
+++ b/src/main/java/org/apache/xalan/templates/Constants.java
@@ -282,6 +282,7 @@ public class Constants extends org.apache.xml.utils.Constants
ATTRNAME_GROUPINGSEPARATOR = "grouping-separator",
ATTRNAME_GROUPINGSIZE = "grouping-size",
ATTRNAME_GROUPBY = "group-by",
+ ATTRNAME_GROUP_ADJACENT = "group-adjacent",
ATTRNAME_HREF = "href",
ATTRNAME_ID = "id",
ATTRNAME_IMPORTANCE = "importance",
diff --git a/src/main/java/org/apache/xalan/templates/ElemForEachGroup.java b/src/main/java/org/apache/xalan/templates/ElemForEachGroup.java
index 1c14a505c..304d1fb72 100644
--- a/src/main/java/org/apache/xalan/templates/ElemForEachGroup.java
+++ b/src/main/java/org/apache/xalan/templates/ElemForEachGroup.java
@@ -47,6 +47,7 @@ import org.apache.xpath.XPathContext;
import org.apache.xpath.axes.NodeCursor;
import org.apache.xpath.composite.XPathForExpr;
import org.apache.xpath.composite.XPathSequenceConstructor;
+import org.apache.xpath.functions.FuncPosition;
import org.apache.xpath.objects.ResultSequence;
import org.apache.xpath.objects.XBoolean;
import org.apache.xpath.objects.XBooleanStatic;
@@ -804,33 +805,41 @@ public class ElemForEachGroup extends ElemTemplateElement
int nextNode;
SourceLocator srcLocator = xctxt.getSAXLocator();
+
+ try {
+ int pos = 0;
+
+ while (DTM.NULL != (nextNode = sourceNodes.nextNode())) {
+ FuncPosition.m_forEachGroupGroupByPos = ++pos;
+ XObject xpathEvalResult = m_GroupByExpression.execute(xctxt, nextNode, xctxt.getNamespaceContext());
+ Object groupingKeyValue = getNormalizedGroupingKeyValue(xctxt, xpathEvalResult);
- while (DTM.NULL != (nextNode = sourceNodes.nextNode())) {
- XObject xpathEvalResult = m_GroupByExpression.execute(xctxt, nextNode, xctxt.getNamespaceContext());
- Object groupingKeyValue = getNormalizedGroupingKeyValue(xctxt, xpathEvalResult);
-
- if (!m_composite) {
- addXdmNodeHandleToGroup(xslForEachGroupByMap, nextNode, groupingKeyValue);
- }
- else {
- // Processing for xsl:for-each-group's composite grouping key
- if (groupingKeyValue instanceof ForEachGroupCompositeGroupingKey) {
- ForEachGroupCompositeGroupingKey groupingKeyObj = (ForEachGroupCompositeGroupingKey)groupingKeyValue;
- ResultSequence groupingKeySeq = groupingKeyObj.getValue();
- if (groupingKeySeq.size() >= 1) {
- addXdmNodeHandleToGroup(xslForEachGroupByMap, nextNode, groupingKeyValue);
+ if (!m_composite) {
+ addXdmNodeHandleToGroup(xslForEachGroupByMap, nextNode, groupingKeyValue);
+ }
+ else {
+ // Processing for xsl:for-each-group's composite grouping key
+ if (groupingKeyValue instanceof ForEachGroupCompositeGroupingKey) {
+ ForEachGroupCompositeGroupingKey groupingKeyObj = (ForEachGroupCompositeGroupingKey)groupingKeyValue;
+ ResultSequence groupingKeySeq = groupingKeyObj.getValue();
+ if (groupingKeySeq.size() >= 1) {
+ addXdmNodeHandleToGroup(xslForEachGroupByMap, nextNode, groupingKeyValue);
+ }
+ else {
+ throw new TransformerException("XTSE1080 : An xsl:for-each-group instruction with attribute "
+ + "'composite=\"yes\"', resulted in a grouping key "
+ + "sequence that is empty.", srcLocator);
+ }
}
else {
- throw new TransformerException("XTSE1080 : An xsl:for-each-group instruction with attribute "
- + "value 'composite=\"yes\"', resulted in a grouping key "
- + "sequence that is empty.", srcLocator);
+ addXdmNodeHandleToGroup(xslForEachGroupByMap, nextNode, groupingKeyValue);
}
}
- else {
- addXdmNodeHandleToGroup(xslForEachGroupByMap, nextNode, groupingKeyValue);
- }
}
}
+ finally {
+ FuncPosition.m_forEachGroupGroupByPos = 0;
+ }
}
/**
@@ -1008,14 +1017,31 @@ public class ElemForEachGroup extends ElemTemplateElement
*/
private void constructGroupsForGroupAdjacent(XPathContext xctxt, DTMCursorIterator sourceNodes,
List<GroupingKeyAndGroupPair> xslForEachGroupAdjacentList) throws TransformerException {
- Object prevValue = null;
+
int idx = 0;
int nextNode;
+ Object prevGroupingKeyValue = null;
+
+ SourceLocator srcLocator = xctxt.getSAXLocator();
+
while (DTM.NULL != (nextNode = sourceNodes.nextNode())) {
XObject xpathEvalResult = m_GroupAdjacentExpression.execute(xctxt, nextNode, xctxt.getNamespaceContext());
- Object groupingKeyValue = getNormalizedGroupingKeyValue(xctxt, xpathEvalResult);
- Object currValue = groupingKeyValue;
+ Object groupingKeyValue = getNormalizedGroupingKeyValue(xctxt, xpathEvalResult);
+
+ if (m_composite) {
+ if (groupingKeyValue instanceof ForEachGroupCompositeGroupingKey) {
+ ForEachGroupCompositeGroupingKey groupingKeyObj = (ForEachGroupCompositeGroupingKey)groupingKeyValue;
+ ResultSequence groupingKeySeq = groupingKeyObj.getValue();
+ if (groupingKeySeq.size() == 0) {
+ throw new TransformerException("XTSE1080 : An xsl:for-each-group instruction with attribute "
+ + "'composite=\"yes\"', resulted in a grouping key "
+ + "sequence that is empty.", srcLocator);
+ }
+ }
+ }
+
+ Object currGroupingKeyValue = groupingKeyValue;
List<Integer> group = null;
@@ -1023,12 +1049,12 @@ public class ElemForEachGroup extends ElemTemplateElement
// This is the first XDM node being iterated, within this loop
group = new ArrayList<Integer>();
group.add(nextNode);
- GroupingKeyAndGroupPair groupingKeyAndGroupPair = new GroupingKeyAndGroupPair(currValue, group);
+ GroupingKeyAndGroupPair groupingKeyAndGroupPair = new GroupingKeyAndGroupPair(currGroupingKeyValue, group);
xslForEachGroupAdjacentList.add(groupingKeyAndGroupPair);
- prevValue = currValue;
+ prevGroupingKeyValue = currGroupingKeyValue;
}
else {
- if (currValue.equals(prevValue)) {
+ if (currGroupingKeyValue.equals(prevGroupingKeyValue)) {
int currResultSize = xslForEachGroupAdjacentList.size();
GroupingKeyAndGroupPair groupingKeyAndGroupPair = xslForEachGroupAdjacentList.get(currResultSize - 1);
group = groupingKeyAndGroupPair.getGroupNodesDtmHandles();
@@ -1037,11 +1063,11 @@ public class ElemForEachGroup extends ElemTemplateElement
else {
group = new ArrayList<Integer>();
group.add(nextNode);
- GroupingKeyAndGroupPair groupingKeyAndGroupPair = new GroupingKeyAndGroupPair(currValue, group);
+ GroupingKeyAndGroupPair groupingKeyAndGroupPair = new GroupingKeyAndGroupPair(currGroupingKeyValue, group);
xslForEachGroupAdjacentList.add(groupingKeyAndGroupPair);
}
- prevValue = currValue;
+ prevGroupingKeyValue = currGroupingKeyValue;
}
idx++;
diff --git a/src/main/java/org/apache/xpath/functions/FuncPosition.java b/src/main/java/org/apache/xpath/functions/FuncPosition.java
index f804b935c..7269a4618 100644
--- a/src/main/java/org/apache/xpath/functions/FuncPosition.java
+++ b/src/main/java/org/apache/xpath/functions/FuncPosition.java
@@ -38,6 +38,8 @@ public class FuncPosition extends Function
private boolean m_isTopLevel;
+ public static int m_forEachGroupGroupByPos = 0;
+
/**
* Figure out if we're executing a toplevel expression.
* If so, we can't be inside of a predicate.
@@ -127,7 +129,8 @@ public class FuncPosition extends Function
*/
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
{
- double pos = (xctxt.getGroupPosition() > 0) ? xctxt.getGroupPosition() : ((double) getPositionInContextNodeList(xctxt));
+ double pos = (xctxt.getGroupPosition() > 0) ? xctxt.getGroupPosition() : ((double) getPositionInContextNodeList(xctxt));
+ pos = (pos > 0) ? pos : m_forEachGroupGroupByPos;
return new XNumber(pos);
}
diff --git a/src/main/java/org/apache/xpath/operations/Variable.java b/src/main/java/org/apache/xpath/operations/Variable.java
index e389505de..c5cfe8271 100644
--- a/src/main/java/org/apache/xpath/operations/Variable.java
+++ b/src/main/java/org/apache/xpath/operations/Variable.java
@@ -267,7 +267,7 @@ public class Variable extends Expression implements PathComponent
}
}
else {
- result = xctxt.getVarStack().getVariableOrParam(xctxt,m_qname);
+ result = xctxt.getVarStack().getVariableOrParam(xctxt, m_qname);
}
}
catch (javax.xml.transform.TransformerException ex) {
@@ -281,10 +281,20 @@ public class Variable extends Expression implements PathComponent
result = xpath.execute(xctxt, xctxt.getCurrentNode(), xctxt.getNamespaceContext());
XslTransformSharedDatastore.xpathNodeCombiningExprRhsStrBuff = null;
- }
+ }
else {
- throw new javax.xml.transform.TransformerException("Variable $" + m_qname.toString() + " "
- + "accessed before it is bound!.");
+ try {
+ if (m_isGlobal) {
+ result = xctxt.getVarStack().getGlobalVariable(xctxt, m_index, destructiveOK);
+ }
+ else {
+ result = xctxt.getVarStack().getLocalVariable(xctxt, m_index, destructiveOK);
+ }
+ }
+ catch (TransformerException ex1) {
+ throw new javax.xml.transform.TransformerException("Variable $" + m_qname.toString() + " "
+ + "accessed before it is bound!.");
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org