19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License.
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License.
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: XPathAPI.java 524807 2007-04-02 15:51:43Z zongaro $
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xpath;
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport javax.xml.transform.TransformerException;
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.PrefixResolver;
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.PrefixResolverDefault;
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.objects.XObject;
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.Document;
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.Node;
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.NodeList;
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.traversal.NodeIterator;
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/**
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The methods in this class are convenience methods into the
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * low-level XPath API.
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * These functions tend to be a little slow, since a number of objects must be
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * created for each evaluation.  A faster way is to precompile the
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * XPaths using the low-level API, and then just use the XPaths
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * over and over.
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * NOTE: In particular, each call to this method will create a new
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * XPathContext, a new DTMManager... and thus a new DTM. That's very
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * safe, since it guarantees that you're always processing against a
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * fully up-to-date view of your document. But it's also portentially
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * very expensive, since you're rebuilding the DTM every time. You should
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * consider using an instance of CachedXPathAPI rather than these static
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * methods.
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @see <a href="http://www.w3.org/TR/xpath">XPath Specification</a>
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * */
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic class XPathAPI
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Use an XPath string to select a single node. XPath namespace
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * prefixes are resolved from the context node, which may not
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * be what you want (see the next method).
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param contextNode The node to start searching from.
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param str A valid XPath string.
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The first node found that matches the XPath, or null.
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static Node selectSingleNode(Node contextNode, String str)
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return selectSingleNode(contextNode, str, contextNode);
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Use an XPath string to select a single node.
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * XPath namespace prefixes are resolved from the namespaceNode.
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param contextNode The node to start searching from.
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param str A valid XPath string.
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The first node found that matches the XPath, or null.
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static Node selectSingleNode(
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          Node contextNode, String str, Node namespaceNode)
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws TransformerException
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Have the XObject return its result as a NodeSetDTM.
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    NodeIterator nl = selectNodeIterator(contextNode, str, namespaceNode);
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Return the first node, or null
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return nl.nextNode();
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  Use an XPath string to select a nodelist.
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  XPath namespace prefixes are resolved from the contextNode.
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param contextNode The node to start searching from.
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param str A valid XPath string.
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @return A NodeIterator, should never be null.
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static NodeIterator selectNodeIterator(Node contextNode, String str)
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return selectNodeIterator(contextNode, str, contextNode);
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  Use an XPath string to select a nodelist.
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  XPath namespace prefixes are resolved from the namespaceNode.
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param contextNode The node to start searching from.
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param str A valid XPath string.
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @return A NodeIterator, should never be null.
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static NodeIterator selectNodeIterator(
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          Node contextNode, String str, Node namespaceNode)
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws TransformerException
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Execute the XPath, and have it return the result
1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XObject list = eval(contextNode, str, namespaceNode);
1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Have the XObject return its result as a NodeSetDTM.
1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return list.nodeset();
1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  Use an XPath string to select a nodelist.
1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  XPath namespace prefixes are resolved from the contextNode.
1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param contextNode The node to start searching from.
1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param str A valid XPath string.
1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @return A NodeIterator, should never be null.
1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static NodeList selectNodeList(Node contextNode, String str)
1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return selectNodeList(contextNode, str, contextNode);
1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  Use an XPath string to select a nodelist.
1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  XPath namespace prefixes are resolved from the namespaceNode.
1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param contextNode The node to start searching from.
1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param str A valid XPath string.
1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @return A NodeIterator, should never be null.
1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static NodeList selectNodeList(
1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          Node contextNode, String str, Node namespaceNode)
1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws TransformerException
1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Execute the XPath, and have it return the result
1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XObject list = eval(contextNode, str, namespaceNode);
1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Return a NodeList.
1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return list.nodelist();
1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  Evaluate XPath string to an XObject.  Using this method,
1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  XPath namespace prefixes will be resolved from the namespaceNode.
1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param contextNode The node to start searching from.
1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param str A valid XPath string.
1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XObject
1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XNull
1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XBoolean
1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XNumber
1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XString
1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XRTreeFrag
1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static XObject eval(Node contextNode, String str)
1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return eval(contextNode, str, contextNode);
1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  Evaluate XPath string to an XObject.
1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  XPath namespace prefixes are resolved from the namespaceNode.
1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  The implementation of this is a little slow, since it creates
1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  a number of objects each time it is called.  This could be optimized
1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  to keep the same objects around, but then thread-safety issues would arise.
2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param contextNode The node to start searching from.
2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param str A valid XPath string.
2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XObject
2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XNull
2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XBoolean
2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XNumber
2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XString
2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  @see org.apache.xpath.objects.XRTreeFrag
2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static XObject eval(Node contextNode, String str, Node namespaceNode)
2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Since we don't have a XML Parser involved here, install some default support
2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // for things like namespaces, etc.
2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // (Changed from: XPathContext xpathSupport = new XPathContext();
2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //    because XPathContext is weak in a number of areas... perhaps
2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //    XPathContext should be done away with.)
2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Create an XPathContext that doesn't support pushing and popping of
2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // variable resolution scopes.  Sufficient for simple XPath 1.0 expressions.
2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XPathContext xpathSupport = new XPathContext(false);
2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Create an object to resolve namespace prefixes.
2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // XPath namespaces are resolved from the input context node's document element
2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // if it is a root node, or else the current context node (for lack of a better
2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // resolution space, given the simplicity of this sample code).
2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PrefixResolverDefault prefixResolver = new PrefixResolverDefault(
2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      (namespaceNode.getNodeType() == Node.DOCUMENT_NODE)
2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      ? ((Document) namespaceNode).getDocumentElement() : namespaceNode);
2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Create the XPath object.
2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Execute the XPath, and have it return the result
2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // return xpath.execute(xpathSupport, contextNode, prefixResolver);
2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return xpath.execute(xpathSupport, ctxtNode, prefixResolver);
2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   Evaluate XPath string to an XObject.
2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   XPath namespace prefixes are resolved from the namespaceNode.
2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   The implementation of this is a little slow, since it creates
2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   a number of objects each time it is called.  This could be optimized
2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   to keep the same objects around, but then thread-safety issues would arise.
2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @param contextNode The node to start searching from.
2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @param str A valid XPath string.
2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @param prefixResolver Will be called if the parser encounters namespace
2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *                         prefixes, to resolve the prefixes to URLs.
2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @see org.apache.xpath.objects.XObject
2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @see org.apache.xpath.objects.XNull
2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @see org.apache.xpath.objects.XBoolean
2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @see org.apache.xpath.objects.XNumber
2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @see org.apache.xpath.objects.XString
2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   @see org.apache.xpath.objects.XRTreeFrag
2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static XObject eval(
2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          Node contextNode, String str, PrefixResolver prefixResolver)
2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws TransformerException
2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Since we don't have a XML Parser involved here, install some default support
2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // for things like namespaces, etc.
2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // (Changed from: XPathContext xpathSupport = new XPathContext();
2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //    because XPathContext is weak in a number of areas... perhaps
2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //    XPathContext should be done away with.)
2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Create the XPath object.
2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Create an XPathContext that doesn't support pushing and popping of
2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // variable resolution scopes.  Sufficient for simple XPath 1.0 expressions.
2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XPathContext xpathSupport = new XPathContext(false);
2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Execute the XPath, and have it return the result
2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return xpath.execute(xpathSupport, ctxtNode, prefixResolver);
2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
289