0

I'm trying to run some xpath queries on some XML that contains namespaces. Unfortunately it's giving me a rather horrid error message as it does not understand the namespaces in the xpath query or the XML.

A sample xpath query is: //b:menuBarItem[@label='Risk']/@id

Can I configure the namespaces in JOOX (1.1.0), in a similar fashion to how I've done it here using the built in java library?

  private static NamespaceContext createXPathNameSpaceContext( final Map<String, String> namespaces ) {
    NamespaceContext nsContext = new NamespaceContext() {
      public Iterator<String> getPrefixes( String namespaceURI ) {
        return null;
      }
      public String getPrefix( String namespaceURI ) {
        return null;
      }
      public String getNamespaceURI( String prefix ) {
        if ( namespaces.containsKey( prefix ) ) {
          return namespaces.get( prefix );
        } else {
          return XMLConstants.NULL_NS_URI;
        }
      }
    };
    return nsContext;
  }

I'm invoking JOOX with the following code.

import static org.joox.JOOX.$;

private void extractResponseData( Document responseXML, String xpath ) {
  String match = $( responseXML ).xpath( xpath ).get( 0 ).getNodeValue();
  // .. etc..
}

The obvious thing that stands out is that I have not registered the namespaces, but I couldn't see how to. I suspect I am being rather short-sighted and have overlooked something in the API. The stack trace I am getting from JOOX is the following.

java.lang.RuntimeException: javax.xml.xpath.XPathExpressionException
    at org.joox.Impl.xpath(Impl.java:494)
    at org.joox.Impl.xpath(Impl.java:467)
    at org.joox.Impl.xpath(Impl.java:93)
    at end2end.http.HttpAction$XML.extractResponseData(HttpAction.java:181)
    at end2end.http.XMLPostAction.extractResponseData(XMLPostAction.java:26)
    at end2end.http.HttpAction.perform(HttpAction.java:58)
    at end2end.TestXML$UserAction.fire(TestXML.java:176)
    at end2end.TestXML$FireAction.fire(TestXML.java:148)
    at end2end.TestXML.multipleUsers(TestXML.java:119)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:702)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:894)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1219)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:336)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:65)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:88)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1198)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1122)
    at org.testng.TestNG.run(TestNG.java:1030)
    at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:215)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
Caused by: javax.xml.xpath.XPathExpressionException
    at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.compile(XPathImpl.java:402)
    at org.joox.Impl.xpath(Impl.java:486)
    at org.joox.Impl.xpath(Impl.java:467)
    at org.joox.Impl.xpath(Impl.java:93)
    at end2end.http.HttpAction$XML.extractResponseData(HttpAction.java:181)
    at end2end.http.XMLPostAction.extractResponseData(XMLPostAction.java:27)
    at end2end.http.HttpAction.perform(HttpAction.java:58)
    at end2end.TestXML$UserAction.fire(TestXML.java:176)
    at end2end.TestXML$FireAction.fire(TestXML.java:148)
    at end2end.TestXML.multipleUsers(TestXML.java:120)
    ... 24 more
Caused by: com.sun.org.apache.xpath.internal.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: 
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.errorForDOM3(XPathParser.java:653)
    at com.sun.org.apache.xpath.internal.compiler.Lexer.mapNSTokens(Lexer.java:638)
    at com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Lexer.java:265)
    at com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Lexer.java:96)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.initXPath(XPathParser.java:110)
    at com.sun.org.apache.xpath.internal.XPath.<init>(XPath.java:176)
    at com.sun.org.apache.xpath.internal.XPath.<init>(XPath.java:264)
    at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.compile(XPathImpl.java:394)
    at org.joox.Impl.xpath(Impl.java:486)
    at org.joox.Impl.xpath(Impl.java:467)
    at org.joox.Impl.xpath(Impl.java:93)
    at end2end.http.HttpAction$XML.extractResponseData(HttpAction.java:181)
    at end2end.http.XMLPostAction.extractResponseData(XMLPostAction.java:26)
    at end2end.http.HttpAction.perform(HttpAction.java:58)
    at end2end.TestXML$UserAction.fire(TestXML.java:176)
    at end2end.TestXML$FireAction.fire(TestXML.java:148)
    at end2end.TestXML.multipleUsers(TestXML.java:119)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:702)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:894)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1219)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:87)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1197)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1122)
    at org.testng.TestNG.run(TestNG.java:1030)
    at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
    ... 1 more
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
mrswadge
  • 1,659
  • 1
  • 20
  • 43

2 Answers2

1

jOOX doesn't support XML namespaces (yet). There is a pending feature request regarding this topic here:

http://code.google.com/p/joox/issues/detail?id=9

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
1

jOOX currently has support for XML namespaces (since 1.2.0), but its xpath method allows only match to elements. So this would work:

$(document).namespace("b", "http://test").xpath("//b:menuBarItem[@label='Risk']")

but this wouldn't:

$(document).namespace("b", "http://test").xpath("//b:menuBarItem[@label='Risk'/@id]")

as it would match to attributes.

Kaitsu
  • 4,094
  • 3
  • 30
  • 37