Dom4j 統計子節點個數


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





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章