2012-01-30 100 views
1

我想解析一個DOM元素。使用Java解析XML

元素元件:

<?xml version="1.0" encoding="UTF-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom"> 
    <id>http://X/feed2</id> 
    <title>Sample Feed</title> 
    <entry> 
    <id>http://X/feed2/104</id> 
    <title>New Title</title> 
    </entry> 
</feed> 

我試圖取以下條目:

<entry> 
    <id>http://top.cs.vt.edu/libx2/[email protected]/feed2/104</id> 
    <title>New Title</title> 
</entry> 

我通過使用XPath解析XML:

「/原子:進料/ atom:entry [atom:id = \「http:// X/feed2/104 \」]「

但是,當我試圖解析Dom時出現異常元件。有人可以建議一個簡單的方法來實現這個在Java?

請參閱我的全碼:

public static parseXml() { 
     String externalEntryIdUrl = "http://theta.cs.vt.edu/~rupen/thirtylibapps/137"; 
     String externalFeedUrl = StringUtils.substringBeforeLast(externalEntryIdUrl, "/"); 
     try { 
      URL url = new URL(externalFeedUrl); 
      InputStream externalXml = new BufferedInputStream(url.openStream()); 
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
      DocumentBuilder db = dbf.newDocumentBuilder(); 
      Document doc = db.parse(externalXml); 
      Element externalFeed = doc.getDocumentElement(); 
      String atomNameSpace = "xmlns:atom=\"http://www.w3.org/2005/Atom\""; 
      String entryIdPath = String.format("//%s:entry[%s:id=%s]", atomNameSpace, atomNameSpace, externalEntryIdUrl); 
      Element externalEntry = (Element) XPathSupport.evalNode(entryIdPath, externalFeed); 
     } catch (Exception ex) { 
      // Throw exception 
     } 
    } 

static synchronized Node evalNode(String xpathExpr, Node node) { 
    NodeList result = evalNodeSet(xpathExpr, node); 
    if (result.getLength() > 1) 
     throw new Error ("More than one node for:" + xpathExpr); 
    else if (result.getLength() == 1) 
     return result.item(0); 
    else 
     return null; 
} 

static synchronized NodeList evalNodeSet(String xpathExpr, Node node) { 
     try { 
       static XPath xpath = factory.newXPath(); 
       xpath.setNamespaceContext(context); 

       static NamespaceContext context = new NamespaceContext() { 
        private Map<String, String> prefix2URI = new HashMap<String, String>(); 
        { 
         prefix2URI.put("libx", "http://libx.org/xml/libx2"); 
         prefix2URI.put("atom", "http://www.w3.org/2005/Atom"); 
        } 
       }; 

      XPathExpression expr = xpath.compile(xpathExpr); 
      Object result = expr.evaluate(node, XPathConstants.NODESET); 
      return (NodeList)result; 
     } catch (XPathExpressionException xpee) { 
      throw new Error ("An xpath expression exception: " + xpee); 
     } 
    } 

重度:>> java.lang.Error的:XPath表達式例外:javax.xml.xpath.XPathExpressionException

+1

*「我得到一個異常」*這是'TooManyKittensException'嗎? Desex湯姆貓。還有別的嗎?也許你可能會與我們分享它(即複製/粘貼)。 – 2012-01-30 05:50:43

+1

你在Java代碼中將名稱空間的前綴'atom'關聯(註冊了名稱空間)到名稱空間'「http://www.w3.org/2005/Atom」'嗎?你可以這樣做(推薦)或者使用類似於:'/ */* [local-name()='entry'] [* [local-name()='id'] ='http:// X/feed2/104]'' – 2012-01-30 05:53:11

回答

0

我想我在從URL中獲取XML時沒有設置名稱空間感知。

所以,

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
dbf.setNamespaceAware(true); 

這樣做解決了我的問題。如果不這樣做,在解析xml時設置XPathFactory實例的命名空間上下文(如我的示例中所示)本身不起作用。

0

你可以利用一個NamespaceContext,並完成類似下面的一個例子:

package forum9059851; 

import java.io.FileInputStream; 
import java.util.Iterator; 
import javax.xml.namespace.NamespaceContext; 
import javax.xml.xpath.*; 
import org.w3c.dom.Element; 
import org.xml.sax.InputSource; 

public class Demo { 

    public static void main(String[] args) { 
     try { 
      XPathFactory xpf = XPathFactory.newInstance(); 
      XPath xp = xpf.newXPath(); 
      xp.setNamespaceContext(new MyNamespaceContext()); 
      XPathExpression xpe = xp.compile("ns:feed/ns:entry"); 
      FileInputStream xmlStream = new FileInputStream("src/forum9059851/input.xml"); 
      InputSource xmlInput = new InputSource(xmlStream); 
      Element result = (Element) xpe.evaluate(xmlInput, XPathConstants.NODE); 
      System.out.println(result); 
     } catch (Exception ex) { 
      // Throw exception 
     } 
    } 

    private static class MyNamespaceContext implements NamespaceContext { 

     public String getNamespaceURI(String prefix) { 
      if("ns".equals(prefix)) { 
       return "http://www.w3.org/2005/Atom"; 
      } 
      return null; 
     } 

     public String getPrefix(String namespaceURI) { 
      return null; 
     } 

     public Iterator getPrefixes(String namespaceURI) { 
      return null; 
     } 

    } 

} 
0

如果你不想推倒重來,並要分析我會進數據建議使用已有的Rome庫。