Hi,

I'm having a problem using the org.apache.xpath.domapi.XPathEvaluatorImpl with namespace prefixes in my xpath expression.
An example xpath I have is "dyn:map(., '.')" which dosent do much but it relies on the exslt extensions.

I have made a custom namespace resolver which maps the standard exslt prefixes to their namespaces and a test program as follows:




import java.io.StringReader;
import org.xml.sax.InputSource;

import org.w3c.dom.Node;
import org.w3c.dom.Document;
import org.w3c.dom.xpath.XPathResult;
import org.w3c.dom.xpath.XPathException;
import org.w3c.dom.xpath.XPathEvaluator;
import org.w3c.dom.xpath.XPathExpression;
import org.w3c.dom.xpath.XPathNSResolver;

import javax.xml.parsers.DocumentBuilderFactory;

// Need to extend org.apache.xpath.domapi.XPathNSResolverImpl to prevent class casts in the xpath evaluator
public class XPathTest extends org.apache.xpath.domapi.XPathNSResolverImpl implements XPathNSResolver {
public static void main(String[] args) throws Exception {
org.apache.xalan.Version.main(null);
XPathEvaluator xpathEvaluator = new org.apache.xpath.domapi.XPathEvaluatorImpl();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
Document doc = documentBuilderFactory.newDocumentBuilder().parse(new InputSource(new StringReader("<foo/>")));
try {
System.out.println("Trying with no namespace resolver");
Object result = xpathEvaluator.evaluate("dyn:map(., '.')", doc, null, XPathResult.ANY_TYPE, null);
System.out.println(result);
}
catch(Exception e) {
System.out.println("I expected this to fail");
e.printStackTrace();
}

try {
System.out.println();
System.out.println("Trying with my namespace resolver");
Object result = xpathEvaluator.evaluate("dyn:map(., '.')", doc, new XPathTest(), XPathResult.ANY_TYPE, null);
System.out.println(result);
}
catch(Exception e) {
System.out.println("I cant work out why this failed");
e.printStackTrace();
}
}
private XPathTest() {
super(null);
}
// these methods are the ones called by the xpath engine
public String getNamespaceForPrefix(String prefix) {
return lookupNamespaceURI(prefix);
}
public String getNamespaceForPrefix(String prefix, Node namespaceContext) {
return lookupNamespaceURI(prefix);
}
// do the actual namespace lookup
public String lookupNamespaceURI(String prefix) {
System.out.println("lookupNamespaceURI " + prefix);
if(prefix.equals("date")) {
return "http://exslt.org/dates-and-times";;
}
else if(prefix.equals("dyn")) {
return "http://exslt.org/dynamic";;
}
else if(prefix.equals("exsl")) {
return "http://exslt.org/common";;
}
else if(prefix.equals("func")) {
return "http://exslt.org/functions";;
}
else if(prefix.equals("math")) {
return "http://exslt.org/math";;
}
else if(prefix.equals("regexp")) {
return "http://exslt.org/regular-expressions";;
}
else if(prefix.equals("set")) {
return "http://exslt.org/sets";;
}
else if(prefix.equals("str")) {
return "http://exslt.org/strings";;
}
else {
return null;
}
}
}



I try to evaluate the xpath with no name space resolver and it fails as expected:


Trying with no namespace resolver
I expected this to fail
org.w3c.dom.DOMException: Unable to resolve prefix with null prefix resolver.
at org.apache.xpath.domapi.XPathEvaluatorImpl$DummyPrefixResolver.getNamespaceForPrefix(XPathEvaluatorImpl.java:115)
at org.apache.xpath.domapi.XPathEvaluatorImpl$DummyPrefixResolver.getNamespaceForPrefix(XPathEvaluatorImpl.java:125)
at org.apache.xpath.compiler.Lexer.mapNSTokens(Lexer.java:625)
at org.apache.xpath.compiler.Lexer.tokenize(Lexer.java:303)
at org.apache.xpath.compiler.Lexer.tokenize(Lexer.java:134)
at org.apache.xpath.compiler.XPathParser.initXPath(XPathParser.java:155)
at org.apache.xpath.XPath.<init>(XPath.java:202)
at org.apache.xpath.XPath.<init>(XPath.java:238)
at org.apache.xpath.domapi.XPathEvaluatorImpl.createExpression(XPathEvaluatorImpl.java:199)
at org.apache.xpath.domapi.XPathEvaluatorImpl.evaluate(XPathEvaluatorImpl.java:291)
at XPathTest.main(XPathTest.java:30)


Then with my namespace resolver:

Trying with my namespace resolver
lookupNamespaceURI dyn
I cant work out why this failed
org.w3c.dom.xpath.XPathException: Unknown error in XPath
at org.apache.xpath.domapi.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:208)
at org.apache.xpath.domapi.XPathEvaluatorImpl.evaluate(XPathEvaluatorImpl.java:293)
at XPathTest.main(XPathTest.java:41)


In my actual usage rather then the test above I have also got the following probably related exception:

org.w3c.dom.xpath.XPathException: java.lang.NoSuchMethodException: For extension function, could not find method org.apache.xpath.axes.WalkingIterator.map([ExpressionContext,] #STRING).
at org.apache.xpath.domapi.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:208)
at org.apache.xpath.domapi.XPathEvaluatorImpl.evaluate(XPathEvaluatorImpl.java:293)

Im guessing the xpath engine is looking in the wrong class for the map method.


Do I need to do any more to set up the org.apache.xpath.domapi.XPathEvaluatorImpl object before calling the evaluate method with the correct namespace resolver?

Thanks for any help in advance,

From Richard.


Reply via email to