code: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements. See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership. The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the  "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  import javax.xml.namespace.*;
  import javax.xml.xpath.*;
  import java.util.Iterator;
  
  /**
   * JAXP 1.3 XPath API sample.
   * 
   * This sample demonstrates the use of NamespaceContext, XPathFunctionResolver
   * and XPathVariableResolver. The evaluated XPath expression ("ex:addFunc(2, 3) + $xyz")
   * contains an extension function and a variable reference. The extension function
   * and variable are evaluated using our customized XPathFunctionResolver and
   * XPathVariableResolver respectively. A NamespaceContext implementation is also
   * needed to map the prefix in the extension function to a valid namespace uri. 
   */
  public class XPathResolver
  {
      /**
       * The XPath expression to evaluate, which contains an extension
       * function and a variable reference.
       */
      private static final String EXPR = "ex:addFunc(2, 3) + $xyz";
      
      /**
       * The NamespaceContext implementation is used to map the prefix "ex"
       * to the namespace uri "http://ex.com".
       */
      public static class MyNamespaceContext implements NamespaceContext
      {
          public String getNamespaceURI(String prefix)
          {
              if (prefix == null)
                throw new IllegalArgumentException("The prefix cannot be null.");
              
              if (prefix.equals("ex"))
                  return "http://ex.com";
              else
                  return null;
          }
          
          public String getPrefix(String namespace)
          {
              if (namespace == null)
                throw new IllegalArgumentException("The namespace uri cannot be null.");
              if (namespace.equals("http://ex.com"))
                return "ex";
              else
                return null;
          }
  
          public Iterator getPrefixes(String namespace)
          {
              return null;
          }
      }
      
      /**
       * The XPathFunctionResolver implementation is used to evaluate
       * the extension function "ex:addFunc(2, 3)".
       */
      public static class MyFunctionResolver implements XPathFunctionResolver
      {
      	/**
      	 * This method returns a customized XPathFunction implementation
      	 * for the extension function "ex:addFunc()".
      	 */
      	public XPathFunction resolveFunction(QName fname, int arity)
      	{
      	  if (fname == null)
      	    throw new NullPointerException("The function name cannot be null.");
      	  
      	  // We only recognize one function, i.e. ex:addFunc().
      	  if (fname.equals(new QName("http://ex.com", "addFunc", "ex")))
      	    /** 
      	     * Return a customized implementation of XPathFunction. We need
      	     * to implement the evaluate(List) method.
      	     */
      	    return new XPathFunction() {
      	      /**
      	       * The actual implementation of the extension function.
      	       * Just cast two arguments to Double and add them together.
      	       */
      	      public Object evaluate(java.util.List args) {
      	        if (args.size() == 2) {
      	          Double arg1 = (Double)args.get(0);
      	          Double arg2 = (Double)args.get(1);
      	          return new Double(arg1.doubleValue() + arg2.doubleValue());
      	        }
      	        else
      	          return null;
      	      }
      	    };
      	  else
      	    return null;
      	}
      }
      
      /**
       * Our own implementation of XPathVariableResolver, which resolves the 
       * variable "xyz" to a double value 4.0.
       */
      public static class MyVariableResolver implements XPathVariableResolver
      {
        public Object resolveVariable(QName varName)
        {
          if (varName == null)
            throw new NullPointerException("The variable name cannot be null.");
          
          if (varName.equals(new QName("", "xyz")))
            return new Double(4.0);
          else
            return null;        	
        }
      }
  
      
      public static void main(String[] args)
      {    	        
          XPathFactory factory = XPathFactory.newInstance();
          XPath xpath = factory.newXPath();
          // Set the NamespaceContext
          xpath.setNamespaceContext(new MyNamespaceContext());
          // Set the function resolver
          xpath.setXPathFunctionResolver(new MyFunctionResolver());
          // Set the variable resolver
          xpath.setXPathVariableResolver(new MyVariableResolver());
          
          Object result = null;
          try {
            result = xpath.evaluate(EXPR, (Object)null, XPathConstants.NUMBER);
          }
          catch (Exception e) {
              e.printStackTrace();
          }
          
          // The evaluation result is 9.0.
          System.out.println("The evaluation result: " + result);
      }
      
  }
  