KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > taglibs > standard > tag > common > xml > JSTLXPathAPI


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.taglibs.standard.tag.common.xml;
18
19 import java.util.Vector JavaDoc;
20
21 import javax.servlet.jsp.JspTagException JavaDoc;
22 import javax.xml.transform.TransformerException JavaDoc;
23
24 import org.apache.taglibs.standard.resources.Resources;
25 import org.apache.xml.utils.PrefixResolver;
26 import org.apache.xpath.XPath;
27 import org.apache.xpath.XPathAPI;
28 import org.apache.xpath.XPathContext;
29 import org.apache.xpath.objects.XObject;
30 import org.w3c.dom.Node JavaDoc;
31 import org.w3c.dom.NodeList JavaDoc;
32 import org.w3c.dom.traversal.NodeIterator;
33
34 /**
35  * The methods in this class are convenience methods into the
36  * low-level XPath API.
37  * These functions tend to be a little slow, since a number of objects must be
38  * created for each evaluation. A faster way is to precompile the
39  * XPaths using the low-level API, and then just use the XPaths
40  * over and over.
41  *
42  * NOTE: In particular, each call to this method will create a new
43  * XPathContext, a new DTMManager... and thus a new DTM. That's very
44  * safe, since it guarantees that you're always processing against a
45  * fully up-to-date view of your document. But it's also portentially
46  * very expensive, since you're rebuilding the DTM every time. You should
47  * consider using an instance of CachedXPathAPI rather than these static
48  * methods.
49  *
50  * @see <a HREF="http://www.w3.org/TR/xpath">XPath Specification</a>
51  *
52  */

53 public class JSTLXPathAPI extends XPathAPI {
54     /**
55      * Use an XPath string to select a single node.
56      * XPath namespace prefixes are resolved using the prefixResolver.
57      *
58      * @param contextNode The node to start searching from.
59      * @param str A valid XPath string.
60      * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
61      * @return The first node found that matches the XPath, or null.
62      *
63      * @throws JspTagException
64      */

65     public static Node JavaDoc selectSingleNode(
66     Node JavaDoc contextNode, String JavaDoc str, PrefixResolver prefixResolver)
67     throws JspTagException JavaDoc {
68         
69         // Have the XObject return its result as a NodeSetDTM.
70
NodeIterator nl = selectNodeIterator(contextNode, str, prefixResolver);
71         
72         // Return the first node, or null
73
return nl.nextNode();
74     }
75     
76     /**
77      * Use an XPath string to select a single node.
78      * XPath namespace prefixes are resolved using the prefixResolver.
79      *
80      * @param contextNode The node to start searching from.
81      * @param str A valid XPath string.
82      * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
83      * @return The first node found that matches the XPath, or null.
84      *
85      * @throws JspTagException
86      */

87     public static Node JavaDoc selectSingleNode(
88     Node JavaDoc contextNode, String JavaDoc str, PrefixResolver prefixResolver,
89     XPathContext xpathSupport ) throws JspTagException JavaDoc {
90         
91         // Have the XObject return its result as a NodeSetDTM.
92
NodeIterator nl = selectNodeIterator(contextNode, str, prefixResolver, xpathSupport);
93         
94         // Return the first node, or null
95
return nl.nextNode();
96     }
97     
98     /**
99      * Use an XPath string to select a nodelist.
100      * XPath namespace prefixes are resolved using PrefixResolver.
101      *
102      * @param contextNode The node to start searching from.
103      * @param str A valid XPath string.
104      * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
105      * @return A NodeIterator, should never be null.
106      *
107      * @throws JspTagException
108      */

109     public static NodeIterator selectNodeIterator(
110     Node JavaDoc contextNode, String JavaDoc str, PrefixResolver prefixResolver)
111     throws JspTagException JavaDoc {
112         
113         // Execute the XPath, and have it return the result
114
XObject list = eval(contextNode, str, prefixResolver, null);
115         
116         // Have the XObject return its result as a NodeSetDTM.
117
return getNodeIterator(list);
118     }
119     
120     /**
121      * Use an XPath string to select a nodelist.
122      * XPath namespace prefixes are resolved using PrefixResolver.
123      *
124      * @param contextNode The node to start searching from.
125      * @param str A valid XPath string.
126      * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
127      * @return A NodeIterator, should never be null.
128      *
129      * @throws JspTagException
130      */

131     public static NodeIterator selectNodeIterator(
132     Node JavaDoc contextNode, String JavaDoc str, PrefixResolver prefixResolver,
133     XPathContext xpathSupport ) throws JspTagException JavaDoc {
134         
135         // Execute the XPath, and have it return the result
136
XObject list = eval(contextNode, str, prefixResolver, xpathSupport);
137         
138         // Have the XObject return its result as a NodeSetDTM.
139
return getNodeIterator(list);
140     }
141     
142     /**
143      * Use an XPath string to select a nodelist.
144      * XPath namespace prefixes are resolved using the prefixResolver.
145      *
146      * @param contextNode The node to start searching from.
147      * @param str A valid XPath string.
148      * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
149      * @return A NodeIterator, should never be null.
150      *
151      * @throws JspTagException
152      */

153     private static NodeList JavaDoc selectNodeList(
154     Node JavaDoc contextNode, String JavaDoc str, PrefixResolver prefixResolver)
155     throws JspTagException JavaDoc {
156         // Execute the XPath, and have it return the result
157
XObject list = eval(contextNode, str, prefixResolver, null);
158         
159         // Return a NodeList.
160
return getNodeList(list);
161     }
162     
163     /**
164      * Use an XPath string to select a nodelist.
165      * XPath namespace prefixes are resolved using the prefixResolver.
166      *
167      * @param contextNode The node to start searching from.
168      * @param str A valid XPath string.
169      * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
170      * @return A NodeIterator, should never be null.
171      *
172      * @throws JspTagException
173      */

174     public static NodeList JavaDoc selectNodeList(
175     Node JavaDoc contextNode, String JavaDoc str, PrefixResolver prefixResolver,
176     XPathContext xpathSupport )
177     throws JspTagException JavaDoc
178     {
179         // Execute the XPath, and have it return the result
180
XObject list = eval(contextNode, str, prefixResolver, xpathSupport);
181         
182         // Return a NodeList.
183
return getNodeList(list);
184     }
185         
186     /**
187      * Returns a NodeIterator from an XObject.
188      * @param list The XObject from which a NodeIterator is returned.
189      * @return A NodeIterator, should never be null.
190      * @throws JspTagException
191      */

192     private static NodeIterator getNodeIterator(XObject list)
193     throws JspTagException JavaDoc {
194         try {
195             return list.nodeset();
196         } catch (TransformerException JavaDoc ex) {
197             throw new JspTagException JavaDoc(
198                 Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex);
199         }
200     }
201
202     /**
203      * Returns a NodeList from an XObject.
204      * @param list The XObject from which a NodeList is returned.
205      * @return A NodeList, should never be null.
206      * @throws JspTagException
207      */

208     static NodeList JavaDoc getNodeList(XObject list)
209     throws JspTagException JavaDoc {
210         try {
211             return list.nodelist();
212         } catch (TransformerException JavaDoc ex) {
213             throw new JspTagException JavaDoc(
214                 Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex);
215         }
216     }
217     
218     /**
219      * Evaluate XPath string to an XObject.
220      * XPath namespace prefixes are resolved from the namespaceNode.
221      * The implementation of this is a little slow, since it creates
222      * a number of objects each time it is called. This could be optimized
223      * to keep the same objects around, but then thread-safety issues would arise.
224      *
225      * @param contextNode The node to start searching from.
226      * @param str A valid XPath string.
227      * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
228      * @param prefixResolver Will be called if the parser encounters namespace
229      * prefixes, to resolve the prefixes to URLs.
230      * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
231      * @see org.apache.xpath.objects.XObject
232      * @see org.apache.xpath.objects.XNull
233      * @see org.apache.xpath.objects.XBoolean
234      * @see org.apache.xpath.objects.XNumber
235      * @see org.apache.xpath.objects.XString
236      * @see org.apache.xpath.objects.XRTreeFrag
237      *
238      * @throws JspTagException
239      */

240     public static XObject eval(
241     Node JavaDoc contextNode, String JavaDoc str, PrefixResolver prefixResolver,
242     XPathContext xpathSupport) throws JspTagException JavaDoc {
243         //System.out.println("eval of XPathContext params: contextNode:str(xpath)"+
244
// ":prefixResolver:xpathSupport => " + contextNode + ":" + str + ":" +
245
// prefixResolver + ":" + xpathSupport );
246
try {
247             if (xpathSupport == null) {
248                 return eval(contextNode, str, prefixResolver);
249             }
250             
251             // Since we don't have a XML Parser involved here, install some default support
252
// for things like namespaces, etc.
253
// (Changed from: XPathContext xpathSupport = new XPathContext();
254
// because XPathContext is weak in a number of areas... perhaps
255
// XPathContext should be done away with.)
256
// Create the XPath object.
257
XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
258             
259             // Execute the XPath, and have it return the result
260
int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
261             
262             // System.out.println("Context Node id ( after getDTMHandlerFromNode) => " + ctxtNode );
263
XObject xobj = xpath.execute(xpathSupport, ctxtNode, prefixResolver);
264             return xobj;
265         } catch (TransformerException JavaDoc ex) {
266             throw new JspTagException JavaDoc(
267                 Resources.getMessage("XPATH_ERROR_EVALUATING_EXPR", str, ex.toString()), ex);
268         } catch (IllegalArgumentException JavaDoc ex) {
269             throw new JspTagException JavaDoc(
270                 Resources.getMessage("XPATH_ILLEGAL_ARG_EVALUATING_EXPR", str, ex.toString()), ex);
271         }
272     }
273     
274     public static XObject eval(
275     Node JavaDoc contextNode, String JavaDoc str, PrefixResolver prefixResolver,
276     XPathContext xpathSupport, Vector JavaDoc varQNames) throws JspTagException JavaDoc {
277         //p("***************** eval ");
278
//p( "contextNode => " + contextNode );
279
//p( "XPath str => " + str );
280
//p( "PrefixResolver => " + prefixResolver );
281
//p( "XPath Context => " + xpathSupport );
282
//p( "Var QNames => " + varQNames );
283
//p( "Global Var Size => " + varQNames.size() );
284
try {
285             XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
286             xpath.fixupVariables( varQNames, varQNames.size());
287             // Execute the XPath, and have it return the result
288
int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
289             // System.out.println("Context Node id ( after getDTMHandlerFromNode) => " + ctxtNode );
290
return xpath.execute(xpathSupport, ctxtNode, prefixResolver);
291         } catch (TransformerException JavaDoc ex) {
292             throw new JspTagException JavaDoc(
293             Resources.getMessage("XPATH_ERROR_EVALUATING_EXPR", str, ex.toString()), ex);
294         } catch (IllegalArgumentException JavaDoc ex) {
295             throw new JspTagException JavaDoc(
296             Resources.getMessage("XPATH_ILLEGAL_ARG_EVALUATING_EXPR", str, ex.toString()), ex);
297         }
298     }
299     
300     private static void p(String JavaDoc s) {
301         System.out.println("[JSTLXPathAPI] " + s);
302     }
303 }
304
Popular Tags