Dom4j 解析Atom 文档

第一种方法遍历Dom树,不使用xpath

Element re=document.getRootElement();
List es=re.elements("entry");

for(int i=0;i<es.size();i++){
    Element currentItem=(Element)es.get(i);
    Element title=(Element)currentItem.elements("title").get(0);
    Element link=(Element)currentItem.elements("link").get(0);
    Element updated=(Element)currentItem.elements("updated").get(0);
    Element content=(Element)currentItem.elements("content").get(0);
}

document是完整的org.dom4j.Document文档对象,本文要说的是第二种,使用xpath,如果是rss,可以简单的使用类似下面的查询表达式

List<Node> list = document.selectNodes("//item");
for (Iterator iter = list.iterator(); iter.hasNext(); ) {
    Node currentItem=(Node)iter.next();
    Element title=(Element)currentItem.selectSingleNode("./title");
    Element link=(Element)currentItem.selectSingleNode("./link");
    Element pubDate=(Element)currentItem.selectSingleNode("./pubDate");
    Element description=(Element)currentItem.selectSingleNode("./description");
}

如果Atom中也这样写,会取不得什么值,打印list.size()会发现是0,因为Atom有默认的名称空间:

xmlns="http://www.w3.org/2005/Atom"

所以需要在解析时先创建名称空间,或者在使用xpath的元素上注册或添加名称空间:

Map uris = new HashMap();
uris.put("atom", "http://www.w3.org/2005/Atom");

XPath xpath = document.createXPath("/atom:feed/atom:entry");
xpath.setNamespaceURIs(uris);
List<Node> list = xpath.selectNodes(document);
for (Iterator iter = list.iterator(); iter.hasNext(); ) {
    Element currentItem=(Element)iter.next();
    Element title=(Element)currentItem.selectSingleNode("./title");
    Element link=(Element)currentItem.selectSingleNode("./link");
    Element pubDate=(Element)currentItem.selectSingleNode("./updated");
    Element description=(Element)currentItem.selectSingleNode("./content");
}

上面的代码在用xpath查询entry时使用Atom 名称空间,按理上这时没问题,可在取Element的值时控制台抛异常:java.lang.NullPointerException,在遍历时找到的Element无法使用,是不是少了名称空间前缀:atom,

Element title=(Element)currentItem.selectSingleNode("./atom:title");
Element link=(Element)currentItem.selectSingleNode("./atom:link");
Element updated=(Element)currentItem.selectSingleNode("./atom:updated");
Element content=(Element)currentItem.selectSingleNode("./atom:content");

奇怪了,还是抛异常:XPath expression uses unbound namespace prefix atom,原来在xpath查询entry时绑定的名称空间仅在entry时可用,下面就容易了,看一看文档Element或Node有没有增加名称空间的方法,还真有一个

public Element addNamespace(String prefix,
                            String uri)

currentItem.addNamespace("atom", "http://www.w3.org/2005/Atom");

加上此行后,代码跑起来了。我google发现也可以在文档根元素上绑定,这样在后续使用xpath时无需再添加名称空间,至于是否可行没实验过。


本文使用的dom4j是1.6.1,如果在你用的版本中使用上述代码有错误,请仔细阅读文档


你可能感兴趣的:(java,xml,dom4j,dom,ATOM)