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沒什麼太大影響。