2012-07-02 75 views
0

我试图在一些包含命名空间的XML上运行一些xpath查询。不幸的是,它给了我一个相当可怕的错误消息,因为它不能理解xpath查询或XML中的命名空间。JOOX命名空间支持

示例XPath查询是://b:menuBarItem[@label='Risk']/@id

我可以配置的命名空间中JOOX (1.1.0),以类似的方式如何,我使用内置的Java库在这里做吗?

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; 
    } 

我用以下代码调用JOOX。

import static org.joox.JOOX.$; 

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

显而易见的是,我没有注册名称空间,但我看不出如何。我怀疑自己目光短浅,忽视了API中的某些内容。我从JOOX获得的堆栈跟踪如下。

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 

回答

0

jOOX目前拥有XML命名空间的支持(自1.2.0),但它的XPath的方法只允许匹配的元素。因此,这会工作:

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

但这并不:

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

,因为它会匹配属性。