public synchronized TemplateModel executeQuery(Object context, String xpathQuery)
     throws TemplateModelException {
   if (!(context instanceof Node)) {
     if (context != null) {
       if (isNodeList(context)) {
         int cnt = ((List) context).size();
         if (cnt != 0) {
           throw new TemplateModelException(
               "Cannot perform an XPath query against a node set of "
                   + cnt
                   + " nodes. Expecting a single node."
                   + ERRMSG_RECOMMEND_JAXEN);
         } else {
           throw new TemplateModelException(ERRMSG_EMPTY_NODE_SET);
         }
       } else {
         throw new TemplateModelException(
             "Cannot perform an XPath query against a "
                 + context.getClass().getName()
                 + ". Expecting a single org.w3c.dom.Node.");
       }
     } else {
       throw new TemplateModelException(ERRMSG_EMPTY_NODE_SET);
     }
   }
   Node node = (Node) context;
   try {
     XPath xpath = new XPath(xpathQuery, null, customPrefixResolver, XPath.SELECT, null);
     int ctxtNode = xpathContext.getDTMHandleFromNode(node);
     XObject xresult = xpath.execute(xpathContext, ctxtNode, customPrefixResolver);
     if (xresult instanceof XNodeSet) {
       NodeListModel result = new NodeListModel(node);
       result.xpathSupport = this;
       NodeIterator nodeIterator = xresult.nodeset();
       Node n;
       do {
         n = nodeIterator.nextNode();
         if (n != null) {
           result.add(n);
         }
       } while (n != null);
       return result.size() == 1 ? result.get(0) : result;
     }
     if (xresult instanceof XBoolean) {
       return ((XBoolean) xresult).bool() ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
     }
     if (xresult instanceof XNull) {
       return null;
     }
     if (xresult instanceof XString) {
       return new SimpleScalar(xresult.toString());
     }
     if (xresult instanceof XNumber) {
       return new SimpleNumber(new Double(((XNumber) xresult).num()));
     }
     throw new TemplateModelException("Cannot deal with type: " + xresult.getClass().getName());
   } catch (TransformerException te) {
     throw new TemplateModelException(te);
   }
 }
  /**
   * Use an XPath string to select a nodelist. XPath namespace prefixes are resolved from the
   * namespaceNode.
   *
   * @param contextNode The node to start searching from.
   * @param xpathnode
   * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
   * @return A NodeIterator, should never be null.
   * @throws TransformerException
   */
  public static NodeIterator selectNodeIterator(
      Node contextNode, Node xpathnode, Node namespaceNode) throws TransformerException {

    // Execute the XPath, and have it return the result
    XObject list = eval(contextNode, xpathnode, namespaceNode);

    // Have the XObject return its result as a NodeSetDTM.
    return list.nodeset();
  }