2012-01-30 89 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库。