[prev in list] [next in list] [prev in thread] [next in thread]
List: xalan-cvs
Subject: [xalan-java] branch xalan-j_xslt3.0 updated: implementing xsl:for-each-group's order of first appear
From: mukulg () apache ! org
Date: 2023-05-08 12:55:13
Message-ID: 168355051327.2746759.16545697947063418974 () gitbox2-he-fi ! apache ! org
[Download RAW message or body]
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 ff77938b implementing xsl:for-each-group's order of first appearance concept \
as defined by xslt 3.0 spec, when xsl:sort elements are not present within \
xsl:for-each-group ff77938b is described below
commit ff77938b9172b0fa65366973231f24db7af743b3
Author: Mukul Gandhi <gandhi.mukul@gmail.com>
AuthorDate: Mon May 8 18:24:46 2023 +0530
implementing xsl:for-each-group's order of first appearance concept as defined by \
xslt 3.0 spec, when xsl:sort elements are not present within \
xsl:for-each-group
---
.../apache/xalan/templates/ElemForEachGroup.java | 110 ++++++++++++++++-----
1 file changed, 87 insertions(+), 23 deletions(-)
diff --git a/src/org/apache/xalan/templates/ElemForEachGroup.java \
b/src/org/apache/xalan/templates/ElemForEachGroup.java index 25d7de25..3ac050cc \
100644
--- a/src/org/apache/xalan/templates/ElemForEachGroup.java
+++ b/src/org/apache/xalan/templates/ElemForEachGroup.java
@@ -21,6 +21,7 @@
package org.apache.xalan.templates;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -361,11 +362,15 @@ public class ElemForEachGroup extends ElemTemplateElement \
implements ExpressionO final int sourceNode = xctxt.getCurrentNode();
DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);
- // form groups from the 'sourceNodes' iterator
+ // form xsl:for-each-group raw groups data from the 'sourceNodes' iterator
// grouping keys, can have data types as defined by XPath data model.
- // hashmap's key is the grouping key, and value is a list of nodes dtm \
integer handles
- Map<Object, List<Integer>> groups = new HashMap<Object, List<Integer>>();
+
+ // groups data is formed, within a hashmap.
+ // hashmap item's key is the grouping key, and value of that hashmap item
+ // is a list of nodes dtm integer handles representing the group for that
+ // grouping key.
+ Map<Object, List<Integer>> xslForEachGroupMap = new HashMap<Object, \
List<Integer>>();
int nextNode;
@@ -376,13 +381,13 @@ public class ElemForEachGroup extends ElemTemplateElement \
implements ExpressionO
XObject xpathEvalResult = m_GroupByExpression.execute(xctxt); \
Object xpathRawResult = \
getXPathEvaluationRawResult(xpathEvalResult);
- if (groups.get(xpathRawResult) != null) {
- List<Integer> group = groups.get(xpathRawResult);
+ if (xslForEachGroupMap.get(xpathRawResult) != null) {
+ List<Integer> group = xslForEachGroupMap.get(xpathRawResult);
group.add(nextNode);
} else {
List<Integer> group = new ArrayList<Integer>();
group.add(nextNode);
- groups.put(xpathRawResult, group);
+ xslForEachGroupMap.put(xpathRawResult, group);
}
}
}
@@ -397,22 +402,22 @@ public class ElemForEachGroup extends ElemTemplateElement \
implements ExpressionO Object currValue = xpathRawResult;
if (idx == 0) {
- // first node within the nodes been traversed
+ // first node within the nodes been traversed, by this loop
List<Integer> group = new ArrayList<Integer>();
group.add(nextNode);
- groups.put(currValue, group);
+ xslForEachGroupMap.put(currValue, group);
prevValue = currValue;
}
else {
if (currValue.equals(prevValue)) {
- List<Integer> group = groups.get(prevValue);
+ List<Integer> group = xslForEachGroupMap.get(prevValue);
group.add(nextNode);
prevValue = currValue;
}
else {
List<Integer> group = new ArrayList<Integer>();
group.add(nextNode);
- groups.put(currValue, group);
+ xslForEachGroupMap.put(currValue, group);
prevValue = currValue;
}
}
@@ -421,7 +426,25 @@ public class ElemForEachGroup extends ElemTemplateElement \
implements ExpressionO }
}
- // end, form groups from the 'sourceNodes' iterator
+ // end, form xsl:for-each-group raw groups data from the 'sourceNodes' \
iterator +
+ // reorder xsl:for-each-group raw groups content known as 'order of first \
appearance' + // as defined by XSLT 3.0 spec (this is the default XSLT \
transformation xsl:for-each-group + // element's output order in absence of \
xsl:for-each-group's xsl:sort elements). + \
List<GroupingKeyAndNodeHandlePair> groupingKeyAndNodeHandlePairList = new ArrayList + \
<GroupingKeyAndNodeHandlePair>(); + if (xslForEachGroupMap.size() > \
0) { + \
Set<Object> groupingKeys = xslForEachGroupMap.keySet(); + for \
(Iterator<Object> groupingKeysIter = groupingKeys.iterator(); + \
groupingKeysIter.hasNext(); ) { + Object groupingKey = \
groupingKeysIter.next(); + List<Integer> groupNodesDtmHandles = \
xslForEachGroupMap.get(groupingKey); + Integer \
groupContentsFirstItemNodeHandle = groupNodesDtmHandles.get(0); + \
GroupingKeyAndNodeHandlePair groupingKeyNodeHandlePair = new \
GroupingKeyAndNodeHandlePair( + \
groupingKey, groupContentsFirstItemNodeHandle); + \
groupingKeyAndNodeHandlePairList.add(groupingKeyNodeHandlePair); + } \
+ }
try {
xctxt.pushCurrentNode(DTM.NULL);
@@ -430,14 +453,16 @@ public class ElemForEachGroup extends ElemTemplateElement \
implements ExpressionO xctxt.pushSAXLocatorNull();
xctxt.pushContextNodeList(sourceNodes);
transformer.pushElemTemplateElement(null);
+
+ Collections.sort(groupingKeyAndNodeHandlePairList); // sort the \
xsl:for-each-group's groups
- Set<Object> groupingKeys = groups.keySet();
-
- // iterate through all the, groups formed by xsl:for-each-group \
instruction,
- // and process the XSLT contents for each group.
- for (Iterator<Object> iter = groupingKeys.iterator(); iter.hasNext(); ) \
{
- Object groupingKey = iter.next(); // current-grouping-key() value, \
for this group
- List<Integer> groupNodesDtmHandles = groups.get(groupingKey); // \
current-group() contents, for this group + \
// loop through all the, groups formed by xsl:for-each-group instruction, + \
// and process the XSLT contents of each group. + for (int idx = 0; idx < \
groupingKeyAndNodeHandlePairList.size(); idx++) { + \
GroupingKeyAndNodeHandlePair groupingKeyNodeLevelPair = \
groupingKeyAndNodeHandlePairList.get(idx); +
+ Object groupingKey = groupingKeyNodeLevelPair.getGroupingKey(); // \
current-grouping-key() value, for this group + List<Integer> \
groupNodesDtmHandles = xslForEachGroupMap.get(groupingKey); // current-group() \
contents, for this group
for (ElemTemplateElement templateElem = this.m_firstChild; \
templateElem != null;
templateElem = \
templateElem.m_nextSibling) { @@ -448,9 +473,9 @@ public class ElemForEachGroup \
extends ElemTemplateElement implements ExpressionO \
templateElem.execute(transformer); }
}
- }
- finally
- {
+ }
+ finally
+ {
if (transformer.getDebug()) {
transformer.getTraceManager().fireSelectedEndEvent(sourceNode, \
this,
"select", new XPath(m_selectExpression),
@@ -463,9 +488,9 @@ public class ElemForEachGroup extends ElemTemplateElement \
implements ExpressionO xctxt.popCurrentExpressionNode();
xctxt.popCurrentNode();
sourceNodes.detach();
- }
+ }
- xctxt.pushCurrentNode(sourceNode);
+ xctxt.pushCurrentNode(sourceNode);
}
/**
@@ -555,5 +580,44 @@ public class ElemForEachGroup extends ElemTemplateElement \
implements ExpressionO
return xpathRawResult;
}
+
+ /*
+ * Class to support, reordering the xsl:for-each-group's groups as per definition \
of default + * sorted order (i.e, order of first appearance) when xsl:sort \
elements are not present within + * xsl:for-each-group.
+ */
+ class GroupingKeyAndNodeHandlePair implements \
Comparable<GroupingKeyAndNodeHandlePair> { +
+ private Object groupingKey;
+
+ private Integer nodeHandle;
+
+ public GroupingKeyAndNodeHandlePair(Object groupingKey, Integer nodeHandle) {
+ this.groupingKey = groupingKey;
+ this.nodeHandle = nodeHandle;
+ }
+
+ public Object getGroupingKey() {
+ return groupingKey;
+ }
+
+ public void setGroupingKey(Object groupingKey) {
+ this.groupingKey = groupingKey;
+ }
+
+ public Integer getNodeHandle() {
+ return nodeHandle;
+ }
+
+ public void setNodeHandle(Integer nodeHandle) {
+ this.nodeHandle = nodeHandle;
+ }
+
+ @Override
+ public int compareTo(GroupingKeyAndNodeHandlePair obj) {
+ return this.getNodeHandle().compareTo(obj.getNodeHandle());
+ }
+
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic