第一种方法遍历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,如果在你用的版本中使用上述代码有错误,请仔细阅读文档