2013-06-03 43 views
3

我有XML文件andi'm試圖使用XPath來獲取所有的值它的路徑,但它不會產生像的命名空間值由XML文件生成的處理路徑:錯誤使用XPath

//rss/channel/item/yweather:forecast/@low 

OR

//rss/channel/yweather:wind/text() 

代碼: 方法使用:

public class XmlSource{ 
    private XPathFactory factory = XPathFactory.newInstance(); 
    private XPath xpath = factory.newXPath(); 

    public Map<String, Object> update(String XML) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException, TransformerException{ 

      XmlSource xml = new XmlSource(); 
      Map<String, Object> result = new HashMap<String, Object>(); 

      Document doc = convert(XML); // converting the String to a document (tested and working efficiently) 
      xml.doc = doc; 
      xpath.setNamespaceContext(new NamespaceResolver(xml.doc)); 

      ArrayList<String> paths = xml.getAllPaths(); // to get the listed above paths (tested and working efficiently) 

       for(int i=0; i < paths.size() ; i++){ 
       result.put(paths.get(i), getValue(paths.get(i), xml.doc)); 
       } 
      return result; 

     } 
    public String getValue(String path, Document doc) throws TransformerException, IOException, ParserConfigurationException, SAXException { 


       this.doc = doc; 


      try { 

       XPathExpression expr = xpath.compile(path); 
       Object result = expr.evaluate(this.doc, XPathConstants.STRING); 

       return result.toString(); 
      } catch (XPathExpressionException ex) { 
       return null; 
      } 
     } 

} 

的NamespaceResolver類:

import java.util.Iterator; 
import javax.xml.XMLConstants; 
import javax.xml.namespace.NamespaceContext; 
import org.w3c.dom.Document; 

public class NamespaceResolver implements NamespaceContext { 
    private Document sourceDocument; 

    public NamespaceResolver(Document document) { 
     sourceDocument = document; 
    } 

    @Override 
    public String getNamespaceURI(String prefix) { 
     if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) { 
      return sourceDocument.lookupNamespaceURI(null); 
     } else { 
      return sourceDocument.lookupNamespaceURI(prefix); 
     } 
    } 

    @Override 
    public String getPrefix(String namespaceURI) { 
     return sourceDocument.lookupPrefix(namespaceURI); 
    } 

    @Override 
    public Iterator<String> getPrefixes(String namespaceURI) { 
     return null; 
    } 
} 

拋出的異常:

at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
     at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30) 
     at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
    --------------- linked to ------------------ 
    javax.xml.xpath.XPathExpressionException 
     org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
    //rss/channel/item/yweather:condition/@text 
    //rss/channel/item/yweather:forecast/@code 
    //rss/channel/item/yweather:forecast/@date 
    //rss/channel/item/yweather:forecast/@day 
    //rss/channel/item/yweather:forecast/@high 
    //rss/channel/item/yweather:forecast/@low 
    //rss/channel/item/yweather:forecast/@text 
    //rss/channel/item/yweather:forecast/@code 
    //rss/channel/item/yweather:forecast/@date 
    //rss/channel/item/yweather:forecast/@day 
    //rss/channel/item/yweather:forecast/@high 
    //rss/channel/item/yweather:forecast/@low 
    //rss/channel/item/yweather:forecast/@text 
    --------------- linked to ------------------ 
    javax.xml.xpath.XPathExpressionException 
    dAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
     at java.lang.reflect.Method.invoke(Unknown Source) 
     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
     at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
     at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) 
     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) 
     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
     at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30) 
     at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
    Caused by: com.sun.org.apache.xpath.internal.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: yweather 
     at com.sun.org.apache.xpath.internal.compiler.XPathParser.errorForDOM3(Unknown Source) 
     at com.sun.org.apache.xpath.internal.compiler.Lexer.mapNSTokens(Unknown Source) 
     at com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Unknown Source) 
     at com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Unknown Source) 
     at com.sun.org.apache.xpath.internal.compiler.XPathParser.initXPath(Unknown Source) 
     at com.sun.org.apache.xpath.internal.XPath.<init>(Unknown Source) 
     at com.sun.org.apache.xpath.internal.XPath.<init>(Unknown Source) 
     ... 30 more 
    com.sun.org.apache.xpath.internal.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: yweather 
     at com.sun.org.apache.xpath.internal.compiler.XPathParser.errorForDOM3(Unknown Source) 
     at com.sun.org.apache.xpath.internal.compiler.Lexer.mapNSTokens(Unknown Source) 
     at com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Unknown Source) 
     at com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Unknown Source) 
     at com.sun.org.apache.xpath.internal.compiler.XPathParser.initXPath(Unknown Source) 
     at com.sun.org.apache.xpath.internal.XPath.<init>(Unknown Source) 
     at com.sun.org.apache.xpath.internal.XPath.<init>(Unknown Source) 
     at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.compile(Unknown Source) 
     at com.nc.inotify.dp.xml.impl.XmlSource.getValue(XmlSource.java:180) 
     at com.nc.inotify.dp.xml.impl.XmlSource.update(XmlSource.java:284) 
     at com.nc.inotify.dp.xml.impl.XmlSourceFactory.getSource(XmlSourceFactory.java:155) 
     at com.nc.inotify.dp.xml.junit.TXmlSourceFactory.tesGetSource(TXmlSourceFactory.java:139) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
     at java.lang.reflect.Method.invoke(Unknown Source) 
     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
     at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
     at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) 
     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) 
     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
     at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30) 
     at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
    --------------- linked to ------------------ 
    javax.xml.xpath.XPathExpressionException 
     at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.compile(Unknown Source) 
     at com.nc.inotify.dp.xml.impl.XmlSource.getValue(XmlSource.java:180) 
     at com.nc.inotify.dp.xml.impl.XmlSource.update(XmlSource.java:284) 
     at com.nc.inotify.dp.xml.impl.XmlSourceFactory.getSource(XmlSourceFactory.java:155) 
     at com.nc.inotify.dp.xml.junit.TXmlSourceFactory.tesGetSource(TXmlSourceFactory.java:139) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
     at java.lang.reflect.Method.invoke(Unknown Source) 
     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
     at 
    //rss/channel/item/yweather:forecast/text() 
    //rss/channel/item/guid/text() 
    DONE 
+1

我看到你捕捉到可能的異常並在更新函數中返回null。如果你只是拋出異常(我想你可能會得到一個)併發布結果,會發生什麼? – ljgw

+0

我已經做了這個,但它引發了像百萬個例外,所以,我讓它返回null因爲這個,我會再次拋出並編輯結果 –

+0

我編輯了一部分拋出異常的問題,請看看 –

回答

10

我能夠通過使用DocumentBuilderFactory,這不是名稱空間感知的重現你的錯誤。

假設你的轉換方法看起來是這樣的:

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); 
Document doc = dBuilder.parse(inputSource); 

那麼你可以試試這個:

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); 
dbFactory.setNamespaceAware(true); 
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); 
Document doc = dBuilder.parse(inputSource); 

這可以解釋爲什麼NamespaceResolver無法得到的namespaceURI。

+2

它幫助我解決了問題! –