All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.instruct.Choose Maven / Gradle / Ivy

Go to download

Provides a basic XSLT 2.0 and XQuery 1.0 processor (W3C Recommendations, January 2007). Command line interfaces and implementations of several Java APIs (DOM, XPath, s9api) are also included.

The newest version!
package net.sf.saxon.instruct;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.expr.*;
import net.sf.saxon.om.*;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.*;
import net.sf.saxon.value.Cardinality;
import net.sf.saxon.value.EmptySequence;
import net.sf.saxon.value.SequenceType;
import net.sf.saxon.value.BooleanValue;
import net.sf.saxon.functions.BooleanFn;
import net.sf.saxon.functions.SystemFunction;
import net.sf.saxon.evpull.EventIterator;
import net.sf.saxon.evpull.EmptyEventIterator;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * Compiled representation of an xsl:choose or xsl:if element in the stylesheet.
 * Also used for typeswitch in XQuery.
*/

public class Choose extends Instruction {

    // The class implements both xsl:choose and xsl:if. There is a list of boolean
    // expressions (conditions) and a list of corresponding actions: the conditions
    // are evaluated in turn, and when one is found that is true, the corresponding
    // action is evaluated. For xsl:if, there is always one condition and one action.
    // An xsl:otherwise is compiled as if it were xsl:when test="true()". If no
    // condition is satisfied, the instruction returns an empty sequence.

    private Expression[] conditions;
    private Expression[] actions;


    /**
    * Construct an xsl:choose instruction
    * @param conditions the conditions to be tested, in order
    * @param actions the actions to be taken when the corresponding condition is true
    */

    public Choose(Expression[] conditions, Expression[] actions) {
        this.conditions = conditions;
        this.actions = actions;
        if (conditions.length != actions.length) {
            throw new IllegalArgumentException("Choose: unequal length arguments");
        }
        for (int i=0; i or "when (test) then ()"

        if (/*Literal.isConstantBoolean(conditions[conditions.length-1], true) && */
                Literal.isEmptySequence(actions[actions.length-1])) {
            if (conditions.length == 1) {
                return new Literal(EmptySequence.getInstance());
            } else {
                Expression[] c = new Expression[conditions.length-1];
                System.arraycopy(conditions, 0, c, 0, conditions.length-1);
                Expression[] a = new Expression[actions.length-1];
                System.arraycopy(actions, 0, a, 0, actions.length-1);
            }
        }

        // Flatten an "else if"

        if (Literal.isConstantBoolean(conditions[conditions.length-1], true) &&
                actions[actions.length-1] instanceof Choose) {
            Choose choose2 = (Choose)actions[actions.length-1];
            int newLen = conditions.length + choose2.conditions.length - 1;
            Expression[] c2 = new Expression[newLen];
            Expression[] a2 = new Expression[newLen];
            System.arraycopy(conditions, 0, c2, 0, conditions.length - 1);
            System.arraycopy(actions, 0, a2, 0, actions.length - 1);
            System.arraycopy(choose2.conditions, 0, c2, conditions.length - 1, choose2.conditions.length);
            System.arraycopy(choose2.actions, 0, a2, actions.length - 1, choose2.actions.length);
            conditions = c2;
            actions = a2;
        }
        
        // Rewrite "if (EXP) then true() else false()" as boolean(EXP)

        if (conditions.length == 2 &&
                Literal.isConstantBoolean(actions[0], true) &&
                Literal.isConstantBoolean(actions[1], false) &&
                Literal.isConstantBoolean(conditions[1], true)) {
            TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy();
            if (th.isSubType(conditions[0].getItemType(th), BuiltInAtomicType.BOOLEAN) &&
                        conditions[0].getCardinality() == StaticProperty.EXACTLY_ONE) {
                return conditions[0];
            } else {
                return SystemFunction.makeSystemFunction("boolean", new Expression[]{conditions[0]});
            }
        }
        return this;
    }

    public Expression typeCheck(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException {
        for (int i=0; i
     * 

The default implementation of this method assumes that an expression does no navigation other than * the navigation done by evaluating its subexpressions, and that the subexpressions are evaluated in the * same context as the containing expression. The method must be overridden for any expression * where these assumptions do not hold. For example, implementations exist for AxisExpression, ParentExpression, * and RootExpression (because they perform navigation), and for the doc(), document(), and collection() * functions because they create a new navigation root. Implementations also exist for PathExpression and * FilterExpression because they have subexpressions that are evaluated in a different context from the * calling expression.

* * @param pathMap the PathMap to which the expression should be added * @param pathMapNodeSet the set of PathMap nodes to which the paths from this expression should be appended * @return the pathMapNode representing the focus established by this expression, in the case where this * expression is the first operand of a path expression or filter expression. For an expression that does * navigation, it represents the end of the arc in the path map that describes the navigation route. For other * expressions, it is the same as the input pathMapNode. */ public PathMap.PathMapNodeSet addToPathMap(PathMap pathMap, PathMap.PathMapNodeSet pathMapNodeSet) { // expressions used in a condition contribute paths, but these do not contribute to the result for (int i=0; i *

The events (of class {@link net.sf.saxon.evpull.PullEvent}) are either complete * items, or one of startElement, endElement, startDocument, or endDocument, known * as semi-nodes. The stream of events may also include a nested EventIterator. * If a start-end pair exists in the sequence, then the events between * this pair represent the content of the document or element. The content sequence will * have been processed to the extent that any attribute and namespace nodes in the * content sequence will have been merged into the startElement event. Namespace fixup * will have been performed: that is, unique prefixes will have been allocated to element * and attribute nodes, and all namespaces will be declared by means of a namespace node * in the startElement event or in an outer startElement forming part of the sequence. * However, duplicate namespaces may appear in the sequence.

*

The content of an element or document may include adjacent or zero-length text nodes, * atomic values, and nodes represented as nodes rather than broken down into events.

* * @param context The dynamic evaluation context * @return the result of the expression as an iterator over a sequence of PullEvent objects * @throws net.sf.saxon.trans.XPathException * if a dynamic error occurs during expression evaluation */ public EventIterator iterateEvents(XPathContext context) throws XPathException { for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy