RE: XPath against a Document

Subject: RE: XPath against a Document
From: Brian Dupras <briand@xxxxxxxxxxx>
Date: Tue, 15 Feb 2000 15:11:40 -0700
> Using Xerces and Xalan;
>     given a Document (i.e. DocumentImpl) and given a String containing
> an XPath expression, I would like to apply the expression against the
> document to obtain the NodeList that matchs the expression.  Is this
> possible ?


here's are two functions I use with xalan 0.19.2 and xerces 1.0.1.  These
functions were adapted from the Xalan examples and input from Scott Boag at
Lotus, so I can't claim bragging rights.  :)


//exmaple:
//  selects all direct <datanode foo='bar'> child elements of any <data>
element in the document
Document doc = <some xml document>;
Node node = selectSingleNode(doc.getDocumentElement(),
"//data/datanode[@foo='bar']");



public static NodeList selectNodes(Node contextNode, String strXPath) throws
SAXException{
	// Since we don't have a XML Parser involved here, install some
default support
	// for things like namespaces, etc.
	// (Changed from: XPathSupportDefault xpathSupport = new
XPathSupportDefault();
	//    because XPathSupportDefault is weak in a number of areas...
perhaps
	//    XPathSupportDefault should be done away with.)
	XPathSupport xpathSupport = new XMLParserLiaisonDefault();

	// Create an object to resolve namespace prefixes. - not needed if
not using namespaces
	// Specify that XPath namespaces will be resolved from the
	// input context node's document element if it is a root node, or
else
	// the current context node (for lack of a better resolution
	// space, given the simplicity of this sample code).
	PrefixResolver prefixResolver = new com.medwired.pp.MyPrefixResolver
((contextNode.getNodeType() == Node.DOCUMENT_NODE) ?
((Document)contextNode).getDocumentElement() : contextNode);

	// Create the XPath object.
	XPath xpath = new XPath(xpathSupport, null);

	// Create a XPath parser.
	XPathProcessorImpl parser = new XPathProcessorImpl(xpathSupport);
	parser.initXPath(xpath, strXPath, prefixResolver);

	// Execute the XPath, and have it return the result
	XObject list = xpath.execute(xpathSupport, contextNode,
prefixResolver);

	// Have the XObject return it's result as a NodeSet.
	NodeList nl = list.nodeset();

	return nl;
}

public static Node selectSingleNode(Node contextNode, String strXPath)
throws SAXException{
	NodeList nl = selectNodes(contextNode, strXPath);
	return (nl.getLength() > 0) ? nl.item(0) : null;
}



////////////////////////////////////////////
//prefix resolver object referenced above
////////////////////////////////////////////


package com.medwired.pp;

import org.w3c.dom.*;
import org.xml.sax.*;
import org.apache.xerces.dom.*;
import org.apache.xerces.parsers.*;
import org.apache.xalan.xslt.*;
import org.apache.xalan.xpath.*;
import org.apache.xalan.xpath.xml.*;

public class MyPrefixResolver implements PrefixResolver
{
  /**
   * The URI for the XML namespace.
   * (Duplicate of that found in
org.apache.xalan.xpath.xml.XMLParserLiaisonDefault).
   */
  public static final String S_XMLNAMESPACEURI =
"http://www.w3.org/XML/1998/namespace";;

  /**
   * The context to resolve the prefix from, if the context
   * is not given.
   */
  Node m_context;

  /**
   * Construct a PrefixResolverDefault object.
   * @param xpathExpressionContext The context from
   * which XPath expression prefixes will be resolved.
   * Warning: This will not work correctly if xpathExpressionContext
   * is an attribute node.
   * @param xpathExpressionContext Node from which to start searching for a
   * xmlns attribute that binds a prefix to a namespace (when the namespace
   * context is not specified in the getNamespaceForPrefix call).
   */
  public MedwiredPrefixResolver(Node xpathExpressionContext){
    m_context = xpathExpressionContext;
  }

  /**
   * Given a namespace, get the corrisponding prefix.  This assumes that
   * the PrevixResolver hold's it's own namespace context, or is a namespace
   * context itself.
   * @param prefix Prefix to resolve.
   * @return Namespace that prefix resolves to, or null if prefix
   * is not bound.
   */
  public String getNamespaceForPrefix(String prefix){
    return getNamespaceForPrefix(prefix, m_context);
  }

  /**
   * Given a namespace, get the corrisponding prefix.
   * Warning: This will not work correctly if namespaceContext
   * is an attribute node.
   * @param prefix Prefix to resolve.
   * @param namespaceContext Node from which to start searching for a
   * xmlns attribute that binds a prefix to a namespace.
   * @return Namespace that prefix resolves to, or null if prefix
   * is not bound.
   */
  public String getNamespaceForPrefix(String prefix, org.w3c.dom.Node
namespaceContext) {
    Node parent = namespaceContext;
    String namespace = null;
    if(prefix.equals("xml")){
      namespace = S_XMLNAMESPACEURI;
    } else {
      int type;
      while ((null != parent) && (null == namespace) && (((type =
parent.getNodeType()) == Node.ELEMENT_NODE) || (type ==
Node.ENTITY_REFERENCE_NODE))){
        if (type == Node.ELEMENT_NODE){
          NamedNodeMap nnm = parent.getAttributes();
          for (int i = 0;  i < nnm.getLength();  i ++){
            Node attr = nnm.item(i);
            String aname = attr.getNodeName();
            boolean isPrefix = aname.startsWith("xmlns:");
            if (isPrefix || aname.equals("xmlns")){
              int index = aname.indexOf(':');
              String p = isPrefix ? aname.substring(index+1) : "";
              if (p.equals(prefix)){
                namespace = attr.getNodeValue();
                break;
              } //if
            } //if
          } //for each attrib in context Node
        } //if Node.ELEMENT_NODE
        parent = parent.getParentNode();
      } //while
    } //else (not "xml:")
    return namespace;
  } //getNamespaceForPrefix(String, Node)
} //class MedwiredPrefixResolver




> -----Original Message-----
> From: Paul Levin [mailto:plevin@xxxxxxx]
> Sent: Tuesday, February 15, 2000 12:17 PM
> To: xsl-list@xxxxxxxxxxxxxxxx
> Subject: XPath against a Document
> 
> 
> Using Xerces and Xalan;
>     given a Document (i.e. DocumentImpl) and given a String containing
> an XPath expression, I would like to apply the expression against the
> document to obtain the NodeList that matchs the expression.  Is this
> possible ?
> 


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread