KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > xpath > XPathEvaluator


1 package net.sf.saxon.xpath;
2 import net.sf.saxon.Configuration;
3 import net.sf.saxon.event.Builder;
4 import net.sf.saxon.event.Stripper;
5 import net.sf.saxon.expr.Expression;
6 import net.sf.saxon.expr.ExpressionTool;
7 import net.sf.saxon.expr.XPathContextMajor;
8 import net.sf.saxon.instruct.SlotManager;
9 import net.sf.saxon.om.*;
10 import net.sf.saxon.type.Type;
11 import net.sf.saxon.value.Value;
12 import org.xml.sax.InputSource JavaDoc;
13
14 import javax.xml.namespace.NamespaceContext JavaDoc;
15 import javax.xml.namespace.QName JavaDoc;
16 import javax.xml.transform.Source JavaDoc;
17 import javax.xml.transform.stream.StreamSource JavaDoc;
18 import javax.xml.xpath.*;
19 import java.io.File JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.List JavaDoc;
22
23 /**
24   * <p>XPathEvaluator provides a simple API for standalone XPath processing (that is,
25   * executing XPath expressions in the absence of an XSLT stylesheet). It is an implementation
26  * of the JAXP 1.3 XPath interface, with additional methods provided (a) for backwards
27  * compatibility (b) to give extra control over the XPath evaluation, and (c) to support
28  * XPath 2.0.</p>
29   *
30   * @author Michael H. Kay
31   */

32
33 // TODO: provide a schema-aware XPath evaluator.
34

35 public class XPathEvaluator implements XPath {
36
37     private Configuration config;
38     private NodeInfo contextNode = null;
39     private StandaloneContext staticContext;
40     private boolean stripSpace = false;
41
42     /**
43     * Default constructor. Creates an XPathEvaluator with a default configuration and name pool.
44     */

45
46     public XPathEvaluator() {
47         this(new Configuration());
48     }
49
50     /**
51      * Construct an XPathEvaluator with a specified configuration.
52      * @param config the configuration to be used
53      */

54     public XPathEvaluator(Configuration config) {
55         this.config = config;
56         staticContext = new StandaloneContext(config);
57     }
58
59     /**
60     * Construct an XPathEvaluator to process a particular source document. This is equivalent to
61     * using the default constructor and immediately calling setSource().
62     * @param source The source document (or a specific node within it).
63     */

64
65     public XPathEvaluator(Source JavaDoc source) throws net.sf.saxon.trans.XPathException {
66         super();
67         if (source instanceof NodeInfo) {
68             config = ((NodeInfo)source).getDocumentRoot().getConfiguration();
69         } else {
70             config = new Configuration();
71         }
72         setSource(source);
73     }
74
75     /**
76     * Indicate whether all whitespace text nodes in the source document are to be
77     * removed. This option has no effect unless it is called before the call on setSource(),
78     * and unless the Source supplied to setSource() is a SAXSource or StreamSource.
79     * @param strip True if all whitespace text nodes are to be stripped from the source document,
80     * false otherwise. The default if the method is not called is false.
81     */

82
83     public void setStripSpace(boolean strip) {
84         stripSpace = strip;
85     }
86
87     /**
88     * Supply the document against which XPath expressions are to be executed. This
89     * method must be called before preparing or executing an XPath expression.
90     * Setting a new source document clears all the namespaces that have been declared.
91     * @param source Any javax.xml.transform.Source object representing the document against
92     * which XPath expressions will be executed. Note that a Saxon {@link net.sf.saxon.om.DocumentInfo DocumentInfo}
93      * (indeed any {@link net.sf.saxon.om.NodeInfo NodeInfo})
94      * can be used as a Source. To use a third-party DOM Document as a source, create an instance of
95      * {@link javax.xml.transform.dom.DOMSource DOMSource} to wrap it.
96     * <p>The Source object supplied also determines the initial setting
97     * of the context item. In most cases the context node will be the root of the supplied document;
98     * however, if a NodeInfo or DOMSource is supplied it can be any node in the document. </p>
99     * @return the NodeInfo of the start node in the resulting document object.
100     */

101
102     public NodeInfo setSource(Source JavaDoc source) throws net.sf.saxon.trans.XPathException {
103         NamePool pool;
104         if (source instanceof NodeInfo) {
105             pool = ((NodeInfo)source).getNamePool();
106         } else {
107             pool = NamePool.getDefaultNamePool();
108         }
109         Stripper stripper = null;
110         if (stripSpace) {
111             stripper = AllElementStripper.getInstance();
112         }
113         Configuration config = new Configuration();
114         config.setNamePool(pool);
115         contextNode = Builder.build(source, stripper, config);
116         staticContext = new StandaloneContext(config);
117         return contextNode;
118     }
119
120     /**
121     * Set the static context for compiling XPath expressions. This provides control over the
122     * environment in which the expression is compiled, for example it allows namespace prefixes to
123     * be declared, variables to be bound and functions to be defined. For most purposes, the static
124     * context can be defined by providing and tailoring an instance of the StandaloneContext class.
125     * Until this method is called, a default static context is used, in which no namespaces are defined
126     * other than the standard ones (xml, xslt, and saxon), and no variables or functions (other than the
127     * core XPath functions) are available.
128     */

129
130     public void setStaticContext(StandaloneContext context) {
131         staticContext = context;
132     }
133
134     /**
135     * Get the current static context
136     */

137
138     public StandaloneContext getStaticContext() {
139         return staticContext;
140     }
141
142     /**
143     * Prepare an XPath expression for subsequent evaluation.
144     * @param expression The XPath expression to be evaluated, supplied as a string.
145     * @return an XPathExpression object representing the prepared expression
146     * @throws net.sf.saxon.trans.XPathException if the syntax of the expression is wrong, or if it references namespaces,
147     * variables, or functions that have not been declared.
148     */

149
150     public XPathExpressionImpl createExpression(String JavaDoc expression) throws net.sf.saxon.trans.XPathException {
151         Expression exp = ExpressionTool.make(expression, staticContext,0,-1,1);
152         exp = exp.typeCheck(staticContext, Type.ITEM_TYPE);
153         SlotManager map = staticContext.getConfiguration().makeSlotManager();
154         ExpressionTool.allocateSlots(exp, 0, map);
155         XPathExpressionImpl xpe = new XPathExpressionImpl(exp, config);
156         xpe.setStackFrameMap(map);
157         if (contextNode != null) {
158             xpe.setContextNode(contextNode);
159         }
160         return xpe;
161     }
162
163     /**
164     * Set the context node. This provides the context node for any expressions executed after this
165     * method is called, including expressions that were prepared before it was called.
166     * @param node The node to be used as the context node. This must
167     * be a node within the context document (the document supplied using the setSource() method).
168     * @throws NullPointerException if the argument is null
169     * @throws IllegalArgumentException if the supplied node is not a node in the context document
170     */

171
172     public void setContextNode(NodeInfo node) {
173         if (node==null) {
174             throw new NullPointerException JavaDoc("Context node cannot be null");
175         }
176         contextNode = node;
177     }
178
179     /**
180     * Prepare and execute an XPath expression, supplied as a string, and returning the results
181     * as a List.
182     * @param expression The XPath expression to be evaluated, supplied as a string.
183     * @return The results of the expression, as a List. The List represents the sequence
184     * of items returned by the expression. Each item in the list will either be an object
185     * representing a node, or a Java object representing an atomic value.
186     * The types of Java object that may be included in the list, and the XML Schema data types that they
187     * correspond to, are as follows:<p>
188     * <ul>
189     * <li>Boolean (xs:boolean)</li>
190     * <li>String (xs:string)</li>
191     * <li>BigDecimal (xs:decimal)</li>
192     * <li>Long (xs:integer and its derived types)</li>
193     * <li>Double (xs:double)</li>
194     * <li>Float (xs:float)</li>
195     * <li>Date (xs:date, xs:dateTime)</li>
196     * </ul>
197     */

198
199     public List JavaDoc evaluate(String JavaDoc expression) throws net.sf.saxon.trans.XPathException {
200         Expression exp = ExpressionTool.make(expression, staticContext,0,-1,1);
201         exp = exp.typeCheck(staticContext, Type.ITEM_TYPE);
202         SlotManager map = staticContext.getConfiguration().makeSlotManager();
203         ExpressionTool.allocateSlots(exp, 0, map);
204         XPathContextMajor context = new XPathContextMajor(contextNode, staticContext.getConfiguration());
205         context.openStackFrame(map);
206         SequenceIterator iterator = exp.iterate(context);
207         ArrayList JavaDoc list = new ArrayList JavaDoc(20);
208         while (true) {
209             Item item = iterator.next();
210             if (item == null) {
211                 return list;
212             }
213             list.add(Value.convert(item));
214         }
215     }
216
217     public void reset() {
218         config = null;
219         contextNode = null;
220         staticContext = null;
221         stripSpace = false;
222     }
223
224     /**
225      * Set XPath 1.0 compatibility mode on or off (by default, it is false)
226      * @param compatible true if XPath 1.0 compatibility mode is to be set to true, false
227      * if it is to be set to false.
228      */

229
230     public void setBackwardsCompatible(boolean compatible) {
231         staticContext.setBackwardsCompatibilityMode(true);
232     }
233
234     /**
235      * Get the value of XPath 1.0 compatibility mode
236      * @return true if XPath 1.0 compatibility mode is set
237      */

238
239     public boolean isBackwardsCompatible() {
240         return staticContext.isInBackwardsCompatibleMode();
241     }
242
243     /**
244      * Set the resolver for XPath variables
245      * @param xPathVariableResolver
246      */

247
248     public void setXPathVariableResolver(XPathVariableResolver xPathVariableResolver) {
249         staticContext.setXPathVariableResolver(xPathVariableResolver);
250     }
251
252     /**
253      * Get the resolver for XPath variables
254      * @return the resolver, if one has been set
255      */

256     public XPathVariableResolver getXPathVariableResolver() {
257         return staticContext.getXPathVariableResolver();
258     }
259
260     /**
261      * Set the resolver for XPath functions
262      * @param xPathFunctionResolver
263      */

264
265     public void setXPathFunctionResolver(XPathFunctionResolver xPathFunctionResolver) {
266         staticContext.setXPathFunctionResolver(xPathFunctionResolver);
267     }
268
269     /**
270      * Get the resolver for XPath functions
271      * @return the resolver, if one has been set
272      */

273
274     public XPathFunctionResolver getXPathFunctionResolver() {
275         return staticContext.getXPathFunctionResolver();
276     }
277
278     /**
279      * Set the namespace context to be used. This supplements any namespaces declared directly
280      * using declareNamespace on the staticContext object
281      * @param namespaceContext The namespace context
282      */

283
284     public void setNamespaceContext(NamespaceContext JavaDoc namespaceContext) {
285         staticContext.setNamespaceContext(namespaceContext);
286     }
287
288     /**
289      * Get the namespace context, if one has been set using {@link #setNamespaceContext}
290      * @return the namespace context if set, or null otherwise
291      */

292
293     public NamespaceContext JavaDoc getNamespaceContext() {
294         return staticContext.getNamespaceContext();
295     }
296
297     /**
298      * Compile an XPath 2.0 expression
299      * @param expr the XPath 2.0 expression to be compiled, as a string
300      * @return the compiled form of the expression
301      * @throws XPathExpressionException if there are any static errors in the expression.
302      * Note that references to undeclared variables are not treated as static errors, because
303      * variables are not pre-declared using this API.
304      */

305     public XPathExpression compile(String JavaDoc expr) throws XPathExpressionException {
306         try {
307             return createExpression(expr);
308         } catch (net.sf.saxon.trans.XPathException e) {
309             throw new XPathExpressionException(e);
310         }
311     }
312
313     /**
314      * Single-shot method to compile and execute an XPath 2.0 expression.
315      * @param expr The XPath 2.0 expression to be compiled and executed
316      * @param node The context node for evaluation of the expression
317      * @param qName The type of result required. For details, see
318      * {@link XPathExpressionImpl#evaluate(Object, javax.xml.namespace.QName)}
319      * @return the result of evaluating the expression, returned as described in
320      * {@link XPathExpressionImpl#evaluate(Object, javax.xml.namespace.QName)}
321      * @throws XPathExpressionException if any static or dynamic error occurs
322      * in evaluating the expression.
323      */

324
325     public Object JavaDoc evaluate(String JavaDoc expr, Object JavaDoc node, QName JavaDoc qName) throws XPathExpressionException {
326         XPathExpression exp = compile(expr);
327         return exp.evaluate(node, qName);
328     }
329
330     /**
331      * Single-shot method to compile an execute an XPath 2.0 expression, returning
332      * the result as a string.
333      * @param expr The XPath 2.0 expression to be compiled and executed
334      * @param node The context node for evaluation of the expression
335      * @return the result of evaluating the expression, converted to a string as if
336      * by calling the XPath string() function
337      * @throws XPathExpressionException if any static or dynamic error occurs
338      * in evaluating the expression.
339      */

340
341     public String JavaDoc evaluate(String JavaDoc expr, Object JavaDoc node) throws XPathExpressionException {
342         XPathExpression exp = compile(expr);
343         return exp.evaluate(node);
344     }
345
346     /**
347      * Single-shot method to parse and build a source document, and
348      * compile an execute an XPath 2.0 expression, against that document
349      * @param expr The XPath 2.0 expression to be compiled and executed
350      * @param inputSource The source document: this will be parsed and built into a tree,
351      * and the XPath expression will be executed with the root node of the tree as the
352      * context node
353      * @param qName The type of result required. For details, see
354      * {@link XPathExpressionImpl#evaluate(Object, javax.xml.namespace.QName)}
355      * @return the result of evaluating the expression, returned as described in
356      * {@link XPathExpressionImpl#evaluate(Object, javax.xml.namespace.QName)}
357      * @throws XPathExpressionException if any static or dynamic error occurs
358      * in evaluating the expression.
359      */

360
361     public Object JavaDoc evaluate(String JavaDoc expr, InputSource JavaDoc inputSource, QName JavaDoc qName) throws XPathExpressionException {
362         XPathExpression exp = compile(expr);
363         return exp.evaluate(inputSource, qName);
364     }
365
366     /**
367      * Single-shot method to parse and build a source document, and
368      * compile an execute an XPath 2.0 expression, against that document,
369      * returning the result as a string
370      * @param expr The XPath 2.0 expression to be compiled and executed
371      * @param inputSource The source document: this will be parsed and built into a tree,
372      * and the XPath expression will be executed with the root node of the tree as the
373      * context node
374      * @return the result of evaluating the expression, converted to a string as
375      * if by calling the XPath string() function
376      * @throws XPathExpressionException if any static or dynamic error occurs
377      * in evaluating the expression.
378      */

379
380     public String JavaDoc evaluate(String JavaDoc expr, InputSource JavaDoc inputSource) throws XPathExpressionException {
381         XPathExpression exp = compile(expr);
382         return exp.evaluate(inputSource);
383     }
384
385     /**
386     * Prepare and execute an XPath expression, supplied as a string, and returning the first
387     * item in the result. This is useful where it is known that the expression will only return
388     * a singleton value (for example, a single node, or a boolean).
389     * @param expression The XPath expression to be evaluated, supplied as a string.
390     * @return The first item in the sequence returned by the expression. If the expression
391     * returns an empty sequence, this method returns null. Otherwise, it returns the first
392     * item in the result sequence, represented as a Java object using the same mapping as for
393     * the evaluate() method
394     */

395
396     public Object JavaDoc evaluateSingle(String JavaDoc expression) throws net.sf.saxon.trans.XPathException {
397         Expression exp = ExpressionTool.make(expression, staticContext,0,-1,1);
398         exp = exp.typeCheck(staticContext, Type.ITEM_TYPE);
399         SlotManager map = staticContext.getConfiguration().makeSlotManager();
400         ExpressionTool.allocateSlots(exp, 0, map);
401         XPathContextMajor context = new XPathContextMajor(contextNode, staticContext.getConfiguration());
402         context.openStackFrame(map);
403         SequenceIterator iterator = exp.iterate(context);
404         Item item = iterator.next();
405         if (item == null) {
406             return null;
407         } else {
408             return Value.convert(item);
409         }
410     }
411
412     /**
413      * A simple command-line interface for the XPathEvaluator (not documented).
414      * First parameter is the filename containing the source document, second
415      * parameter is the XPath expression.
416      */

417
418     public static void main(String JavaDoc[] args) throws Exception JavaDoc {
419         if (args.length != 2) {
420             System.err.println("format: java XPathEvaluator source.xml \"expression\"");
421             return;
422         }
423         XPathEvaluator xpe = new XPathEvaluator(new StreamSource JavaDoc(new File JavaDoc(args[0])));
424         List JavaDoc results = xpe.evaluate(args[1]);
425         for (int i = 0; i < results.size(); i++) {
426             Object JavaDoc o = results.get(i);
427             System.err.println(o);
428         }
429     }
430
431 }
432
433 //
434
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
435
// you may not use this file except in compliance with the License. You may obtain a copy of the
436
// License at http://www.mozilla.org/MPL/
437
//
438
// Software distributed under the License is distributed on an "AS IS" basis,
439
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
440
// See the License for the specific language governing rights and limitations under the License.
441
//
442
// The Original Code is: all this file.
443
//
444
// The Initial Developer of the Original Code is Michael H. Kay
445
//
446
// Contributor(s):
447
//
448
Popular Tags