001: package net.sf.saxon.style;
002:
003: import net.sf.saxon.expr.Expression;
004: import net.sf.saxon.expr.ExpressionTool;
005: import net.sf.saxon.instruct.Executable;
006: import net.sf.saxon.instruct.ForEach;
007: import net.sf.saxon.om.AttributeCollection;
008: import net.sf.saxon.om.Axis;
009: import net.sf.saxon.sort.SortExpression;
010: import net.sf.saxon.sort.SortKeyDefinition;
011: import net.sf.saxon.trans.XPathException;
012: import net.sf.saxon.type.ItemType;
013: import net.sf.saxon.value.EmptySequence;
014:
015: /**
016: * Handler for xsl:for-each elements in stylesheet. <br>
017: */
018:
019: public class XSLForEach extends StyleElement {
020:
021: Expression select = null;
022:
023: /**
024: * Determine whether this node is an instruction.
025: * @return true - it is an instruction
026: */
027:
028: public boolean isInstruction() {
029: return true;
030: }
031:
032: /**
033: * Specify that xsl:sort is a permitted child
034: */
035:
036: protected boolean isPermittedChild(StyleElement child) {
037: return (child instanceof XSLSort);
038: }
039:
040: /**
041: * Determine the type of item returned by this instruction (only relevant if
042: * it is an instruction).
043: * @return the item type returned
044: */
045:
046: protected ItemType getReturnedItemType() {
047: return getCommonChildItemType();
048: }
049:
050: /**
051: * Determine whether this type of element is allowed to contain a template-body
052: * @return true: yes, it may contain a template-body
053: */
054:
055: public boolean mayContainSequenceConstructor() {
056: return true;
057: }
058:
059: public void prepareAttributes() throws XPathException {
060:
061: AttributeCollection atts = getAttributeList();
062:
063: String selectAtt = null;
064:
065: for (int a = 0; a < atts.getLength(); a++) {
066: int nc = atts.getNameCode(a);
067: String f = getNamePool().getClarkName(nc);
068: if (f == StandardNames.SELECT) {
069: selectAtt = atts.getValue(a);
070: } else {
071: checkUnknownAttribute(nc);
072: }
073: }
074:
075: if (selectAtt == null) {
076: reportAbsence("select");
077: } else {
078: select = makeExpression(selectAtt);
079: }
080:
081: }
082:
083: public void validate() throws XPathException {
084: checkWithinTemplate();
085: checkSortComesFirst(false);
086: select = typeCheck("select", select);
087: }
088:
089: public Expression compile(Executable exec) throws XPathException {
090: SortKeyDefinition[] sortKeys = makeSortKeys();
091: Expression sortedSequence = select;
092: if (sortKeys != null) {
093: sortedSequence = new SortExpression(select, sortKeys);
094: ExpressionTool.makeParentReferences(sortedSequence);
095: }
096:
097: Expression block = compileSequenceConstructor(exec,
098: iterateAxis(Axis.CHILD), true);
099: if (block == null) {
100: // body of for-each is empty: it's a no-op.
101: return EmptySequence.getInstance();
102: }
103: try {
104: ForEach inst = new ForEach(sortedSequence, block
105: .simplify(getStaticContext()));
106: ExpressionTool.makeParentReferences(inst);
107: return inst;
108: } catch (XPathException err) {
109: compileError(err);
110: return null;
111: }
112: }
113:
114: }
115:
116: //
117: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
118: // you may not use this file except in compliance with the License. You may obtain a copy of the
119: // License at http://www.mozilla.org/MPL/
120: //
121: // Software distributed under the License is distributed on an "AS IS" basis,
122: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
123: // See the License for the specific language governing rights and limitations under the License.
124: //
125: // The Original Code is: all this file.
126: //
127: // The Initial Developer of the Original Code is Michael H. Kay.
128: //
129: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
130: //
131: // Contributor(s): none.
132: //
|