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没什么太大影响。





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