Dom4j 统计子节点个数
前言 |
最近在使用dom4j对XML进行解析的过程中,遇到一些问题,笔者在这里和大家一起分享一下。
首先,说下需要的具体要求,要求用dom4j对XML进行解析,统计每个节点的所有子孙节点的个数,并添加到当前节点的count属性中。看似问题很简单,原本以为dom4j会直接提供这样的接口供我们使用,然后调用addAttribute就搞定了。把dom4j文档翻了个稀巴烂也没找个这样的接口,这时对dom4j稍稍有点失望了,连这样的接口都没有提供。看的时候倒是发现dom4j提供了这样一个接口NodeCount (),真是喜出望外,二话不说拿来就用,结果又是失望而归,该接口只能统计当前节点的第一级子节点的数量。也就是不对其孙子辈儿的节点负责任,dom4j也太不负责任了吧。
开始遍历 |
不过有了NodeCount(),想来完成任务也不是什么难事。首先,当前节点的子节点个数不就是等于它的子节点的子节点的。。。。。。的个数总和吗,想来肯定是要递归了。所有先写了个递归遍历所有节点的算法。
public void getNodeCount(Element element)
{
for(int i = 0; i < element.nodeCount(); i++) {
Node node = element.node(i);
if(node instanceof Element) {
Element elementTemp = (Element) Node;
getNodeCount(elementTemp);
}
}
}
下面就是工作的重点了,现在可以对每个element进行遍历了,那么开始统计子节点的个数。
开始统计 |
public int getNodeCount(Element element) {
int nodeCount = 0;
for(int i = 0; i < element.nodeCount(); i++) {
Node node = element.node(i);
if(node instanceof Element) {
int nodeCountI = 0;
Element elementTemp = (Element) Node;
if(elementTemp.nodeCount <= 0) nodeCountI = 0;
nodeCount = nodeCountI + getNodeCount(elementTemp);
}
}
nodeCount = nodeCountI + element.nodeCount();
Element.addAttribute(“count”, nodeCount + “”);
Return nodeCount;
}
至此用dom4j统计节点的所有子节点个数就完成了。
学习dom4j操作XML
Dom4j入门指南(1)
XML |
首先你要做的就是分析XML的document对象出来,这对于dom4j来说简直就是小菜一碟,看招
package com.mgoann.dom4j;
import java.net.MalformedURLException;
import java.net.URL;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
public class Mydom4j {
public static void main(String[] args) {
try {
new Mydom4j().parse(new URL("http://www.w3school.com.cn/example/xmle/note.xml"));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
}
public Document parse(URL url) throws DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(url);
return document;
}
}
在这我说几句,要想使用好dom4j必须要对XML结构很熟悉,对W3C规定的XML标准有一定的了解,这里可以参考http://www.w3school.com.cn/x.asp,这个站点还算不错,对W3C提出的一些基础标准做一个系统的了解。
上面这段代码我想大家都能看懂,就是从一个url地址去读取document对象出来,至于怎么出来这不是我们所关心的,而我们应当把握dom4j是怎么封装的XML,正确的说应该是dom4j对规范的一个实现。Document在dom4j使用中至始至终一直都会出现,在这里你应该猜的差不多了,没错document就是代表XML的实体,它里面封装了所有XML信息,当我们取的时候就应当去里边去取。
遍历 |
要对document进行分析,就免不了对它进行遍历,由于dom4j采用java中的集合框架来实现,所有你会发现,遍历document就像遍历一个集合一样简单。你可以通过多种不同方法来返回一个标准Collections中的Iterator接口,而剩下的工作,我想你自己也应该清楚了吧,看招
public void bar(Document document) {
Element root = document.getRootElement();
for(Iterator it = root.elementIterator(); it.hasNext();) {
Element element = (Element) it.next();
String content = element.asXML();
System.out.println(content);
}
}
上面代码中出现了Element对象,这个Element类在整个dom4j中的地位也是举足轻重的,其他也是dom4j标准的一个实现。每个Element对象对应的就是一组XML标签。Dom4j中任何工作都是从RootElement开始的,rootelement就是整个XML的根元素,通过对根元素的分析可以得到整个XML中的任何一个元素。
而上面的方法就是从rootelement开始遍历整个XML,找出每一个elment,也就是每一组XML标签。下面该做什么事情,我想你应该迫不及待了吧。标签都有了,那标签里的东西还不是手到擒来吗(嘿嘿。。。。)。
以上输出结果是:
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
Dom4j入门指南(2)
XPath |
XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。
XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 同时被构建于 XPath 表达之上。
因此,对 XPath 的理解是很多高级 XML 应用的基础。
下面让我们来看看dom4j对Xpath标准是怎样实现的。在dom4j中,xpath表达式可以进行描述整个Document或是任何的Node(节点),其中包括Attribute(属性)、Element。而这个功能强大而复杂的xpath标准,在dom4j中你只需要一行代码就搞定。看到这里你是不是开始心痒痒了,呵呵,不急,下面咋们来练练,看招
为了能够让大家对xpath有个清楚的认识,我从网上找了个比较复杂的xml来做示例。下面是xml原文
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<template>
<do type="options" label="Back">
<prev/>
</do>
</template>
<card id="JY">
<onevent type="onenterbackward">
<prev/>
</onevent>
<do type="accept">
<go href="#display_fav"/>
</do>
<p> Pick your fav Book:
<select name="fav" title="Stooges">
<option value="Xiao">Xiao ao jiang hu</option>
<option value="She">She diao ying xiong</option>
<option value="Lu">Lu ding ji</option>
<option value="Shen">Shen diao xia lv</option>
</select>
</p>
</card>
</wml>
我把它放到了D盘下,命名为example.xml。以下是代码:
package com.mgoann.dom4j;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
public class Mydom4j {
public static void main(String[] args) {
try {
Mydom4j dom = new Mydom4j();
Document doc = dom.parse(new File("d:/example.xml"));
dom.barXpath(doc);
} catch (DocumentException e) {
e.printStackTrace();
}
}
public Document parse(File file) throws DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(file);
return document;
}
public void barXpath(Document document) {
List selectNodes = document.selectNodes( "/wml/card/p/select/option" );
for(Iterator it = selectNodes.iterator(); it.hasNext();) {
print((Element)it.next());
}
Node node = document.selectSingleNode( "/wml/card/p/select/option" );
print(node);
String value = node.valueOf( "@value" );
print(value);
}
public void print(Node node) {
System.out.println("================================");
System.out.println(node.asXML());
}
public void print(String str) {
System.out.println("================================");
System.out.println(str);
}
}
以上程序输出结果:
================================
<option value="Xiao">Xiao ao jiang hu</option>
================================
<option value="She">She diao ying xiong</option>
================================
<option value="Lu">Lu ding ji</option>
================================
<option value="Shen">Shen diao xia lv</option>
================================
<option value="Xiao">Xiao ao jiang hu</option>
Xiao
到现在大家应该对dom4j的xpath实现有个简单的认识了吧。
Dom4j入门指南(3)
快速遍历 |
如果你处理的XML文件很大,这个时候建议你最好使用dom4j提供的快速遍历方法,这个可以满足你对性能的需求,因为dom4j快速遍历不会为每层循环都创建一个Iterator对象。是不是说的云里雾里的,其实我也晕了,不怕,咋来动个手就明白了。
public void treeWalk(Document document) {
treeWalk( document.getRootElement() );
}
public void treeWalk(Element element) {
for ( int i = 0, size = element.nodeCount(); i < size; i++ ) {
Node node = element.node(i);
if ( node instanceof Element ) {
treeWalk( (Element) node );
}
else {
// do something....
}
}
}
Node node = element.node(i);关键是这一句,我们直接通过element下标就可以遍历节点,而避免了为此创建Iterator对象,这就节省了大量遍历时间和资源。是不是很灵活,嚎。。。(板砖)
使用dom4j可以很轻松的完成String到document的互转。
Document转String:
Document document = …;
String text = document.asXML();
String转Document:
String text = “<person><name>James</name></person>”;
Document document = DocumentHelper.parseText(text);
Dom4j使用起来很简单,可以处理XML、XPath、XSLT,它是一种使用了java集合框架的java平台,对DOM、SAX和JAXP也是完全支持。
目前dom4j出到了2.0版本,官方文档只有1.6.1版本的,不过对于使用dom4j没什么太大影响。