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/04/30 17:03:05 UTC
[xalan-java] branch xalan-j_xslt3.0 updated: committing wip implementation of xslt 3.0 xsl:for-each-group instruction
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 0da6dead committing wip implementation of xslt 3.0 xsl:for-each-group instruction
0da6dead is described below
commit 0da6deadc8f06876df08d9c792fb24b4ed8fa337
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sun Apr 30 22:32:38 2023 +0530
committing wip implementation of xslt 3.0 xsl:for-each-group instruction
---
src/org/apache/xalan/processor/XSLTSchema.java | 31 +-
src/org/apache/xalan/templates/Constants.java | 14 +-
.../apache/xalan/templates/ElemForEachGroup.java | 462 +++++++++++++++++++++
.../xalan/templates/ElemTemplateElement.java | 16 +
.../apache/xalan/transformer/TransformerImpl.java | 86 ++++
5 files changed, 595 insertions(+), 14 deletions(-)
diff --git a/src/org/apache/xalan/processor/XSLTSchema.java b/src/org/apache/xalan/processor/XSLTSchema.java
index 50bf910a..e71d9a25 100644
--- a/src/org/apache/xalan/processor/XSLTSchema.java
+++ b/src/org/apache/xalan/processor/XSLTSchema.java
@@ -38,6 +38,7 @@ import org.apache.xalan.templates.ElemExtensionDecl;
import org.apache.xalan.templates.ElemExtensionScript;
import org.apache.xalan.templates.ElemFallback;
import org.apache.xalan.templates.ElemForEach;
+import org.apache.xalan.templates.ElemForEachGroup;
import org.apache.xalan.templates.ElemIf;
import org.apache.xalan.templates.ElemLiteralResult;
import org.apache.xalan.templates.ElemMessage;
@@ -192,10 +193,16 @@ public class XSLTSchema extends XSLTElementDef
// Required.
- // xsl:value-of, xsl:for-each, xsl:copy-of
+ // xsl:value-of, xsl:for-each, xsl:copy-of, xsl:for-each-group
XSLTAttributeDef selectAttrRequired = new XSLTAttributeDef(null,
"select",
- XSLTAttributeDef.T_EXPR, true, false,XSLTAttributeDef.ERROR);
+ XSLTAttributeDef.T_EXPR, true, false, XSLTAttributeDef.ERROR);
+
+ // Optional.
+ // xsl:for-each-group
+ XSLTAttributeDef groupByAttrOpt = new XSLTAttributeDef(null,
+ "group-by",
+ XSLTAttributeDef.T_EXPR, false, false, XSLTAttributeDef.ERROR);
// Optional.
// xsl:variable, xsl:param, xsl:with-param
@@ -343,13 +350,13 @@ public class XSLTSchema extends XSLTElementDef
new XSLTAttributeDef(Constants.S_XSLNAMESPACEURL, "*",
XSLTAttributeDef.T_CDATA, false, false,XSLTAttributeDef.WARNING);
- XSLTElementDef[] templateElements = new XSLTElementDef[23];
- XSLTElementDef[] templateElementsAndParams = new XSLTElementDef[24];
- XSLTElementDef[] templateElementsAndSort = new XSLTElementDef[24];
+ XSLTElementDef[] templateElements = new XSLTElementDef[24];
+ XSLTElementDef[] templateElementsAndParams = new XSLTElementDef[25];
+ XSLTElementDef[] templateElementsAndSort = new XSLTElementDef[25];
//exslt
- XSLTElementDef[] exsltFunctionElements = new XSLTElementDef[24];
+ XSLTElementDef[] exsltFunctionElements = new XSLTElementDef[25];
- XSLTElementDef[] charTemplateElements = new XSLTElementDef[15];
+ XSLTElementDef[] charTemplateElements = new XSLTElementDef[16];
XSLTElementDef resultElement = new XSLTElementDef(this, null, "*",
null /*alias */,
templateElements /* elements */,
@@ -445,6 +452,14 @@ public class XSLTSchema extends XSLTElementDef
spaceAttr },
new ProcessorTemplateElem(),
ElemForEach.class /* class object */, true, false, true, 20, true);
+
+ XSLTElementDef xslForEachGroup = new XSLTElementDef(this,
+ Constants.S_XSLNAMESPACEURL, "for-each-group",
+ null /*alias */, templateElementsAndSort,
+ new XSLTAttributeDef[]{ selectAttrRequired, groupByAttrOpt, spaceAttr },
+ new ProcessorTemplateElem(),
+ ElemForEachGroup.class /* class object */, true, false, true, 20, true);
+
XSLTElementDef xslIf = new XSLTElementDef(this,
Constants.S_XSLNAMESPACEURL,
"if", null /*alias */,
@@ -594,6 +609,7 @@ public class XSLTSchema extends XSLTElementDef
templateElements[i++] = xslCallTemplate;
templateElements[i++] = xslApplyImports;
templateElements[i++] = xslForEach;
+ templateElements[i++] = xslForEachGroup;
templateElements[i++] = xslValueOf;
templateElements[i++] = xslCopyOf;
templateElements[i++] = xslNumber;
@@ -631,6 +647,7 @@ public class XSLTSchema extends XSLTElementDef
charTemplateElements[i++] = xslCallTemplate;
charTemplateElements[i++] = xslApplyImports;
charTemplateElements[i++] = xslForEach;
+ charTemplateElements[i++] = xslForEachGroup;
charTemplateElements[i++] = xslValueOf;
charTemplateElements[i++] = xslCopyOf;
charTemplateElements[i++] = xslNumber;
diff --git a/src/org/apache/xalan/templates/Constants.java b/src/org/apache/xalan/templates/Constants.java
index 9bc6442a..8545fe85 100644
--- a/src/org/apache/xalan/templates/Constants.java
+++ b/src/org/apache/xalan/templates/Constants.java
@@ -32,10 +32,7 @@ public class Constants extends org.apache.xml.utils.Constants
* IDs for XSL element types. These are associated
* with the string literals in the TransformerImpl class.
* Don't change the numbers. NOTE THAT THESE ARE NOT IN
- * ALPHABETICAL ORDER!
- * (It's a pity Java doesn't have a real Enumerated Mnemonic
- * datatype... or a C-like preprocessor in lieu thereof which
- * could be used to generate and maintain synch between these lists.)
+ * ALPHABETICAL ORDER.
*/
public static final int ELEMNAME_UNDEFINED = -1, ELEMNAME_WITHPARAM = 2,
ELEMNAME_ADDATTRIBUTE = 4, ELEMNAME_ANCHOR = 22,
@@ -89,12 +86,14 @@ public class Constants extends org.apache.xml.utils.Constants
ELEMNAME_LITERALRESULT = 77, ELEMNAME_TEXTLITERALRESULT = 78,
ELEMNAME_EXTENSIONCALL = 79, ELEMNAME_EXTENSIONDECL = 85,
ELEMNAME_EXTENSIONSCRIPT = 86, ELEMNAME_OUTPUT = 80,
- ELEMNAME_COMPONENT = 81, ELEMNAME_SCRIPT = 82;
+ ELEMNAME_COMPONENT = 81, ELEMNAME_SCRIPT = 82,
+
+ ELEMNAME_FOREACHGROUP = 90;
- // Next free number: 90 (88 and 89 used for EXSLT elements);
+ // Next free number: 91
/**
- * Literals for XSL element names. Note that there are more
+ * Literals for XSL element names. Note that there are more
* names than IDs, because some names map to the same ID.
*/
public static final String
@@ -132,6 +131,7 @@ public class Constants extends org.apache.xml.utils.Constants
ELEMNAME_EXTENSION_STRING = "functions",
ELEMNAME_FALLBACK_STRING = "fallback",
ELEMNAME_FOREACH_STRING = "for-each",
+ ELEMNAME_FOREACHGROUP_STRING = "for-each-group",
ELEMNAME_IF_STRING = "if",
ELEMNAME_IMPORT_STRING = "import",
ELEMNAME_INCLUDE_STRING = "include",
diff --git a/src/org/apache/xalan/templates/ElemForEachGroup.java b/src/org/apache/xalan/templates/ElemForEachGroup.java
new file mode 100644
index 00000000..4f578b0e
--- /dev/null
+++ b/src/org/apache/xalan/templates/ElemForEachGroup.java
@@ -0,0 +1,462 @@
+/*
+ * 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.
+ */
+/*
+ * $Id$
+ */
+package org.apache.xalan.templates;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.xml.transform.TransformerException;
+
+import org.apache.xalan.transformer.NodeSorter;
+import org.apache.xalan.transformer.TransformerImpl;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMIterator;
+import org.apache.xml.utils.IntStack;
+import org.apache.xpath.Expression;
+import org.apache.xpath.ExpressionOwner;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.XObject;
+
+/**
+ * Implementation of the xsl:for-each-group XSLT 3.0 instruction.
+ *
+ * <xsl:for-each-group
+ select = expression
+ group-by? = expression
+ group-adjacent? = expression
+ group-starting-with? = pattern
+ group-ending-with? = pattern
+ composite? = boolean
+ collation? = { uri } >
+ <!-- Content: (xsl:sort*, sequence-constructor) -->
+ </xsl:for-each-group>
+
+ <xsl:sort
+ select? = expression
+ lang? = { language }
+ order? = { "ascending" | "descending" }
+ collation? = { uri }
+ stable? = { boolean }
+ case-order? = { "upper-first" | "lower-first" }
+ data-type? = { "text" | "number" | eqname } >
+ <!-- Content: sequence-constructor -->
+ </xsl:sort>
+
+ XSLT 3.0 grouping functions,
+ 1) fn:current-group()
+ 2) fn:current-grouping-key()
+ *
+ * (xsl:for-each-group instruction was first introduced in XSLT 2.0 language)
+ *
+ * @author Mukul Gandhi
+ *
+ * @xsl.usage advanced
+ */
+
+/*
+ This implementation is WIP
+
+1) To make this more compliant to XSLT 3.0 spec
+2) We're still using XalanJ's implementation of XPath 1.0 data model
+ for xsl:for-each-group's implementation.
+*/
+public class ElemForEachGroup extends ElemTemplateElement implements ExpressionOwner
+{
+
+ private static final long serialVersionUID = -6682554013978812260L;
+
+ /**
+ * Construct a element representing xsl:for-each-group.
+ */
+ public ElemForEachGroup(){}
+
+ /**
+ * The "select" expression.
+ * @serial
+ */
+ protected Expression m_selectExpression = null;
+
+ /**
+ * The "group-by" expression.
+ */
+ protected Expression m_GroupByExpression = null;
+
+ /**
+ * Set the "select" attribute.
+ *
+ * @param xpath The XPath expression for the "select" attribute.
+ */
+ public void setSelect(XPath xpath)
+ {
+ m_selectExpression = xpath.getExpression();
+ }
+
+ /**
+ * Get the "select" attribute.
+ *
+ * @return The XPath expression for the "select" attribute.
+ */
+ public Expression getSelect()
+ {
+ return m_selectExpression;
+ }
+
+ public void setGroupBy(XPath xpath)
+ {
+ m_GroupByExpression = xpath.getExpression();
+ }
+
+ public Expression getGroupBy()
+ {
+ return m_GroupByExpression;
+ }
+
+ /**
+ * This function is called after everything else has been
+ * recomposed, and allows the template to set remaining
+ * values that may be based on some other property that
+ * depends on recomposition.
+ *
+ * NEEDSDOC @param sroot
+ *
+ * @throws TransformerException
+ */
+ public void compose(StylesheetRoot sroot) throws TransformerException
+ {
+ super.compose(sroot);
+
+ int length = getSortElemCount();
+
+ for (int i = 0; i < length; i++)
+ {
+ getSortElem(i).compose(sroot);
+ }
+
+ java.util.Vector vnames = sroot.getComposeState().getVariableNames();
+
+ if (m_selectExpression != null) {
+ m_selectExpression.fixupVariables(vnames, sroot.getComposeState().getGlobalsSize());
+ } else {
+ m_selectExpression = getStylesheetRoot().m_selectDefault.getExpression();
+ }
+ }
+
+ /**
+ * This after the template's children have been composed.
+ */
+ public void endCompose(StylesheetRoot sroot) throws TransformerException
+ {
+ int length = getSortElemCount();
+
+ for (int i = 0; i < length; i++)
+ {
+ getSortElem(i).endCompose(sroot);
+ }
+
+ super.endCompose(sroot);
+ }
+
+ /**
+ * Vector containing the xsl:sort elements associated with this element.
+ * @serial
+ */
+ protected Vector m_sortElems = null;
+
+ /**
+ * Get the count xsl:sort elements associated with this element.
+ * @return The number of xsl:sort elements.
+ */
+ public int getSortElemCount()
+ {
+ return (m_sortElems == null) ? 0 : m_sortElems.size();
+ }
+
+ /**
+ * Get a xsl:sort element associated with this element.
+ *
+ * @param i Index of xsl:sort element to get
+ *
+ * @return xsl:sort element at given index
+ */
+ public ElemSort getSortElem(int i)
+ {
+ return (ElemSort) m_sortElems.elementAt(i);
+ }
+
+ /**
+ * Set a xsl:sort element associated with this element.
+ *
+ * @param sortElem xsl:sort element to set
+ */
+ public void setSortElem(ElemSort sortElem)
+ {
+ if (null == m_sortElems)
+ m_sortElems = new Vector();
+
+ m_sortElems.addElement(sortElem);
+ }
+
+ /**
+ * Get an int constant identifying the type of element.
+ * @see org.apache.xalan.templates.Constants
+ *
+ * @return The token ID for this element
+ */
+ public int getXSLToken()
+ {
+ return Constants.ELEMNAME_FOREACHGROUP;
+ }
+
+ /**
+ * Return the node name.
+ *
+ * @return The element's name
+ */
+ public String getNodeName()
+ {
+ return Constants.ELEMNAME_FOREACHGROUP_STRING;
+ }
+
+ /**
+ * Execute the xsl:for-each-group transformation
+ *
+ * @param transformer non-null reference to the the current transform-time state.
+ *
+ * @throws TransformerException
+ */
+ public void execute(TransformerImpl transformer) throws TransformerException
+ {
+ transformer.pushCurrentTemplateRuleIsNull(true);
+ if (transformer.getDebug())
+ transformer.getTraceManager().fireTraceEvent(this);
+
+ try
+ {
+ transformSelectedNodes(transformer);
+ }
+ finally
+ {
+ if (transformer.getDebug())
+ transformer.getTraceManager().fireTraceEndEvent(this);
+ transformer.popCurrentTemplateRuleIsNull();
+ }
+ }
+
+ /**
+ * Get template element associated with this
+ *
+ *
+ * @return template element associated with this (itself)
+ */
+ protected ElemTemplateElement getTemplateMatch()
+ {
+ return this;
+ }
+
+ /**
+ * Sort given nodes
+ *
+ *
+ * @param xctxt The XPath runtime state for the sort.
+ * @param keys Vector of sort keys
+ * @param sourceNodes Iterator of nodes to sort
+ *
+ * @return iterator of sorted nodes
+ *
+ * @throws TransformerException
+ */
+ public DTMIterator sortNodes(XPathContext xctxt, Vector keys, DTMIterator sourceNodes)
+ throws TransformerException {
+ NodeSorter sorter = new NodeSorter(xctxt);
+ sourceNodes.setShouldCacheNodes(true);
+ sourceNodes.runTo(-1);
+ xctxt.pushContextNodeList(sourceNodes);
+
+ try
+ {
+ sorter.sort(sourceNodes, keys, xctxt);
+ sourceNodes.setCurrentPos(0);
+ }
+ finally
+ {
+ xctxt.popContextNodeList();
+ }
+
+ return sourceNodes;
+ }
+
+ /**
+ * Perform a query if needed, and call transformNode for each child.
+ *
+ * @param transformer non-null reference to the the current transform-time state.
+ *
+ * @throws TransformerException Thrown in a variety of circumstances.
+ * @throws CloneNotSupportedException
+ * @xsl.usage advanced
+ */
+ public void transformSelectedNodes(TransformerImpl transformer)
+ throws TransformerException {
+ final XPathContext xctxt = transformer.getXPathContext();
+ final int sourceNode = xctxt.getCurrentNode();
+ DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);
+
+ // form groups from the 'sourceNodes' iterator
+
+ // assuming string grouping keys for now.
+ // hashmap's key is the grouping key, and value is a list of dtm integer node handles
+ Map<String, List<Integer>> groups = new HashMap<String, List<Integer>>();
+
+ int nextNode;
+
+ while (DTM.NULL != (nextNode = sourceNodes.nextNode())) {
+ xctxt.pushCurrentNode(nextNode);
+
+ XObject xpathEvalResult = m_GroupByExpression.execute(xctxt);
+
+ String grpByEvalResultStrValue = xpathEvalResult.toString();
+ if (groups.get(grpByEvalResultStrValue) != null) {
+ List<Integer> group = groups.get(grpByEvalResultStrValue);
+ group.add(nextNode);
+ } else {
+ List<Integer> group = new ArrayList<Integer>();
+ group.add(nextNode);
+ groups.put(grpByEvalResultStrValue, group);
+ }
+ }
+
+ // end, form groups from the 'sourceNodes' iterator
+
+ try {
+ xctxt.pushCurrentNode(DTM.NULL);
+
+ IntStack currentNodes = xctxt.getCurrentNodeStack();
+
+ xctxt.pushCurrentExpressionNode(DTM.NULL);
+
+ IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();
+
+ xctxt.pushSAXLocatorNull();
+ xctxt.pushContextNodeList(sourceNodes);
+ transformer.pushElemTemplateElement(null);
+
+ Set<String> groupingKeys = groups.keySet();
+
+ // iterate through all the, groups formed by xsl:for-each-group instruction
+ for (Iterator<String> iter = groupingKeys.iterator(); iter.hasNext(); ) {
+ String groupingKey = iter.next(); // this is raw current-grouping-key() value
+ List<Integer> groupNodesDtmHandles = groups.get(groupingKey); // this is raw dtm current-group() contents
+
+ for (ElemTemplateElement templateElem = this.m_firstChild; templateElem != null;
+ templateElem = templateElem.m_nextSibling) {
+ xctxt.setSAXLocator(templateElem);
+ transformer.setCurrentElement(templateElem);
+ templateElem.setForEachGroupControlInformation(groupingKey,
+ groupNodesDtmHandles);
+ templateElem.execute(transformer);
+ }
+ }
+ }
+ finally
+ {
+ if (transformer.getDebug())
+ transformer.getTraceManager().fireSelectedEndEvent(sourceNode, this,
+ "select", new XPath(m_selectExpression),
+ new org.apache.xpath.objects.XNodeSet(sourceNodes));
+
+ xctxt.popSAXLocator();
+ xctxt.popContextNodeList();
+ transformer.popElemTemplateElement();
+ xctxt.popCurrentExpressionNode();
+ xctxt.popCurrentNode();
+ sourceNodes.detach();
+ }
+ }
+
+ /**
+ * Add a child to the child list.
+ * <!ELEMENT xsl:apply-templates (xsl:sort|xsl:with-param)*>
+ * <!ATTLIST xsl:apply-templates
+ * select %expr; "node()"
+ * mode %qname; #IMPLIED
+ * >
+ *
+ * @param newChild Child to add to child list
+ *
+ * @return Child just added to child list
+ */
+ public ElemTemplateElement appendChild(ElemTemplateElement newChild)
+ {
+ int type = ((ElemTemplateElement) newChild).getXSLToken();
+
+ if (type == Constants.ELEMNAME_SORT)
+ {
+ setSortElem((ElemSort) newChild);
+
+ return newChild;
+ }
+ else {
+ return super.appendChild(newChild);
+ }
+ }
+
+ /**
+ * Call the children visitors.
+ * @param visitor The visitor whose appropriate method will be called.
+ */
+ public void callChildVisitors(XSLTVisitor visitor, boolean callAttributes)
+ {
+ if(callAttributes && (null != m_selectExpression))
+ m_selectExpression.callVisitors(this, visitor);
+
+ int length = getSortElemCount();
+
+ for (int i = 0; i < length; i++)
+ {
+ getSortElem(i).callVisitors(visitor);
+ }
+
+ super.callChildVisitors(visitor, callAttributes);
+ }
+
+ /**
+ * @see ExpressionOwner#getExpression()
+ */
+ public Expression getExpression()
+ {
+ return m_selectExpression;
+ }
+
+ /**
+ * @see ExpressionOwner#setExpression(Expression)
+ */
+ public void setExpression(Expression exp)
+ {
+ exp.exprSetParent(this);
+ m_selectExpression = exp;
+ }
+
+}
diff --git a/src/org/apache/xalan/templates/ElemTemplateElement.java b/src/org/apache/xalan/templates/ElemTemplateElement.java
index 807c0b72..0846f512 100644
--- a/src/org/apache/xalan/templates/ElemTemplateElement.java
+++ b/src/org/apache/xalan/templates/ElemTemplateElement.java
@@ -62,6 +62,12 @@ public class ElemTemplateElement extends UnImplNode
WhitespaceStrippingElementMatcher, XSLTVisitable
{
static final long serialVersionUID = 4440018597841834447L;
+
+ // xsl:for-each-group grouping key string value
+ private String fGroupingKey;
+
+ // xsl:for-each-group "current group" contents
+ private List<Integer> fGroupNodesDtmHandles;
/**
* Construct a template element instance.
@@ -135,6 +141,16 @@ public class ElemTemplateElement extends UnImplNode
public void execute(
TransformerImpl transformer)
throws TransformerException{}
+
+ /*
+ * Method to support, xsl:for-each-group instruction.
+ */
+ public void setForEachGroupControlInformation(String groupingKey,
+ List<Integer> groupNodesDtmHandles)
+ throws TransformerException {
+ this.fGroupingKey = groupingKey;
+ this.fGroupNodesDtmHandles = groupNodesDtmHandles;
+ }
/**
* Get the owning "composed" stylesheet. This looks up the
diff --git a/src/org/apache/xalan/transformer/TransformerImpl.java b/src/org/apache/xalan/transformer/TransformerImpl.java
index bd9baaf7..105543d8 100644
--- a/src/org/apache/xalan/transformer/TransformerImpl.java
+++ b/src/org/apache/xalan/transformer/TransformerImpl.java
@@ -56,6 +56,7 @@ import org.apache.xalan.templates.AVT;
import org.apache.xalan.templates.Constants;
import org.apache.xalan.templates.ElemAttributeSet;
import org.apache.xalan.templates.ElemForEach;
+import org.apache.xalan.templates.ElemForEachGroup;
import org.apache.xalan.templates.ElemSort;
import org.apache.xalan.templates.ElemTemplate;
import org.apache.xalan.templates.ElemTemplateElement;
@@ -2564,6 +2565,91 @@ public class TransformerImpl extends Transformer
return keys;
}
+
+ public Vector processSortKeysForEachGroup(ElemForEachGroup foreachgroup, int sourceNodeContext)
+ throws TransformerException
+ {
+
+ Vector keys = null;
+ XPathContext xctxt = m_xcontext;
+ int nElems = foreachgroup.getSortElemCount();
+
+ if (nElems > 0)
+ keys = new Vector();
+
+ // March backwards, collecting the sort keys.
+ for (int i = 0; i < nElems; i++)
+ {
+ ElemSort sort = foreachgroup.getSortElem(i);
+
+ if (m_debug)
+ getTraceManager().fireTraceEvent(sort);
+
+ String langString =
+ (null != sort.getLang())
+ ? sort.getLang().evaluate(xctxt, sourceNodeContext, foreachgroup) : null;
+ String dataTypeString = sort.getDataType().evaluate(xctxt,
+ sourceNodeContext, foreachgroup);
+
+ if (dataTypeString.indexOf(":") >= 0)
+ System.out.println(
+ "TODO: Need to write the hooks for QNAME sort data type");
+ else if (!(dataTypeString.equalsIgnoreCase(Constants.ATTRVAL_DATATYPE_TEXT))
+ &&!(dataTypeString.equalsIgnoreCase(
+ Constants.ATTRVAL_DATATYPE_NUMBER)))
+ foreachgroup.error(XSLTErrorResources.ER_ILLEGAL_ATTRIBUTE_VALUE,
+ new Object[]{ Constants.ATTRNAME_DATATYPE,
+ dataTypeString });
+
+ boolean treatAsNumbers =
+ ((null != dataTypeString) && dataTypeString.equals(
+ Constants.ATTRVAL_DATATYPE_NUMBER)) ? true : false;
+ String orderString = sort.getOrder().evaluate(xctxt, sourceNodeContext,
+ foreachgroup);
+
+ if (!(orderString.equalsIgnoreCase(Constants.ATTRVAL_ORDER_ASCENDING))
+ &&!(orderString.equalsIgnoreCase(
+ Constants.ATTRVAL_ORDER_DESCENDING)))
+ foreachgroup.error(XSLTErrorResources.ER_ILLEGAL_ATTRIBUTE_VALUE,
+ new Object[]{ Constants.ATTRNAME_ORDER,
+ orderString });
+
+ boolean descending =
+ ((null != orderString) && orderString.equals(
+ Constants.ATTRVAL_ORDER_DESCENDING)) ? true : false;
+ AVT caseOrder = sort.getCaseOrder();
+ boolean caseOrderUpper;
+
+ if (null != caseOrder)
+ {
+ String caseOrderString = caseOrder.evaluate(xctxt, sourceNodeContext,
+ foreachgroup);
+
+ if (!(caseOrderString.equalsIgnoreCase(Constants.ATTRVAL_CASEORDER_UPPER))
+ &&!(caseOrderString.equalsIgnoreCase(
+ Constants.ATTRVAL_CASEORDER_LOWER)))
+ foreachgroup.error(XSLTErrorResources.ER_ILLEGAL_ATTRIBUTE_VALUE,
+ new Object[]{ Constants.ATTRNAME_CASEORDER,
+ caseOrderString });
+
+ caseOrderUpper =
+ ((null != caseOrderString) && caseOrderString.equals(
+ Constants.ATTRVAL_CASEORDER_UPPER)) ? true : false;
+ }
+ else
+ {
+ caseOrderUpper = false;
+ }
+
+ keys.addElement(new NodeSortKey(this, sort.getSelect(), treatAsNumbers,
+ descending, langString, caseOrderUpper,
+ foreachgroup));
+ if (m_debug)
+ getTraceManager().fireTraceEndEvent(sort);
+ }
+
+ return keys;
+ }
//==========================================================
// SECTION: TransformState implementation
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org