tags:

views:

539

answers:

2

I've recently hit a wall with an issue with Java's native XML API (the W3C one) which at its core is that if I try to use a direct XPath expression in my document like, say, //body the XPath is evaluated as false (incorrect behaviour), however if I replace that with //*[1] it evaluates as true (desired behaviour).

I have checked numerous times and with different documents that the XML I use is valid (I'm using mainly XHTML 2.0 with rest of this system).

Since I have no idea what really causes this, here's the set of configuration options for various factory objects I'm using.

As you can see, I have lots of custom implementations of various classes related to the whole issue which I think may have something to do with the issue but I'm not sure, running around with unit tests, playing with debugger and a huge load of .println:s hasn't helped me yet.

XPath:

  • xpathfactory.setXPathFunctionResolver(myFunctionResolver)
  • xpath.setNamespaceContext(myNamespaceContext);
  • xpath.setXPathVariableResolver(myResolver);

DocumentBuilder:

(f == DocumentBuilderFactory)

  • f.f.setValidating(false);
  • f.setSchema(null);
  • f.setNamespaceAware(true);
  • f.setIgnoringComments(true);
  • f.setIgnoringElementContentWhitespace(true);
  • +features "http://xml.org/sax/features/validation", "http://apache.org/xml/features/validation/schema" and "http://apache.org/xml/features/nonvalidating/load-external-dtd" as false

(dc == DocumentBuilder)

  • dc.setEntityResolver(null);
  • dc.setErrorHandler(myErrorHandler);

Also worth mentioning is that I'm using Sun Java 5 on Windows XP.

All ideas are welcome at this point, I'm getting quite frustrated because of this issue.

Conclusion

It was a namespace issue, the problem was that I didn't declare default namespace in myNamespaceContext at all! Just by adding

else {
    return "http://www.w3.org/1999/xhtml";
}

made the thing work and now I made it so that default namespace is detected. Works like a charm! Both answers helped me to find the cause and I'd select both as preferred answer if I could.

+3  A: 

Not familiar with java, but that sounds for all the world like a namespace problem - presumably the default namespace of the document and the evaluator are different.

edit: can we see your xml doc and code? And how does //*[local-name()='body'] respond?

annakata
The xml doc is basically just a Hello World version of simplest possible XHTML document (I can't unfortunately provide actual doc since it contains disclosed material). The xpath expression you gave works just like //*[1], that is it evaluates as expected and returns true.
Esko
definitely a namespace issue then - find a way to provide that to your evaluator
annakata
+2  A: 

If it's XHTML then it'll have a namespace defined. You either remove that (not necessarily advisable), or qualify your expression thus:

//:body

(note the leading colon which qualifies the above)enter code here

Brian Agnew
Throws "com.sun.org.apache.xpath.internal.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: "
Esko