1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2002-2005 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: XPathEvaluatorImpl.java,v 1.2.4.1 2005/09/10 04:04:07 jeffsuttor Exp $ 22 */ 23 24 package com.sun.org.apache.xpath.internal.domapi; 25 26 import javax.xml.transform.TransformerException; 27 28 import com.sun.org.apache.xml.internal.utils.PrefixResolver; 29 import com.sun.org.apache.xpath.internal.XPath; 30 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; 31 import com.sun.org.apache.xpath.internal.res.XPATHMessages; 32 import org.w3c.dom.DOMException; 33 import org.w3c.dom.Document; 34 import org.w3c.dom.Node; 35 import org.w3c.dom.xpath.XPathEvaluator; 36 import org.w3c.dom.xpath.XPathException; 37 import org.w3c.dom.xpath.XPathExpression; 38 import org.w3c.dom.xpath.XPathNSResolver; 39 40 /** 41 * 42 * The class provides an implementation of XPathEvaluator according 43 * to the DOM L3 XPath Specification, Working Group Note 26 February 2004. 44 * 45 * <p>See also the <a href='http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226'>Document Object Model (DOM) Level 3 XPath Specification</a>.</p> 46 * 47 * </p>The evaluation of XPath expressions is provided by 48 * <code>XPathEvaluator</code>, which will provide evaluation of XPath 1.0 49 * expressions with no specialized extension functions or variables. It is 50 * expected that the <code>XPathEvaluator</code> interface will be 51 * implemented on the same object which implements the <code>Document</code> 52 * interface in an implementation which supports the XPath DOM module. 53 * <code>XPathEvaluator</code> implementations may be available from other 54 * sources that may provide support for special extension functions or 55 * variables which are not defined in this specification.</p> 56 * 57 * @see org.w3c.dom.xpath.XPathEvaluator 58 * 59 * @xsl.usage internal 60 */ 61 public final class XPathEvaluatorImpl implements XPathEvaluator { 62 63 /** 64 * This prefix resolver is created whenever null is passed to the 65 * evaluate method. Its purpose is to satisfy the DOM L3 XPath API 66 * requirement that if a null prefix resolver is used, an exception 67 * should only be thrown when an attempt is made to resolve a prefix. 68 */ 69 private class DummyPrefixResolver implements PrefixResolver { 70 71 /** 72 * Constructor for DummyPrefixResolver. 73 */ DummyPrefixResolver()74 DummyPrefixResolver() {} 75 76 /** 77 * @exception DOMException 78 * NAMESPACE_ERR: Always throws this exceptionn 79 * 80 * @see com.sun.org.apache.xml.internal.utils.PrefixResolver#getNamespaceForPrefix(String, Node) 81 */ getNamespaceForPrefix(String prefix, Node context)82 public String getNamespaceForPrefix(String prefix, Node context) { 83 String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_RESOLVER, null); 84 throw new DOMException(DOMException.NAMESPACE_ERR, fmsg); // Unable to resolve prefix with null prefix resolver. 85 } 86 87 /** 88 * @exception DOMException 89 * NAMESPACE_ERR: Always throws this exceptionn 90 * 91 * @see com.sun.org.apache.xml.internal.utils.PrefixResolver#getNamespaceForPrefix(String) 92 */ getNamespaceForPrefix(String prefix)93 public String getNamespaceForPrefix(String prefix) { 94 return getNamespaceForPrefix(prefix,null); 95 } 96 97 /** 98 * @see com.sun.org.apache.xml.internal.utils.PrefixResolver#handlesNullPrefixes() 99 */ handlesNullPrefixes()100 public boolean handlesNullPrefixes() { 101 return false; 102 } 103 104 /** 105 * @see com.sun.org.apache.xml.internal.utils.PrefixResolver#getBaseIdentifier() 106 */ getBaseIdentifier()107 public String getBaseIdentifier() { 108 return null; 109 } 110 111 } 112 113 /** 114 * The document to be searched to parallel the case where the XPathEvaluator 115 * is obtained by casting a Document. 116 */ 117 private final Document m_doc; 118 119 /** 120 * Constructor for XPathEvaluatorImpl. 121 * 122 * @param doc The document to be searched, to parallel the case where'' 123 * the XPathEvaluator is obtained by casting the document. 124 */ XPathEvaluatorImpl(Document doc)125 public XPathEvaluatorImpl(Document doc) { 126 m_doc = doc; 127 } 128 129 /** 130 * Constructor in the case that the XPath expression can be evaluated 131 * without needing an XML document at all. 132 * 133 */ XPathEvaluatorImpl()134 public XPathEvaluatorImpl() { 135 m_doc = null; 136 } 137 138 /** 139 * Creates a parsed XPath expression with resolved namespaces. This is 140 * useful when an expression will be reused in an application since it 141 * makes it possible to compile the expression string into a more 142 * efficient internal form and preresolve all namespace prefixes which 143 * occur within the expression. 144 * 145 * @param expression The XPath expression string to be parsed. 146 * @param resolver The <code>resolver</code> permits translation of 147 * prefixes within the XPath expression into appropriate namespace URIs 148 * . If this is specified as <code>null</code>, any namespace prefix 149 * within the expression will result in <code>DOMException</code> 150 * being thrown with the code <code>NAMESPACE_ERR</code>. 151 * @return The compiled form of the XPath expression. 152 * @exception XPathException 153 * INVALID_EXPRESSION_ERR: Raised if the expression is not legal 154 * according to the rules of the <code>XPathEvaluator</code>i 155 * @exception DOMException 156 * NAMESPACE_ERR: Raised if the expression contains namespace prefixes 157 * which cannot be resolved by the specified 158 * <code>XPathNSResolver</code>. 159 * 160 * @see org.w3c.dom.xpath.XPathEvaluator#createExpression(String, XPathNSResolver) 161 */ createExpression( String expression, XPathNSResolver resolver)162 public XPathExpression createExpression( 163 String expression, 164 XPathNSResolver resolver) 165 throws XPathException, DOMException { 166 167 try { 168 169 // If the resolver is null, create a dummy prefix resolver 170 XPath xpath = new XPath(expression,null, 171 ((null == resolver) ? new DummyPrefixResolver() : ((PrefixResolver)resolver)), 172 XPath.SELECT); 173 174 return new XPathExpressionImpl(xpath, m_doc); 175 176 } catch (TransformerException e) { 177 // Need to pass back exception code DOMException.NAMESPACE_ERR also. 178 // Error found in DOM Level 3 XPath Test Suite. 179 if(e instanceof XPathStylesheetDOM3Exception) 180 throw new DOMException(DOMException.NAMESPACE_ERR,e.getMessageAndLocation()); 181 else 182 throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,e.getMessageAndLocation()); 183 184 } 185 } 186 187 /** 188 * Adapts any DOM node to resolve namespaces so that an XPath expression 189 * can be easily evaluated relative to the context of the node where it 190 * appeared within the document. This adapter works like the DOM Level 3 191 * method <code>lookupNamespaceURI</code> on nodes in resolving the 192 * namespaceURI from a given prefix using the current information available 193 * in the node's hierarchy at the time lookupNamespaceURI is called, also 194 * correctly resolving the implicit xml prefix. 195 * 196 * @param nodeResolver The node to be used as a context for namespace 197 * resolution. 198 * @return <code>XPathNSResolver</code> which resolves namespaces with 199 * respect to the definitions in scope for a specified node. 200 * 201 * @see org.w3c.dom.xpath.XPathEvaluator#createNSResolver(Node) 202 */ createNSResolver(Node nodeResolver)203 public XPathNSResolver createNSResolver(Node nodeResolver) { 204 205 return new XPathNSResolverImpl((nodeResolver.getNodeType() == Node.DOCUMENT_NODE) 206 ? ((Document) nodeResolver).getDocumentElement() : nodeResolver); 207 } 208 209 /** 210 * Evaluates an XPath expression string and returns a result of the 211 * specified type if possible. 212 * 213 * @param expression The XPath expression string to be parsed and 214 * evaluated. 215 * @param contextNode The <code>context</code> is context node for the 216 * evaluation of this XPath expression. If the XPathEvaluator was 217 * obtained by casting the <code>Document</code> then this must be 218 * owned by the same document and must be a <code>Document</code>, 219 * <code>Element</code>, <code>Attribute</code>, <code>Text</code>, 220 * <code>CDATASection</code>, <code>Comment</code>, 221 * <code>ProcessingInstruction</code>, or <code>XPathNamespace</code> 222 * node. If the context node is a <code>Text</code> or a 223 * <code>CDATASection</code>, then the context is interpreted as the 224 * whole logical text node as seen by XPath, unless the node is empty 225 * in which case it may not serve as the XPath context. 226 * @param resolver The <code>resolver</code> permits translation of 227 * prefixes within the XPath expression into appropriate namespace URIs 228 * . If this is specified as <code>null</code>, any namespace prefix 229 * within the expression will result in <code>DOMException</code> 230 * being thrown with the code <code>NAMESPACE_ERR</code>. 231 * @param type If a specific <code>type</code> is specified, then the 232 * result will be coerced to return the specified type relying on 233 * XPath type conversions and fail if the desired coercion is not 234 * possible. This must be one of the type codes of 235 * <code>XPathResult</code>. 236 * @param result The <code>result</code> specifies a specific result 237 * object which may be reused and returned by this method. If this is 238 * specified as <code>null</code>or the implementation does not reuse 239 * the specified result, a new result object will be constructed and 240 * returned.For XPath 1.0 results, this object will be of type 241 * <code>XPathResult</code>. 242 * @return The result of the evaluation of the XPath expression.For XPath 243 * 1.0 results, this object will be of type <code>XPathResult</code>. 244 * @exception XPathException 245 * INVALID_EXPRESSION_ERR: Raised if the expression is not legal 246 * according to the rules of the <code>XPathEvaluator</code>i 247 * <br>TYPE_ERR: Raised if the result cannot be converted to return the 248 * specified type. 249 * @exception DOMException 250 * NAMESPACE_ERR: Raised if the expression contains namespace prefixes 251 * which cannot be resolved by the specified 252 * <code>XPathNSResolver</code>. 253 * <br>WRONG_DOCUMENT_ERR: The Node is from a document that is not 254 * supported by this XPathEvaluator. 255 * <br>NOT_SUPPORTED_ERR: The Node is not a type permitted as an XPath 256 * context node. 257 * 258 * @see org.w3c.dom.xpath.XPathEvaluator#evaluate(String, Node, XPathNSResolver, short, XPathResult) 259 */ evaluate( String expression, Node contextNode, XPathNSResolver resolver, short type, Object result)260 public Object evaluate( 261 String expression, 262 Node contextNode, 263 XPathNSResolver resolver, 264 short type, 265 Object result) 266 throws XPathException, DOMException { 267 268 XPathExpression xpathExpression = createExpression(expression, resolver); 269 270 return xpathExpression.evaluate(contextNode, type, result); 271 } 272 273 } 274