14c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/* 24c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one 34c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * or more contributor license agreements. See the NOTICE file 44c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed with this work for additional information 54c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * regarding copyright ownership. The ASF licenses this file 64c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to you under the Apache License, Version 2.0 (the "License"); 74c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * you may not use this file except in compliance with the License. 84c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * You may obtain a copy of the License at 94c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Unless required by applicable law or agreed to in writing, software 134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * See the License for the specific language governing permissions and 164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * limitations under the License. 174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/* 194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * $Id: CachedXPathAPI.java 524811 2007-04-02 15:51:59Z zongaro $ 204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpackage org.apache.xpath; 224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.TransformerException; 244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.PrefixResolver; 264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.PrefixResolverDefault; 274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.objects.XObject; 284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.w3c.dom.Document; 304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.w3c.dom.Node; 314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.w3c.dom.NodeList; 324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.w3c.dom.traversal.NodeIterator; 334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/** 354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * The methods in this class are convenience methods into the 364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * low-level XPath API. 374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * These functions tend to be a little slow, since a number of objects must be 394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * created for each evaluation. A faster way is to precompile the 404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * XPaths using the low-level API, and then just use the XPaths 414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * over and over. 424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * This is an alternative for the old XPathAPI class, which provided 444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * static methods for the purpose but had the drawback of 454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * instantiating a new XPathContext (and thus building a new DTMManager, 464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * and new DTMs) each time it was called. XPathAPIObject instead retains 474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * its context as long as the object persists, reusing the DTMs. This 484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * does have a downside: if you've changed your source document, you should 494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * obtain a new XPathAPIObject to continue searching it, since trying to use 504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * the old DTMs will probably yield bad results or malfunction outright... and 514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * the cached DTMs may consume memory until this object and its context are 524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * returned to the heap. Essentially, it's the caller's responsibility to 534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * decide when to discard the cache. 544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see <a href="http://www.w3.org/TR/xpath">XPath Specification</a> 564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * */ 574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpublic class CachedXPathAPI 584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson{ 594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** XPathContext, and thus the document model system (DTMs), persists through multiple 604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson calls to this object. This is set in the constructor. 614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson protected XPathContext xpathSupport; 634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <p>Default constructor. Establishes its own {@link XPathContext}, and hence 664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * its own {@link org.apache.xml.dtm.DTMManager}. 674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Good choice for simple uses.</p> 684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <p>Note that any particular instance of {@link CachedXPathAPI} must not be 694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * operated upon by multiple threads without synchronization; we do 704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * not currently support multithreaded access to a single 714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * {@link org.apache.xml.dtm.DTM}.</p> 724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public CachedXPathAPI() 744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Create an XPathContext that doesn't support pushing and popping of 764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // variable resolution scopes. Sufficient for simple XPath 1.0 expressions. 774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson xpathSupport = new XPathContext(false); 784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <p>This constructor shares its {@link XPathContext} with a pre-existing 824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * {@link CachedXPathAPI}. That allows sharing document models 834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * ({@link org.apache.xml.dtm.DTM}) and previously established location 844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * state.</p> 854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <p>Note that the original {@link CachedXPathAPI} and the new one should 864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * not be operated upon concurrently; we do not support multithreaded access 874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to a single {@link org.apache.xml.dtm.DTM} at this time. Similarly, 884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * any particular instance of {@link CachedXPathAPI} must not be operated 894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * upon by multiple threads without synchronization.</p> 904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <p>%REVIEW% Should this instead do a clone-and-reset on the XPathSupport object?</p> 914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public CachedXPathAPI(CachedXPathAPI priorXPathAPI) 944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson xpathSupport = priorXPathAPI.xpathSupport; 964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** Returns the XPathSupport object used in this CachedXPathAPI 1004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * %REVIEW% I'm somewhat concerned about the loss of encapsulation 1024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * this causes, but the xml-security folks say they need it. 1034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * */ 1044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public XPathContext getXPathContext() 1054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 1064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return this.xpathSupport; 1074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 1114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Use an XPath string to select a single node. XPath namespace 1124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * prefixes are resolved from the context node, which may not 1134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * be what you want (see the next method). 1144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param contextNode The node to start searching from. 1164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param str A valid XPath string. 1174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return The first node found that matches the XPath, or null. 1184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws TransformerException 1204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 1214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public Node selectSingleNode(Node contextNode, String str) 1224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws TransformerException 1234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 1244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return selectSingleNode(contextNode, str, contextNode); 1254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 1284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Use an XPath string to select a single node. 1294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * XPath namespace prefixes are resolved from the namespaceNode. 1304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param contextNode The node to start searching from. 1324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param str A valid XPath string. 1334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces. 1344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return The first node found that matches the XPath, or null. 1354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws TransformerException 1374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 1384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public Node selectSingleNode( 1394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson Node contextNode, String str, Node namespaceNode) 1404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws TransformerException 1414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 1424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Have the XObject return its result as a NodeSetDTM. 1444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson NodeIterator nl = selectNodeIterator(contextNode, str, namespaceNode); 1454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Return the first node, or null 1474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return nl.nextNode(); 1484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 1514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Use an XPath string to select a nodelist. 1524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * XPath namespace prefixes are resolved from the contextNode. 1534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param contextNode The node to start searching from. 1554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param str A valid XPath string. 1564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return A NodeIterator, should never be null. 1574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws TransformerException 1594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 1604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public NodeIterator selectNodeIterator(Node contextNode, String str) 1614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws TransformerException 1624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 1634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return selectNodeIterator(contextNode, str, contextNode); 1644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 1674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Use an XPath string to select a nodelist. 1684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * XPath namespace prefixes are resolved from the namespaceNode. 1694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param contextNode The node to start searching from. 1714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param str A valid XPath string. 1724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces. 1734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return A NodeIterator, should never be null. 1744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws TransformerException 1764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 1774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public NodeIterator selectNodeIterator( 1784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson Node contextNode, String str, Node namespaceNode) 1794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws TransformerException 1804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 1814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Execute the XPath, and have it return the result 1834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson XObject list = eval(contextNode, str, namespaceNode); 1844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Have the XObject return its result as a NodeSetDTM. 1864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return list.nodeset(); 1874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 1904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Use an XPath string to select a nodelist. 1914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * XPath namespace prefixes are resolved from the contextNode. 1924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param contextNode The node to start searching from. 1944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param str A valid XPath string. 1954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return A NodeIterator, should never be null. 1964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws TransformerException 1984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 1994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public NodeList selectNodeList(Node contextNode, String str) 2004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws TransformerException 2014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 2024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return selectNodeList(contextNode, str, contextNode); 2034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 2044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 2064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Use an XPath string to select a nodelist. 2074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * XPath namespace prefixes are resolved from the namespaceNode. 2084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 2094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param contextNode The node to start searching from. 2104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param str A valid XPath string. 2114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces. 2124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return A NodeIterator, should never be null. 2134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 2144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws TransformerException 2154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 2164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public NodeList selectNodeList( 2174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson Node contextNode, String str, Node namespaceNode) 2184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws TransformerException 2194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 2204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Execute the XPath, and have it return the result 2224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson XObject list = eval(contextNode, str, namespaceNode); 2234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Return a NodeList. 2254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return list.nodelist(); 2264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 2274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 2294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Evaluate XPath string to an XObject. Using this method, 2304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * XPath namespace prefixes will be resolved from the namespaceNode. 2314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param contextNode The node to start searching from. 2324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param str A valid XPath string. 2334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null. 2344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XObject 2354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XNull 2364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XBoolean 2374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XNumber 2384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XString 2394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XRTreeFrag 2404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 2414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws TransformerException 2424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 2434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public XObject eval(Node contextNode, String str) 2444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws TransformerException 2454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 2464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return eval(contextNode, str, contextNode); 2474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 2484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 2504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Evaluate XPath string to an XObject. 2514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * XPath namespace prefixes are resolved from the namespaceNode. 2524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * The implementation of this is a little slow, since it creates 2534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * a number of objects each time it is called. This could be optimized 2544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to keep the same objects around, but then thread-safety issues would arise. 2554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 2564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param contextNode The node to start searching from. 2574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param str A valid XPath string. 2584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces. 2594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null. 2604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XObject 2614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XNull 2624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XBoolean 2634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XNumber 2644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XString 2654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XRTreeFrag 2664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 2674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws TransformerException 2684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 2694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public XObject eval(Node contextNode, String str, Node namespaceNode) 2704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws TransformerException 2714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 2724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Since we don't have a XML Parser involved here, install some default support 2744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // for things like namespaces, etc. 2754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // (Changed from: XPathContext xpathSupport = new XPathContext(); 2764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // because XPathContext is weak in a number of areas... perhaps 2774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // XPathContext should be done away with.) 2784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Create an object to resolve namespace prefixes. 2804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // XPath namespaces are resolved from the input context node's document element 2814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // if it is a root node, or else the current context node (for lack of a better 2824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // resolution space, given the simplicity of this sample code). 2834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson PrefixResolverDefault prefixResolver = new PrefixResolverDefault( 2844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson (namespaceNode.getNodeType() == Node.DOCUMENT_NODE) 2854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson ? ((Document) namespaceNode).getDocumentElement() : namespaceNode); 2864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Create the XPath object. 2884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null); 2894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Execute the XPath, and have it return the result 2914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // return xpath.execute(xpathSupport, contextNode, prefixResolver); 2924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode); 2934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return xpath.execute(xpathSupport, ctxtNode, prefixResolver); 2954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 2964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 2974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 2984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Evaluate XPath string to an XObject. 2994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * XPath namespace prefixes are resolved from the namespaceNode. 3004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * The implementation of this is a little slow, since it creates 3014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * a number of objects each time it is called. This could be optimized 3024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to keep the same objects around, but then thread-safety issues would arise. 3034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 3044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param contextNode The node to start searching from. 3054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param str A valid XPath string. 3064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param prefixResolver Will be called if the parser encounters namespace 3074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * prefixes, to resolve the prefixes to URLs. 3084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null. 3094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XObject 3104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XNull 3114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XBoolean 3124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XNumber 3134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XString 3144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see org.apache.xpath.objects.XRTreeFrag 3154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 3164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws TransformerException 3174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 3184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public XObject eval( 3194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson Node contextNode, String str, PrefixResolver prefixResolver) 3204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws TransformerException 3214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 3224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 3234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Since we don't have a XML Parser involved here, install some default support 3244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // for things like namespaces, etc. 3254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // (Changed from: XPathContext xpathSupport = new XPathContext(); 3264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // because XPathContext is weak in a number of areas... perhaps 3274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // XPathContext should be done away with.) 3284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Create the XPath object. 3294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null); 3304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 3314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Create an XPathContext that doesn't support pushing and popping of 3324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // variable resolution scopes. Sufficient for simple XPath 1.0 expressions. 3334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson XPathContext xpathSupport = new XPathContext(false); 3344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 3354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Execute the XPath, and have it return the result 3364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode); 3374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 3384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return xpath.execute(xpathSupport, ctxtNode, prefixResolver); 3394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 3404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson} 341