001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: XPathExpressionImpl.java 1225426 2011-12-29 04:13:08Z mrglavas $ 020 */ 021 022 023 package org.apache.xpath.domapi; 024 025 import javax.xml.transform.TransformerException; 026 027 import org.apache.xpath.XPath; 028 import org.apache.xpath.XPathContext; 029 import org.apache.xpath.objects.XObject; 030 import org.apache.xpath.res.XPATHErrorResources; 031 import org.apache.xpath.res.XPATHMessages; 032 import org.w3c.dom.DOMException; 033 import org.w3c.dom.Document; 034 import org.w3c.dom.Node; 035 import org.w3c.dom.xpath.XPathException; 036 import org.w3c.dom.xpath.XPathExpression; 037 import org.w3c.dom.xpath.XPathNamespace; 038 039 /** 040 * 041 * The class provides an implementation of XPathExpression according 042 * to the DOM L3 XPath Specification, Working Group Note 26 February 2004. 043 * 044 * <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> 045 * 046 * <p>The <code>XPathExpression</code> interface represents a parsed and resolved 047 * XPath expression.</p> 048 * 049 * @see org.w3c.dom.xpath.XPathExpression 050 * 051 * @xsl.usage internal 052 */ 053 class XPathExpressionImpl implements XPathExpression { 054 055 /** 056 * The xpath object that this expression wraps 057 */ 058 final private XPath m_xpath; 059 060 /** 061 * The document to be searched to parallel the case where the XPathEvaluator 062 * is obtained by casting a Document. 063 */ 064 final private Document m_doc; 065 066 /** 067 * Constructor for XPathExpressionImpl. 068 * 069 * @param xpath The wrapped XPath object. 070 * @param doc The document to be searched, to parallel the case where'' 071 * the XPathEvaluator is obtained by casting the document. 072 */ 073 XPathExpressionImpl(XPath xpath, Document doc) { 074 m_xpath = xpath; 075 m_doc = doc; 076 } 077 078 /** 079 * 080 * This method provides an implementation XPathResult.evaluate according 081 * to the DOM L3 XPath Specification, Working Group Note 26 February 2004. 082 * 083 * <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> 084 * 085 * <p>Evaluates this XPath expression and returns a result.</p> 086 * @param contextNode The <code>context</code> is context node for the 087 * evaluation of this XPath expression.If the XPathEvaluator was 088 * obtained by casting the <code>Document</code> then this must be 089 * owned by the same document and must be a <code>Document</code>, 090 * <code>Element</code>, <code>Attribute</code>, <code>Text</code>, 091 * <code>CDATASection</code>, <code>Comment</code>, 092 * <code>ProcessingInstruction</code>, or <code>XPathNamespace</code> 093 * node.If the context node is a <code>Text</code> or a 094 * <code>CDATASection</code>, then the context is interpreted as the 095 * whole logical text node as seen by XPath, unless the node is empty 096 * in which case it may not serve as the XPath context. 097 * @param type If a specific <code>type</code> is specified, then the 098 * result will be coerced to return the specified type relying on 099 * XPath conversions and fail if the desired coercion is not possible. 100 * This must be one of the type codes of <code>XPathResult</code>. 101 * @param result The <code>result</code> specifies a specific result 102 * object which may be reused and returned by this method. If this is 103 * specified as <code>null</code>or the implementation does not reuse 104 * the specified result, a new result object will be constructed and 105 * returned.For XPath 1.0 results, this object will be of type 106 * <code>XPathResult</code>. 107 * @return The result of the evaluation of the XPath expression.For XPath 108 * 1.0 results, this object will be of type <code>XPathResult</code>. 109 * @exception XPathException 110 * TYPE_ERR: Raised if the result cannot be converted to return the 111 * specified type. 112 * @exception DOMException 113 * WRONG_DOCUMENT_ERR: The Node is from a document that is not supported 114 * by the XPathEvaluator that created this 115 * <code>XPathExpression</code>. 116 * <br>NOT_SUPPORTED_ERR: The Node is not a type permitted as an XPath 117 * context node. 118 * 119 * @see org.w3c.dom.xpath.XPathExpression#evaluate(Node, short, XPathResult) 120 * @xsl.usage internal 121 */ 122 public Object evaluate( 123 Node contextNode, 124 short type, 125 Object result) 126 throws XPathException, DOMException { 127 128 // If the XPathEvaluator was determined by "casting" the document 129 if (m_doc != null) { 130 131 // Check that the context node is owned by the same document 132 if ((contextNode != m_doc) && (!contextNode.getOwnerDocument().equals(m_doc))) { 133 String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_WRONG_DOCUMENT, null); 134 throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, fmsg); 135 } 136 137 // Check that the context node is an acceptable node type 138 short nodeType = contextNode.getNodeType(); 139 if ((nodeType != Document.DOCUMENT_NODE) && 140 (nodeType != Document.ELEMENT_NODE) && 141 (nodeType != Document.ATTRIBUTE_NODE) && 142 (nodeType != Document.TEXT_NODE) && 143 (nodeType != Document.CDATA_SECTION_NODE) && 144 (nodeType != Document.COMMENT_NODE) && 145 (nodeType != Document.PROCESSING_INSTRUCTION_NODE) && 146 (nodeType != XPathNamespace.XPATH_NAMESPACE_NODE)) { 147 String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_WRONG_NODETYPE, null); 148 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, fmsg); 149 } 150 } 151 152 // 153 // If the type is not a supported type, throw an exception and be 154 // done with it! 155 if (!XPathResultImpl.isValidType(type)) { 156 String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INVALID_XPATH_TYPE, new Object[] {new Integer(type)}); 157 throw new XPathException(XPathException.TYPE_ERR,fmsg); // Invalid XPath type argument: {0} 158 } 159 160 // Create an XPathContext that doesn't support pushing and popping of 161 // variable resolution scopes. Sufficient for simple XPath 1.0 162 // expressions. 163 // Cache xpath context? 164 XPathContext xpathSupport = new XPathContext(false); 165 166 // if m_document is not null, build the DTM from the document 167 if (null != m_doc) { 168 xpathSupport.getDTMHandleFromNode(m_doc); 169 } 170 171 XObject xobj = null; 172 try { 173 xobj = m_xpath.execute(xpathSupport, contextNode, null); 174 } catch (TransformerException te) { 175 // What should we do here? 176 throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,te.getMessageAndLocation()); 177 } 178 179 // Create a new XPathResult object 180 // Reuse result object passed in? 181 // The constructor will check the compatibility of type and xobj and 182 // throw an exception if they are not compatible. 183 return new XPathResultImpl(type,xobj,contextNode, m_xpath); 184 } 185 186 }