You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by Scott Moore <Sc...@netDecide.com> on 2001/12/03 16:54:05 UTC

XPathAPI help needed

I posted this question on the Xalan Java User List, but didn't get any
responses.  I'm hoping someone here can help me.


Both Xalan 2.2.D11 and 2.2.D13 fail.

I'm trying to select a node from a DOM using the XPathAPI.selectSingleNode()
call.  Everything works fine unless the XML has namespaces and I try to
reference them in my XPath expression.

For instance, take the following sample SOAP fault:

<SOAP-ENV:Envelope
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <SOAP-ENV:Fault>
            <faultcode>Client</faultcode>
            <faultstring>The SOAP message request did not contain the
appropriate security token credentials required to execute a request on the
server.</faultstring>
            <faultactor>Server</faultactor>
            <detail>
                <e:yourfaultdetails xmlns:e="mynamespace">
                    <message>The SOAP request did not contain a valid
security token.</message>
                    <errorcode>1000000</errorcode>
                </e:yourfaultdetails>
            </detail>
        </SOAP-ENV:Fault>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


In my Java code, when I call

XPathAPI.selectSingleNode(doc,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/SOAP-ENV:Fault/faultcode");

It fails saying javax.xml.transform.TransformerException: Prefix must
resolve to a namespace: SOAP-ENV


So, I figure I need to use the selectSingleNode() API where I pass in a
namespace node as the third parameter.  BUT, FOR THE LOVE OF XALAN, WHAT IS
A NAMESPACE NODE?!  I've tried passing it the document root of the above
SOAP fault.  I've tried creating a new document with a single element with
the SOAP-ENV namespace declared and passing that element as the third
parameter.  I've even declared the namespace in an element and passed the
attribute that contains the "xmlns:SOAP-ENV" name.

Please, someone, tell me what I'm doing wrong.

Thanks,
Scott

RE: XPathAPI help needed

Posted by Paul Brown <pr...@fivesight.com>.
> [Scott.Moore at netDecide.com]
> Subject: XPathAPI help needed
> Everything works fine unless the XML has namespaces and I try to
> reference them in my XPath expression.

You have two choices:

1) You need to create a dummy prefix resolver that knows about your
namespaces; you can do this by implementing the relevant interface
(org.apache.xml.utils.PrefixResolver).

2) You can use a PrefixResolverDefault
(org.apache.xml.utils.PrefixResolverDefault) constructed for the context
node in your expression.  (It only has one constructor.)

Choice #1 is much better than choice #2 because choice #2 means that you're
dependent on the prefixes declared in the document.  Choice #1 means that
you're dependent on the URIs.

Tell you what, I'll contribute some code...  It follows:

import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Node;
import org.apache.xml.utils.PrefixResolver;

/**
 * This class implements the org.apache.xml.utils.PrefixResolver
 * interface to support execution of XPath expressions without
 * dependence on document-delcared namespace prefixes.
 */
public class StaticPrefixResolverImpl implements PrefixResolver
{

  /**
   * Runtime storage for prefixes and URIs.
   */
  private HashMap _prefixes;

  private static final String EMPTY_STRING = "";

  /**
   * The URI for the &quot;xml&quot; namespace.
   */
  public static final String S_XMLNAMESPACEURI =
    "http://www.w3.org/XML/1998/namespace";
  public static final String XML_PREFIX = "xml";

  /**
   * The URI for namespace declarations.
   */
  public static final String S_XMLNSNAMESPACEURI =
    "http://www.w3.org/2000/xmlns/";
  public static final String XMLNS_PREFIX = "xmlns";

  /**
   * Create a new StaticPrefixResolverImpl using the supplied map of
prefixes
   * and URIs.  The constructor creates a copy of the supplied map.
   *
   * @param prefixMap a map of the prefixes and URIs to be used by the
instance.
   */
  public StaticPrefixResolverImpl(Map prefixMap)
  {
    if (prefixMap != null) {
      _prefixes = new HashMap(prefixMap);
    } else {
      _prefixes = new HashMap();
    }
    _prefixes.put(XML_PREFIX,S_XMLNAMESPACEURI);
    _prefixes.put(XMLNS_PREFIX,S_XMLNSNAMESPACEURI);
  }

  /**
   * Return the base identifier for the document.
   */
  public String getBaseIdentifier()
  {
    return (String) _prefixes.get(EMPTY_STRING);
  }

  /**
   * Retrieve the URI corresponding to the supplied prefix.
   *
   * @param prefix the prefix to match to a URI.
   */
  public String getNamespaceForPrefix(String prefix)
  {
    return (String) _prefixes.get(prefix);
  }

  /**
   * Retrieve a namespace in context.  Note that this is meaningless for our
   * implementation, as the prefixes are static for the entire document and
   * independent of any local declarations.
   *
   * @param prefix the prefix to query
   * @param n the context Node (ignored)
   */
  public String getNamespaceForPrefix(String prefix, Node n)
  {
    return getNamespaceForPrefix(prefix);
  }

}

	-- Paul