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

net.sf.saxon.sxpath.XPathExpression Maven / Gradle / Ivy

There is a newer version: 12.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2018-2023 Saxonica Limited
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.sxpath;

import net.sf.saxon.Controller;
import net.sf.saxon.expr.Expression;
import net.sf.saxon.expr.StaticContext;
import net.sf.saxon.expr.XPathContextMajor;
import net.sf.saxon.expr.instruct.Executable;
import net.sf.saxon.expr.instruct.SlotManager;
import net.sf.saxon.om.Item;
import net.sf.saxon.om.ItemConsumer;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.om.SequenceTool;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.TypeHierarchy;

import java.util.ArrayList;
import java.util.List;

/**
 * This class is a representation of an XPath Expression for use with the {@link XPathEvaluator} class.
 * It is modelled on the XPath API defined in JAXP 1.3, but is free-standing, and is more strongly typed.
 * 

In Saxon 9.6, the methods that returned Object and did implicit conversion to a native Java object * have been removed; all conversions must now be done explicitly.

* */ public class XPathExpression { private final StaticContext env; private final Expression expression; private SlotManager stackFrameMap; private final Executable executable; private int numberOfExternalVariables; /** * The constructor is protected, to ensure that instances can only be * created using the createExpression() or createPattern() method of XPathEvaluator * * @param env the static context of the expression * @param exp the internal representation of the compiled expression * @param exec the Executable associated with this expression */ protected XPathExpression(StaticContext env, Expression exp, Executable exec) { expression = exp; this.env = env; this.executable = exec; } /** * Get the Executable associated with this expression * @return the associated Executable */ public Executable getExecutable() { return executable; } /** * Define the number of slots needed for local variables within the expression * * @param map the stack frame map identifying all the variables used by the expression, both * those declared internally, and references to variables declared externally * @param numberOfExternalVariables the number of slots in the stack frame allocated to * externally-declared variables. These must be assigned a value before execution starts */ protected void setStackFrameMap(SlotManager map, int numberOfExternalVariables) { stackFrameMap = map; this.numberOfExternalVariables = numberOfExternalVariables; } /** * Create a dynamic context suitable for evaluating this expression, without supplying a context * item * * @return an XPathDynamicContext object representing a suitable dynamic context. This will * be initialized with a stack frame suitable for holding the variables used by the * expression. */ public XPathDynamicContext createDynamicContext() { XPathContextMajor context = new XPathContextMajor(null, executable); context.openStackFrame(stackFrameMap); return new XPathDynamicContext(env.getRequiredContextItemType(), context, stackFrameMap); } /** * Create a dynamic context suitable for evaluating this expression * * @param contextItem the initial context item, which may be null if no * context item is required, or if it is to be supplied later * @return an XPathDynamicContext object representing a suitable dynamic context. This will * be initialized with a stack frame suitable for holding the variables used by the * expression. * @throws XPathException if the context item does not match the required context item type * set up in the static context */ public XPathDynamicContext createDynamicContext(Item contextItem) throws XPathException { checkContextItemType(contextItem); XPathContextMajor context = new XPathContextMajor(contextItem, executable); context.openStackFrame(stackFrameMap); return new XPathDynamicContext(env.getRequiredContextItemType(), context, stackFrameMap); } /** * Create a dynamic context suitable for evaluating this expression within an environment * represented by an existing controller. The dynamic context will inherit properties of the * Controller such as the current error listener, URI resolver, document pool, and implicit * timezone. * * @param controller an existing controller. May be null, in which case the method is * equivalent to calling {@link #createDynamicContext(net.sf.saxon.om.Item)} * @param contextItem the initial context item, which may be null if no * context item is required, or if it is to be supplied later * @return an XPathDynamicContext object representing a suitable dynamic context. This will * be initialized with a stack frame suitable for holding the variables used by the * expression. * @throws XPathException if the context item does not match the required context item type * set up in the static context * @since 9.2 */ public XPathDynamicContext createDynamicContext(Controller controller, Item contextItem) throws XPathException { checkContextItemType(contextItem); if (controller == null) { return createDynamicContext(contextItem); } else { XPathContextMajor context = controller.newXPathContext(); context.openStackFrame(stackFrameMap); XPathDynamicContext dc = new XPathDynamicContext(env.getRequiredContextItemType(), context, stackFrameMap); if (contextItem != null) { dc.setContextItem(contextItem); } return dc; } } private void checkContextItemType(Item contextItem) throws XPathException { if (contextItem != null) { ItemType type = env.getRequiredContextItemType(); TypeHierarchy th = env.getConfiguration().getTypeHierarchy(); if (!type.matches(contextItem, th)) { throw new XPathException("Supplied context item does not match required context item type " + type); } } } /** * Execute the expression, returning the result as a {@link SequenceIterator}, whose members will be instances * of the class {@link net.sf.saxon.om.Item} *

Note that if evaluation of the expression fails with a dynamic error, this will generally * be reported in the form of an exception thrown by the next() method of the {@link SequenceIterator}

* * @param context the XPath dynamic context * @return an iterator over the result of the expression * @throws XPathException if a dynamic error occurs during the expression evaluation (though in many * cases, the error will only be detected when the iterator is actually used). */ public SequenceIterator iterate(XPathDynamicContext context) throws XPathException { context.checkExternalVariables(stackFrameMap, numberOfExternalVariables); return expression.makeElaborator().elaborateForPull().iterate(context.getXPathContextObject()); } /** * Execute the expression, returning the result as a List, whose members will be instances * of the class {@link net.sf.saxon.om.Item} * * @param context the XPath dynamic context * @return a list of items representing the result of the expression * @throws XPathException if a dynamic error occurs while evaluation the expression */ public List evaluate(XPathDynamicContext context) throws XPathException { List list = new ArrayList<>(20); // Don't replace with list::add - C# doesn't like it because list.add() returns boolean //noinspection Convert2MethodRef SequenceTool.supply(expression.iterate(context.getXPathContextObject()), (ItemConsumer) item -> list.add(item)); return list; } /** * Execute the expression, returning the result as a single {@link net.sf.saxon.om.Item} * If the result of the expression is a sequence containing more than one item, items after * the first are discarded. If the result is an empty sequence, the method returns null. * * @param context the XPath dynamic context * @return the first item in the result of the expression, or null to indicate that the result * is an empty sequence * @throws XPathException if a dynamic error occurs during the expression evaluation */ /*@Nullable*/ public Item evaluateSingle(XPathDynamicContext context) throws XPathException { SequenceIterator iter = expression.iterate(context.getXPathContextObject()); Item result = iter.next(); iter.close(); return result; } /** * Evaluate the expression, returning its effective boolean value * * @param context the XPath dynamic context * @return the effective boolean value of the result, as defined by the fn:boolean() function * @throws XPathException if a dynamic error occurs, or if the result is a value for which * no effective boolean value is defined */ public boolean effectiveBooleanValue(XPathDynamicContext context) throws XPathException { return expression.makeElaborator().elaborateForBoolean().eval(context.getXPathContextObject()); } /** * Low-level method to get the internal Saxon expression object. This exposes a wide range of * internal methods that may be needed by specialized applications, and allows greater control * over the dynamic context for evaluating the expression. * * @return the underlying Saxon expression object. */ public Expression getInternalExpression() { return expression; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy