日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

XJL:XML文件處理...

 nbtymm 2007-03-27

 

XML 技術(shù)是隨著 Java 的發(fā)展而發(fā)展起來(lái)的。在 XML 出現(xiàn)之前對(duì)于簡(jiǎn)單的數(shù)據(jù)格式通常是存儲(chǔ)在 ini 配置文件等文本文件中,復(fù)雜的格式則采用自定義的文件格式,因此對(duì)于每種文件格式都要有專門的解析程序。 XML 出現(xiàn)以后解決了這個(gè)問(wèn)題,程序面對(duì)的是有固定格式的 XML 文件,只要通過(guò)標(biāo)準(zhǔn) API 就可以進(jìn)行 XML 文件的處理。

XML 文件在案例系統(tǒng)中應(yīng)用是很廣泛的,比如 ClientConfig.xml 、 ServerConfig.xml 文件就是使用 XML 文件來(lái)做配置文件的,元數(shù)據(jù)文件以及元數(shù)據(jù)加載器更是離不開(kāi) XML 。因此本章將系統(tǒng)講解一下 XML 文件的處理技術(shù)。

1.1    XML處理技術(shù)比較

Java 領(lǐng)域 XML 文件的技術(shù)大致分為兩類: XML API OXMapping XML API XML 處理的基礎(chǔ),可選技術(shù)包括 JDOM 、 Dom4j 等; OXMapping Object-XML Mapping 的簡(jiǎn)稱,這種技術(shù)隱藏了 XML 底層操作的細(xì)節(jié),可以將 XML 文件映射成一個(gè) JavaBean 對(duì)象,也可以把一個(gè) JavaBean 對(duì)象保存成一個(gè) XML 文件,可選技術(shù) XStream 、 Digester Castor 等。 XML API OXMapping 的關(guān)系類似于 JDBC ORMaping 的關(guān)系, OXMapping 內(nèi)部實(shí)現(xiàn)使用 XML API 來(lái)完成,兩種實(shí)現(xiàn)技術(shù)從不同的層面實(shí)現(xiàn)了 XML 的處理。

XML API

此類 XML 處理技術(shù)中最流行的莫過(guò)于 JDOM Dom4j 了,二者的使用方式非常相似。不過(guò) Dom4j 的優(yōu)勢(shì)比 JDOM 更明顯一些:

Dom4j 大量的使用接口,這使得 Dom4j Dom4j 更加靈活和具有可擴(kuò)展性;

Dom4j 的性能表現(xiàn)比 JDOM 好;

Dom4j 支持 XPath 等高級(jí)特性;

正是由于這些優(yōu)點(diǎn),很多開(kāi)源項(xiàng)目都開(kāi)始使用 Dom4j XML 解析技術(shù),本書也將使用 Dom4j 做為 XML 處理的首選。

OXMapping

使用 XML API 解析是略顯煩瑣的,受 ORMapping 技術(shù)的啟發(fā),人們發(fā)明了 OXMapping 技術(shù),使用 OXMapping 技術(shù),我們可以將 XML 文件映射成一個(gè) JavaBean 對(duì)象,也可以把一個(gè) JavaBean 對(duì)象保存成一個(gè) XML 文件,這大大簡(jiǎn)化了我們的開(kāi)發(fā)工作量,使得開(kāi)發(fā)人員能更多的關(guān)注應(yīng)用層面的東西。

開(kāi)源世界中涌現(xiàn)出很多 OXMapping 框架,包括 XStream 、 Digester 、 Castor 等。 XStream Digester 把映射的過(guò)程在代碼中完成,而 Castor 則需要寫一個(gè)和 Hibernate cfg.xml 類似的映射配置文件。與 Digester 比起來(lái), XStream 的主要優(yōu)點(diǎn)就是更加小巧,使用也更加方便,不過(guò)目前使用 Digester 是“開(kāi)源名牌” Apache 下的子項(xiàng)目,網(wǎng)上可以參考的資料也比 XStream 多,好在 XStream 比較簡(jiǎn)潔,所以并不會(huì)對(duì) XStream 造成太大影響。

http://www./huanzhugege/

1.2    Dom4j的使用

Dom4j 是一個(gè)易用的、開(kāi)源的庫(kù),用于 XML XPath XSLT 。它應(yīng)用于 Java 平臺(tái),采用了 Java 集合框架并完全支持 DOM , SAX JAXP Dom4j 上的一個(gè)開(kāi)源項(xiàng)目,地址為 http:///projects/dom4j 。

Dom4j 里基于接口編程是一個(gè)非常顯著的優(yōu)點(diǎn),下面是其主要的接口的繼承體系結(jié)構(gòu)圖:

5 . 1

這些接口大部分都是定義在包 org.dom4j 中,下面簡(jiǎn)單介紹各個(gè)接口的意義:

5 . 1 Dom4j 主要接口

Node

Node 為是 dom4j 中所有的 XML 節(jié)點(diǎn)的基類型接口

Attribute

Attribute 定義了 XML 的屬性

Branch

Branch 為能夠包含子節(jié)點(diǎn)的節(jié)點(diǎn)如 XML 元素 (Element) 和文檔 (Docuemnts) 定義了一個(gè)公共的行為

Document

定義了 XML 文檔

Element

Element 定義 XML 元素

DocumentType

DocumentType 定義 XML DOCTYPE 聲明

Entity

Entity 定義 XML entity

CharacterData

CharacterData 是一個(gè)標(biāo)識(shí)借口,標(biāo)識(shí)基于字符的節(jié)點(diǎn)。如 CDATA , Comment, Text

CDATA

CDATA 定義了 XML CDATA 區(qū)域

Comment

Comment 定義了 XML 注釋的行為

Text

Text 定義 XML 文本節(jié)點(diǎn)

ProcessingInstruction

ProcessingInstruction 定義 XML 處理指令

 

讀取 XML 文件

XML 應(yīng)用中,最常用的莫過(guò)于 XML 文件的解析讀取了, Dom4j 提供了多種讀取 XML 文檔的方式,包括 Dom 樹遍歷、 Visitor 方式和 XPath 方式。

無(wú)論哪種方式,我們首先都要根據(jù) xml 文件構(gòu)造一個(gè) Document 對(duì)象:

SAXReader reader = new SAXReader();

Document document = reader.read(new File(fileName));

這里我們選用了 SAXReader 做為 XML 讀取器,我們同樣也可以選擇 DOMReader 做為 XML 讀取器:

SAXReader reader = new DOMReader();

Document document = reader.read(new File(fileName));

其中 reader read 方法有多個(gè)重載方法,可以從 InputStream, File, URL 等多種不同的源來(lái)讀取 XML 文檔。

1 Dom 樹遍歷

這種讀取方式中把 Dom 看成一個(gè)普通的樹,要讀取 XML 中某個(gè)節(jié)點(diǎn)的值,只要采用數(shù)據(jù)結(jié)構(gòu)中的樹遍歷算法定位到需要讀取的節(jié)點(diǎn)即可。

要便利 Dom 樹,首先要取得樹的根節(jié)點(diǎn):

Element root = document.getRootElement();

取得根節(jié)點(diǎn)以后就可以一級(jí)一級(jí)的向下讀了:

// 遍歷所有子節(jié)點(diǎn)

for ( Iterator i = root.elementIterator(); i.hasNext(); )

{

       Element element = (Element) i.next();

       // do something

    }

    // 遍歷名稱為“ foo ”的節(jié)點(diǎn)

for ( Iterator i = root.elementIterator( foo ); i.hasNext();)

{

       Element foo = (Element) i.next();

       // do something

    }

    // 遍歷屬性

for ( Iterator i = root.attributeIterator(); i.hasNext(); )

{

       Attribute attribute = (Attribute) i.next();

       // do something

}

2 Visitor 方式

Dom 樹遍歷是最普通,也是最常用的 XML 讀取方式,其他的 XML 解析引擎,比如 JDom 等,也是使用這種方式進(jìn)行 XML 的讀取。不過(guò) Dom4j 提供了另外一種讀取方式,那就是 Visitor 方式。這種方式實(shí)現(xiàn)了 Visitor 模式,調(diào)用者只要編寫一個(gè) Visitor 就可以了。 Visitor 模式使得訪問(wèn)者易于增加新的操作,同時(shí)使訪問(wèn)者集中相關(guān)的操作而分離無(wú)關(guān)的操作。

編寫的 Visitor 必須實(shí)現(xiàn) org.dom4j.Visitor 接口, Dom4j 還提供了一個(gè) Default Adapter 模式的默認(rèn)適配器 org.dom4j.VisitorSupport

public class DemoVisitor extends VisitorSupport

{

public void visit(Element element)

{

System.out.println(element.getName());

}

public void visit(Attribute attr)

{

System.out.println(attr.getName());

}

}

然后在要開(kāi)始遍歷的節(jié)點(diǎn)調(diào)用此 Visitor 即可:

root.accept(new DemoVisitor ())

此方式需要遍歷所有的節(jié)點(diǎn)和元素,因此速度會(huì)稍慢一些。

3 XPath 方式

Dom4j 最吸引人的特性莫過(guò)于對(duì) XPath 的集成支持了,這個(gè)特性并不是所有的 XML 解析引擎都支持的,但是確實(shí)一個(gè)非常有用的特性。

XPath 是尋址、搜索和匹配文檔的各個(gè)部分的語(yǔ)言。它使用路徑標(biāo)記法來(lái)指定和匹配文檔的各個(gè)部分,該標(biāo)記法與文件系統(tǒng)和 URL 中使用的類似。例如, XPath:/x/y/z 搜索文檔的根節(jié)點(diǎn) x ,其下存在節(jié)點(diǎn) y ,其下存在節(jié)點(diǎn) z 。該語(yǔ)句返回與指定路徑結(jié)構(gòu)匹配的所有節(jié)點(diǎn)。 /x/y/* 返回父節(jié)點(diǎn)為 x y 節(jié)點(diǎn)下的任何節(jié)點(diǎn)。 /x/y[@name=a] 匹配所有父節(jié)點(diǎn)為 x y 節(jié)點(diǎn),其屬性稱為 name ,屬性值為 a 。

XPath 大大簡(jiǎn)化了 XML 的尋址操作,使用者只要通過(guò)匹配表達(dá)式告訴引擎要匹配文檔的哪些部分即可,具體的匹配工作由 XPath 引擎來(lái)完成。這種方式更加接近于人類的自然思維方式。我們來(lái)看一個(gè)實(shí)際的例子:

有一個(gè) XML 文件記錄了一個(gè)部門的基本情況:

<?xml version="1.0" encoding="GB2312"?>

<department>

     <name> 開(kāi)發(fā)部 </name>

     <level>2</level>

     <employeeList>

         <employee number="001" name="Tom" />

         <employee number="002" name="Jim" />

         <employee number="003" name="Lily" />

     </employeeList>

</department>

name 代表部門名稱, level 為部門的級(jí)別, employeeList 下是部門所有的員工列表。下面編寫一個(gè)程序讀取此文件并打印出部門的信息。

代碼 5 . 1 XPath 演示

InputStream inStream = null;

try

{

     inStream = Dom4jDemo01.class.getResourceAsStream(

"/com/cownew/Char0502/Department01.xml");

     SAXReader reader = new SAXReader();

     Document doc = reader.read(new InputStreamReader(inStream));

     Node nameNode = doc.selectSingleNode("http://department/name");

     System.out.println(" 部門名稱 :" + nameNode.getText());

 

     Node levelNode = doc.selectSingleNode("http://department/level");

     System.out.println(" 部門級(jí)別 :" + levelNode.getText());

 

     List employeeNodeList = doc

                   .selectNodes("http://department/employeeList/employee");

     System.out.println(" 部門下屬雇員 :");

     for (int i = 0, n = employeeNodeList.size(); i < n; i++)

     {

         DefaultElement employeeElement = (DefaultElement) employeeNodeList

                            .get(i);

         String name = employeeElement.attributeValue("name");

         String number = employeeElement.attributeValue("number");

         System.out.println(name + " ,工號(hào) :" + number);

     }

} finally

{

     ResourceUtils.close(inStream);

}

運(yùn)行結(jié)果

部門名稱 : 開(kāi)發(fā)部

部門級(jí)別 :2

部門下屬雇員 :

Tom ,工號(hào) :001

Jim ,工號(hào) :002

Lily ,工號(hào) :003

 

使用 XPath 以后,我們只要使用“ //department/name ”這種非常清晰的方式就可以直接定位到具體的節(jié)點(diǎn)。 XPath 方式中定位單個(gè)節(jié)點(diǎn)使用 selectSingleNode 方法,而定位多節(jié)點(diǎn)則使用 selectNodes 方法。

案例系統(tǒng)中所有的 XML 文件都是使用 XPath 方式進(jìn)行解析的,包括 ClientConfig.java 、 ServerConfig.java 、 EntityMetaDataParser.java 等。

XML 文件的創(chuàng)建

Dom4j XML 文件的創(chuàng)建和其他的 XML 引擎類似,首先以 Document 的根節(jié)點(diǎn)為基礎(chǔ)構(gòu)造出一棵節(jié)點(diǎn)樹,然后調(diào)用相應(yīng)的 IO 類庫(kù)就可以將 XML 文件保存到適當(dāng)?shù)慕橘|(zhì)中了。

下面演示一下生成上文提到的那個(gè)部門信息 XML 文件的過(guò)程

代碼 5 . 2 XML 創(chuàng)建演示

import java.io.FileWriter;

import java.io.IOException;

 

import org.dom4j.Document;

import org.dom4j.DocumentHelper;

import org.dom4j.Element;

import org.dom4j.io.OutputFormat;

import org.dom4j.io.XMLWriter;

 

public class Dom4jDemo02

{

     public static void main(String[] args)

     {

         // 創(chuàng)建文檔對(duì)象

         Document document = DocumentHelper.createDocument();

 

         // 添加根節(jié)點(diǎn) "department"

         Element departElement = document.addElement("department");

 

         // 添加 "name" 節(jié)點(diǎn)

         Element departNameElement = DocumentHelper.createElement("name");

         departNameElement.setText(" 開(kāi)發(fā)部 ");

         departElement.add(departNameElement);

 

         // 添加 "level" 節(jié)點(diǎn)

         Element departLevelElement = DocumentHelper.createElement("level");

         departLevelElement.setText("2");

         departElement.add(departLevelElement);

 

         // 添加員工列表 "employeeList" 節(jié)點(diǎn)

         Element employeeElementList = DocumentHelper

                   .createElement("employeeList");

         departElement.add(employeeElementList);

 

         // 添加員工節(jié)點(diǎn) "employee"

         Element emp1Element = DocumentHelper.createElement("employee");

         emp1Element.addAttribute("number", "001");

         emp1Element.addAttribute("name", "Tom");

         employeeElementList.add(emp1Element);

 

         Element emp2Element = DocumentHelper.createElement("employee");

         emp2Element.addAttribute("number", "002");

         emp2Element.addAttribute("name", "Jim");

         employeeElementList.add(emp2Element);

 

         Element emp3Element = DocumentHelper.createElement("employee");

         // 添加屬性

         emp3Element.addAttribute("number", "003");

         emp3Element.addAttribute("name", "Lily");

         employeeElementList.add(emp3Element);

 

         try

         {

              writeToFile(document, "c:/department.xml");

         } catch (IOException e)

         {

              e.printStackTrace();

         }

     }

 

     private static void writeToFile(Document document, String file)

              throws IOException

     {

         // 美化格式

         OutputFormat format = OutputFormat.createPrettyPrint();

         format.setEncoding("GB2312");

         XMLWriter writer = null;

         try

         {

              writer = new XMLWriter(new FileWriter(file), format);

              writer.write(document);

         } finally

         {

              if (writer != null)

                   writer.close();

         }

     }

}

運(yùn)行以后就可以在 c:/ 下發(fā)現(xiàn)生成了和 5.2.1 的文件內(nèi)容一樣的 department.xml 了。

這里有兩點(diǎn)需要注意的:

1 OutputFormat format = OutputFormat.createPrettyPrint()

XML 通常是需要人閱讀的, Dom4j 默認(rèn)的生成格式是緊縮格式的,這樣可以減少空間占用,但是帶來(lái)的缺點(diǎn)就是文件格式非常難看,因此我們采用鎖緊格式進(jìn)行輸出。

2 format.setEncoding("GB2312")

Dom4j 默認(rèn)的編碼格式是“ UTF-8 ”,這在輸出中文字符的時(shí)候會(huì)有問(wèn)題,因此我們改成“ GB2312 ”格式。

這里使用了 Dom4j 提供的工具類 DocumentHelper 提供的 createElement 方法來(lái)創(chuàng)建一個(gè)節(jié)點(diǎn),這個(gè)工具類還有 public static CDATA createCDATA(String text) 、 public static Comment createComment(String text) 、 public static Entity createEntity(String name, String text) 等方法可以幫助我們更快的創(chuàng)建節(jié)點(diǎn)。 DocumentHelper 還提供了 parseText 方法,可以直接將字符串解析成 Documen 對(duì)象。

http://www./huanzhugege/

1.3    XStream的使用

在使用 XStream 之前首先到 http://xstream. 下載 XStream 的最新版本,然后把 XSteam***.jar xpp3-***.jar 導(dǎo)入到 ClassPath 下,然后就可以使用了,當(dāng)然不加入 xpp3-***.jar 也可以,我們可以使用 DomDriver 做為 XML 解析驅(qū)動(dòng)(只要在實(shí)例化 XStream 的時(shí)候使用 new XStream(new DomDriver()) 即可),不過(guò) Xpp3 XStream 提供的一個(gè)很有效率的 XML pull-parser 實(shí)現(xiàn),推薦使用,可以提高解析的效率。

XML 的解析

我們有一個(gè)記錄書籍進(jìn)行的 XML 文件:

<book>

     <name>J2EE Guide Book</name>

     <author>

         <name>Jerry</name>

         <email>Jerry@mail.com</email>

     </author>

</book>

為了解析此 XML 文件,我們首先創(chuàng)建代表書籍和人員的兩個(gè) JavaBean 。

代碼 5 . 3 人員和書籍的 JavaBean

public class BookInfo

{

     private String name;

     private PersonInfo author;

     public PersonInfo getAuthor()

     {

         return author;

     }

     public void setAuthor(PersonInfo author)

     {

         this.author = author;

     }

     public String getName()

     {

         return name;

     }

     public void setName(String name)

     {

         this.name = name;

     }

}

 

public class PersonInfo

{

     private String name;

     private String email;

     public String getEmail()

     {

         return email;

     }

     public void setEmail(String email)

     {

         this.email = email;

     }

     public String getName()

     {

         return name;

     }

     public void setName(String name)

     {

         this.name = name;

     }

}

然后我們就可以進(jìn)行文件的解析了,這也是重頭戲:

代碼 5 . 4 XStream XML 解析

XStream xstream = new XStream();

xstream.alias("book", BookInfo.class);

xstream.alias("author", PersonInfo.class);

InputStream inStream = XStreamDemo.class

         .getResourceAsStream("/com/cownew/Char0503/Books.xml");

InputStreamReader reader = new InputStreamReader(inStream);

BookInfo book = (BookInfo) xstream.fromXML(reader);

StringBuffer sb = new StringBuffer();

sb.append(book.getName()).append(" 的作者 ");

sb.append(book.getAuthor().getName()).append(" Email :");

sb.append(book.getAuthor().getEmail());

System.out.println(sb);

運(yùn)行結(jié)果:

J2EE Guide Book 的作者 Jerry Email :Jerry@mail.com     

由于 book 節(jié)點(diǎn)和 author 節(jié)點(diǎn)對(duì)應(yīng)的數(shù)據(jù)類型是我們的自定義類型,因此我們必須首先向 XStream 注冊(cè)這兩個(gè)類型

xstream.alias("book", BookInfo.class);

xstream.alias("author", PersonInfo.class);

由于我們是使用 XStream 解析已有的 XML 文件,因此我們必須讓 XStream 知道標(biāo)簽對(duì)應(yīng)的類型是什么,如果我們是使用 XStream 進(jìn)行 XML 文件的生成,那么我們甚至無(wú)需向 XStream 注冊(cè)別名即可進(jìn)行文件解析。

注冊(cè)完類型以后,調(diào)用 XStream 類的 fromXML 方法即可把 XML 解析成 JavaBean 對(duì)象,無(wú)需額外的操作。

XML 文件的保存

我們不僅需要解析 XML 文件,有的時(shí)候還需要將數(shù)據(jù)保存到 XML 文件, XStream 同樣能很好的完成,并且能更體現(xiàn)出 XStream 的強(qiáng)大。

代碼 5 . 5 XStream XML 的保存

List bookList = new ArrayList();

PersonInfo p1 = new PersonInfo();

p1.setName("Tom");

p1.setEmail("Tom@mail.com");

PersonInfo p2 = new PersonInfo();

p2.setName("Jerry");

p2.setEmail("Jerry@mail.com");

    

BookInfo book1 = new BookInfo();

book1.setName("About Face");

book1.setAuthor(p1);

    

BookInfo book2 = new BookInfo();

book2.setName("UI Design");

book2.setAuthor(p2);

    

bookList.add(book1);

bookList.add(book2);

    

XStream xstream = new XStream();

String xml = xstream.toXML(bookList);

System.out.println(xml);

    

List list = (List) xstream.fromXML(xml);

for(int i=0,n=list.size();i<n;i++)

{

     BookInfo book = (BookInfo) list.get(i);

     StringBuffer sb = new StringBuffer();

     sb.append(book.getName()).append(" 的作者 ");

     sb.append(book.getAuthor().getName()).append(" Email :");

     sb.append(book.getAuthor().getEmail());

     System.out.println(sb);

}

運(yùn)行結(jié)果:

<list>

  <com.cownew.Char0503.BookInfo>

    <name>About Face</name>

    <author>

      <name>Tom</name>

      <email>Tom@mail.com</email>

    </author>

  </com.cownew.Char0503.BookInfo>

  <com.cownew.Char0503.BookInfo>

    <name>UI Design</name>

    <author>

      <name>Jerry</name>

      <email>Jerry@mail.com</email>

    </author>

  </com.cownew.Char0503.BookInfo>

</list>

About Face 的作者 Tom Email :Tom@mail.com

UI Design 的作者 Jerry Email :Jerry@mail.com

 

不可思議吧!我們就是像在序列化一樣把 JavaBean “序列化”為 XML 格式字符串,然后又輕松的將 XML 格式字符串“反序列化”為 JavaBean 。

不過(guò)美中不足的就是“ <com.cownew.Char0503.BookInfo> ”這個(gè)標(biāo)簽顯得有點(diǎn)羅嗦。解決方式很簡(jiǎn)單,使用 5.3.1 一節(jié)中提到的 alias 方法就可以辦到:

xstream.alias("book", BookInfo.class); 添加到 XStream xstream = new XStream(); 之后,然后重新運(yùn)行:

<list>

  <book>

    <name>About Face</name>

    <author>

      <name>Tom</name>

      <email>Tom@mail.com</email>

    </author>

  </book>

  <book>

    <name>UI Design</name>

    <author>

      <name>Jerry</name>

      <email>Jerry@mail.com</email>

    </author>

  </book>

</list>

About Face 的作者 Tom Email :Tom@mail.com

UI Design 的作者 Jerry Email :Jerry@mail.com

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多