001: package net.sf.saxon.sxpath;
002:
003: import net.sf.saxon.expr.Expression;
004: import net.sf.saxon.expr.XPathContextMajor;
005: import net.sf.saxon.instruct.SlotManager;
006: import net.sf.saxon.trans.XPathException;
007: import net.sf.saxon.value.SequenceExtent;
008: import net.sf.saxon.value.Value;
009: import net.sf.saxon.om.NodeInfo;
010: import net.sf.saxon.om.SequenceIterator;
011: import net.sf.saxon.om.Item;
012:
013: import javax.xml.transform.Source;
014: import java.util.Collections;
015: import java.util.List;
016:
017: /**
018: * This class is a representation of an XPath Expression for use with the XPathEvaluator class.
019: * It is modelled on the XPath API defined in JAXP 1.3, but is cut down to remove any dependencies on JAXP 1.3,
020: * making it suitable for use on vanilla JDK 1.4 installations.
021: *
022: * @author Michael H. Kay
023: */
024:
025: public class XPathExpression {
026:
027: private XPathEvaluator evaluator;
028: private Expression expression;
029: private SlotManager stackFrameMap;
030:
031: /**
032: * The constructor is protected, to ensure that instances can only be
033: * created using the createExpression() method of XPathEvaluator
034: */
035:
036: protected XPathExpression(XPathEvaluator evaluator, Expression exp) {
037: expression = exp;
038: this .evaluator = evaluator;
039: }
040:
041: /**
042: * Define the number of slots needed for local variables within the expression
043: */
044:
045: protected void setStackFrameMap(SlotManager map) {
046: stackFrameMap = map;
047: }
048:
049: /**
050: * Execute a prepared XPath expression, returning the results as a List.
051: *
052: * @param source the document or other node against which the XPath expression
053: * will be evaluated. This may be a Saxon NodeInfo object, representing a node in an
054: * existing tree, or it may be any kind of JAXP Source object such as a StreamSource
055: * SAXSource or DOMSource.
056: * @return The results of the expression, as a List. The List represents the sequence
057: * of items returned by the expression. Each item in the list will either be an instance
058: * of net.sf.saxon.om.NodeInfo, representing a node, or a Java object representing an atomic value.
059: */
060:
061: public List evaluate(Source source) throws XPathException {
062: NodeInfo origin;
063: if (source instanceof NodeInfo) {
064: origin = (NodeInfo) source;
065: } else {
066: origin = evaluator.build(source);
067: }
068: XPathContextMajor context = new XPathContextMajor(origin,
069: evaluator.getConfiguration());
070: context.openStackFrame(stackFrameMap);
071: SequenceIterator iter = expression.iterate(context);
072: SequenceExtent extent = new SequenceExtent(iter);
073: List result = (List) extent.convertToJava(List.class, context);
074: if (result == null) {
075: result = Collections.EMPTY_LIST;
076: }
077: return result;
078: }
079:
080: /**
081: * Execute a prepared XPath expression, returning the first item in the result.
082: * This is useful where it is known that the expression will only return
083: * a singleton value (for example, a single node, or a boolean).
084: * @param source the document or other node against which the XPath expression
085: * will be evaluated. This may be a Saxon NodeInfo object, representing a node in an
086: * existing tree, or it may be any kind of JAXP Source object such as a StreamSource
087: * SAXSource or DOMSource.
088: *
089: * @return The first item in the sequence returned by the expression. If the expression
090: * returns an empty sequence, this method returns null. Otherwise, it returns the first
091: * item in the result sequence, represented as a Java object using the same mapping as for
092: * the evaluate() method
093: */
094:
095: public Object evaluateSingle(Source source) throws XPathException {
096: NodeInfo origin;
097: if (source instanceof NodeInfo) {
098: origin = (NodeInfo) source;
099: } else {
100: origin = evaluator.build(source);
101: }
102: XPathContextMajor context = new XPathContextMajor(origin,
103: evaluator.getConfiguration());
104: context.openStackFrame(stackFrameMap);
105: SequenceIterator iterator = expression.iterate(context);
106: Item item = iterator.next();
107: if (item == null) {
108: return null;
109: } else {
110: return Value.convert(item);
111: }
112: }
113:
114: /**
115: * Get a raw iterator over the results of the expression. This returns results without
116: * any conversion of the returned items to "native" Java classes. This method is intended
117: * for use by applications that need to process the results of the expression using
118: * internal Saxon interfaces.
119: * @param source the document or other node against which the XPath expression
120: * will be evaluated. This may be a Saxon NodeInfo object, representing a node in an
121: * existing tree, or it may be any kind of JAXP Source object such as a StreamSource
122: * SAXSource or DOMSource.
123: */
124:
125: public SequenceIterator rawIterator(Source source)
126: throws XPathException {
127: NodeInfo origin;
128: if (source instanceof NodeInfo) {
129: origin = (NodeInfo) source;
130: } else {
131: origin = evaluator.build(source);
132: }
133: XPathContextMajor context = new XPathContextMajor(origin,
134: evaluator.getConfiguration());
135: context.openStackFrame(stackFrameMap);
136: SequenceIterator iterator = expression.iterate(context);
137: return iterator;
138: }
139:
140: /**
141: * Low-level method to get the internal Saxon expression object. This exposes a wide range of
142: * internal methods that may be needed by specialized applications, and allows greater control
143: * over the dynamic context for evaluating the expression.
144: *
145: * @return the underlying Saxon expression object.
146: */
147:
148: public Expression getInternalExpression() {
149: return expression;
150: }
151:
152: }
153:
154: //
155: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
156: // you may not use this file except in compliance with the License. You may obtain a copy of the
157: // License at http://www.mozilla.org/MPL/
158: //
159: // Software distributed under the License is distributed on an "AS IS" basis,
160: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
161: // See the License for the specific language governing rights and limitations under the License.
162: //
163: // The Original Code is: all this file.
164:
165: // The Initial Developer of the Original Code is
166: // Michael H. Kay.
167: //
168: // Contributor(s):
169: //
|