利用XMLBean輕輕松松讀寫XML
作者:葉楓
版權(quán)聲明:本文可以自由轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
作者:葉楓(
http://blog.matrix.org.cn/page/葉楓)
原文:[http://www.matrix.org.cn/resource/article/44/44027_XMLBean.html]http://www.matrix.org.cn/resource/article/44/44027_XMLBean.html[/url]
關(guān)鍵字:XML XMLBean Parser
一、關(guān)于XML解析??XML在Java應(yīng)用程序里變得越來越重要, 廣泛應(yīng)用于數(shù)據(jù)存儲(chǔ)和
交換. 比如我們常見的配置文件,都是以XML方式存儲(chǔ)的. XML還應(yīng)用
于Java Message Service和Web Services等技術(shù)作為數(shù)據(jù)交換.
因此,正確讀寫XML文檔是XML應(yīng)用的基礎(chǔ).
??Java提供了SAX和DOM兩種方式用于解析XML,但即便如此,要讀寫一個(gè)
稍微復(fù)雜的XML,也不是一件容易的事.
二、XMLBean簡(jiǎn)介????Hibernate已經(jīng)成為目前流行的面向Java環(huán)境的對(duì)象/關(guān)系數(shù)據(jù)庫映射工具.
在Hibernate等對(duì)象/關(guān)系數(shù)據(jù)庫映射工具出現(xiàn)之前,對(duì)數(shù)據(jù)庫的操作是
通過JDBC來實(shí)現(xiàn)的,對(duì)數(shù)據(jù)庫的任何操作,開發(fā)人員都要自己寫SQL語句
來實(shí)現(xiàn). 對(duì)象/關(guān)系數(shù)據(jù)庫映射工具出現(xiàn)后,對(duì)數(shù)據(jù)庫的操作轉(zhuǎn)成對(duì)
JavaBean的操作,極大方便了數(shù)據(jù)庫開發(fā). 所以如果有一個(gè)類似的工具能夠
實(shí)現(xiàn)將對(duì)XML的讀寫轉(zhuǎn)成對(duì)JavaBean的操作,將會(huì)簡(jiǎn)化XML的讀寫,即使對(duì)XML
不熟悉的開發(fā)人員也能方便地讀寫XML. 這個(gè)工具就是XMLBean.
三、準(zhǔn)備XMLBean和XML文檔?? XMLBean是Apache的一個(gè)開源項(xiàng)目,可以從http://www.apache.org下載,
最新的版本是2.0. 解壓后目錄如下:
xmlbean2.0.0
???? +---bin
???? +---docs
???? +---lib
???? +---samples
???? +---schemas另外還要準(zhǔn)備一個(gè)XML文檔(customers.xml),
在本文的例子里,我們將對(duì)這個(gè)文檔進(jìn)行讀寫操作. 文檔源碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<Customers>
????<customer>
????????????<id>1</id>
????????????<gender>female</gender>
????????????<firstname>Jessica</firstname>
????????????<lastname>Lim</lastname>
????????????<phoneNumber>1234567</phoneNumber>
????????????<address>
????????????????<primaryAddress>
????????????????????????<postalCode>350106</postalCode>
????????????????????????<addressLine1>#25-1</addressLine1>
????????????????????????<addressLine2>SHINSAYAMA 2-CHOME</addressLine2>
????????????????</primaryAddress>
????????????????<billingAddress>
????????????????????????<receiver>Ms Danielle</receiver>
????????????????????????<postalCode>350107</postalCode>
????????????????????????<addressLine1>#167</addressLine1>
????????????????????????<addressLine2>NORTH TOWER HARBOUR CITY</addressLine2>
????????????????</billingAddress>
????????????</address>
????</customer>
????<customer>
????????????<id>2</id>
????????????<gender>male</gender>
????????????<firstname>David</firstname>
????????????<lastname>Bill</lastname>
????????????<phoneNumber>808182</phoneNumber>
????????????<address>
????????????????<primaryAddress>
????????????????????????<postalCode>319087</postalCode>
????????????????????????<addressLine1>1033 WS St.</addressLine1>
????????????????????????<addressLine2>Tima Road</addressLine2>
????????????????</primaryAddress>
????????????????<billingAddress>
????????????????????????<receiver>Mr William</receiver>
????????????????????????<postalCode>672993</postalCode>
????????????????????????<addressLine1>1033 WS St.</addressLine1>
????????????????????????<addressLine2>Tima Road</addressLine2>
????????????????</billingAddress>
????????????</address>
????</customer>
</Customers>
這是一個(gè)客戶的數(shù)據(jù)模型,每個(gè)客戶都有客戶編號(hào)(ID),姓名,性別(gender),
電話號(hào)碼(phoneNumber)和地址,其中地址有兩個(gè): 首要地址(PrimaryAddress)
和帳單地址(BillingAddress),每個(gè)地址有郵編,地址1,和地址2組成.
其中帳單地址還有收件人(receiver).
????此外,還要準(zhǔn)備一個(gè)配置文件(文件名customer.xsdconfig),這個(gè)文件的
作用我后面會(huì)講,它的內(nèi)容如下:
<xb:config xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config">
??<xb:namespace>
????<xb:package>sample.xmlbean</xb:package>
??</xb:namespace>
</xb:config>
四、XMLBean使用步驟????和其他面向Java環(huán)境的對(duì)象/關(guān)系數(shù)據(jù)庫映射工具的使用步驟一樣,
在正式使用XMLBean前,我們要作兩個(gè)準(zhǔn)備.
????1. 生成XML Schema文件
?????? 什么是XML Schema文件? 正常情況下,每個(gè)XML文件都有一個(gè)Schema文件,
?????? XML Schema文件是一個(gè)XML的約束文件,它定義了XML文件的結(jié)構(gòu)和元素.
?????? 以及對(duì)元素和結(jié)構(gòu)的約束. 通俗地講,如果說XML文件是數(shù)據(jù)庫里的記錄,
?????? 那么Schema就是表結(jié)構(gòu)定義.
?????? 為什么需要這個(gè)文件? XMLBean需要通過這個(gè)文件知道一個(gè)XML文件的
?????? 結(jié)構(gòu)以及約束,比如數(shù)據(jù)類型等. 利用這個(gè)Schema文件,XMLBean將會(huì)產(chǎn)生
?????? 一系列相關(guān)的Java Classes來實(shí)現(xiàn)對(duì)XML的操作. 而作為開發(fā)人員,則是
?????? 利用XMLBean產(chǎn)生的Java Classes來完成對(duì)XML的操作而不需要SAX或DOM.
?????? 怎樣產(chǎn)生這個(gè)Schema文件呢? 如果對(duì)于熟悉XML的開發(fā)人員,可以自己來
?????? 寫這個(gè)Schema文件,對(duì)于不熟悉XML的開發(fā)人員,可以通過一些工具來完成.
?????? 比較有名的如XMLSPY和Stylus Studio都可以通過XML文件來生成Schema
?????? 文件. 加入我們已經(jīng)生成這個(gè)Schema文件(customer.xsd):
??????
?????? <?xml version="1.0" encoding="UTF-8"?>
?????? <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
??????????????????elementFormDefault="qualified">
???????? <xs:element name="Customers">
?????????? <xs:complexType>
???????????? <xs:sequence>
?????????????? <xs:element maxOccurs="unbounded" name="customer"
?????????????????????????? type="customerType"/>
???????????? </xs:sequence>
?????????? </xs:complexType>
???????? </xs:element>
?????? <xs:complexType name="customerType">
???????????? <xs:sequence>
?????????????? <xs:element name="id" type="xs:int"/>
?????????????? <xs:element name="gender" type="xs:string"/>
?????????????? <xs:element name="firstname" type="xs:string"/>
?????????????? <xs:element name="lastname" type="xs:string"/>
?????????????? <xs:element name="phoneNumber" type="xs:string"/>
?????????????? <xs:element name="address" type="addressType"/>
???????????? </xs:sequence>
?????? </xs:complexType>
???????? <xs:complexType name="addressType">
???????????? <xs:sequence>
?????????????? <xs:element name="primaryAddress" type="primaryAddressType"/>
?????????????? <xs:element name="billingAddress" type="billingAddressType"/>
???????????? </xs:sequence>
???????? </xs:complexType>
???????? <xs:complexType name="primaryAddressType">
???????????? <xs:sequence>
?????????????? <xs:element name="postalCode" type="xs:string"/>
?????????????? <xs:element name="addressLine1" type="xs:string"/>
?????????????? <xs:element name="addressLine2" type="xs:string"/>
???????????? </xs:sequence>
???????? </xs:complexType>
???????? <xs:complexType name="billingAddressType">
???????????? <xs:sequence>
?????? ????????????<xs:element name="receiver" type="xs:string"/>
?????????????? <xs:element name="postalCode" type="xs:string"/>
?????????????? <xs:element name="addressLine1" type="xs:string"/>
?????????????? <xs:element name="addressLine2" type="xs:string"/>
???????????? </xs:sequence>
???????? </xs:complexType>
?????? </xs:schema>
??????
????2. 利用scomp來生成Java Classes
?????? scomp是XMLBean提供的一個(gè)編譯工具,它在bin的目錄下. 通過這個(gè)工具,
?????? 我們可以將以上的Schema文件生成Java Classes.
?????? scomp的語法如下:-
??????
?????? scomp [options] [dirs]* [schemaFile.xsd]* [service.wsdl]* [config.xsdconfig]*
??????
?????? 主要參數(shù)說明:
?????? -src [dir]??????????????????-- 生成的Java Classes存放目錄
???? -srconly??????????????????-- 不編譯Java Classes,不產(chǎn)生Jar文件
???? -out [jarFileName]??-- 生成的Jar文件,缺省是xmltypes.jar
?????? -compiler???????????????? -- Java編譯器的路徑,即Javac的位置
?????? schemaFile.xsd????-- XML Schema文件位置
?????? config.xsdconfig?? -- xsdconfig文件的位置, 這個(gè)文件主要用來制定生成的Java Class
??????????????????????????????的一些文件名規(guī)則和Package的名稱,在本文,package是sample.xmlbean
?????? 在本文,我是這樣運(yùn)行的:
??????
?????? scomp -src build\src??-out build\customerXmlBean.jar schema\customer.xsd
???????????? -compiler C:\jdk142_04\bin\javac customer.xsdconfig
??????
?????? 這個(gè)命令行的意思是告訴scomp生成customerXmlBean.jar,放在build目錄下,同時(shí)
?????? 生成源代碼放在build\src下, Schema文件是customer.xsd,xsdconfig文件是customer.xsdconfig.
?????? 其實(shí), 生成的Java源代碼沒有多大作用,我們要的是jar文件.我們先看一下build\src\sample\xmlbean下生成的Classes.
??????
??????????CustomersDocument.java????-- 整個(gè)XML文檔的Java Class映射
?????? CustomerType.java??????????????-- 節(jié)點(diǎn)sustomer的映射
?????? AddressType.java???????????????? -- 節(jié)點(diǎn)address的映射
?????? BillingAddressType.java????????-- 節(jié)點(diǎn)billingAddress的映射
?????? PrimaryAddressType.java??????-- 節(jié)點(diǎn)primaryAddress的映射
????
?????? 好了,到此我們所有的準(zhǔn)備工作已經(jīng)完成了. 下面就開始進(jìn)入重點(diǎn):利用剛才生成的jar文件讀寫XML.
五、利用XMLBean讀XML文件????新建一個(gè)Java Project,將XMLBean2.0.0\lib\下的Jar文件和剛才我們生成的customerXmlBean.jar加入
????到Project的ClassPath.
????新建一個(gè)Java Class: CustomerXMLBean.??源碼如下:
????
????package com.sample.reader;
????import java.io.File;
????
????import sample.xmlbean.*;
????import org.apache.commons.beanutils.BeanUtils;
????import org.apache.xmlbeans.XmlOptions;
????public class CustomerXMLBean {
????private String filename = null;
????
????public CustomerXMLBean(String filename) {
????????????super();
????????????this.filename = filename;
????}
????public void customerReader() {
????????????try {
??????????????File xmlFile = new File(filename);
??????????????CustomersDocument doc = CustomersDocument.Factory.parse(xmlFile);
??????????????CustomerType[] customers = doc.getCustomers().getCustomerArray();
??????????
??????????????for (int i = 0; i < customers.length; i++) {
????????????????CustomerType customer = customers[i];
????????????????println("Customer#" + i);
????????????????println("Customer ID:" + customer.getId());
????????????????println("First name:" + customer.getFirstname());
????????????????println("Last name:" + customer.getLastname());
????????????????println("Gender:" + customer.getGender());
????????????????println("PhoneNumber:" + customer.getPhoneNumber());
????????????????// Primary address
????????????????PrimaryAddressType primaryAddress = customer.getAddress().getPrimaryAddress();
????????????????println("PrimaryAddress:");
????????????????println("PostalCode:" + primaryAddress.getPostalCode());
????????????????println("AddressLine1:" + primaryAddress.getAddressLine1());
????????????????println("AddressLine2:" + primaryAddress.getAddressLine2());
????????????????// Billing address
????????????????BillingAddressType billingAddress = customer.getAddress().getBillingAddress();
????????????????println("BillingAddress:");
????????????????println("Receiver:" + billingAddress.getReceiver());
????????????????println("PostalCode:" + billingAddress.getPostalCode());
????????????????println("AddressLine1:" + billingAddress.getAddressLine1());
????????????????println("AddressLine2:" + billingAddress.getAddressLine2());
????????????
??????????????}
????????????} catch (Exception ex) {
????????????????????ex.printStackTrace();
????????????}
????}
????private void println(String str) {
??????????System.out.println(str);
????}
?? public static void main(String[] args) {
??????String filename = "F://JavaTest//Eclipse//XMLBean//xml//customers.xml";
??????????????????
???? CustomerXMLBean customerXMLBean = new CustomerXMLBean(filename);
?????????????????? customerXMLBean.customerReader();
????}
????}
????
????運(yùn)行它,參看輸出結(jié)果:
????
?????? Customer#0
?????? Customer ID:1
?????? First name:Jessica
?????? Last name:Lim
?????? Gender:female
?????? PhoneNumber:1234567
?????? PrimaryAddress:
?????? PostalCode:350106
?????? AddressLine1:#25-1
?????? AddressLine2:SHINSAYAMA 2-CHOME
?????? BillingAddress:
?????? Receiver:Ms Danielle
?????? PostalCode:350107
?????? AddressLine1:#167
?????? AddressLine2:NORTH TOWER HARBOUR CITY
?????? Customer#1
?????? Customer ID:2
?????? First name:David
?????? Last name:Bill
?????? Gender:male
?????? PhoneNumber:808182
?????? PrimaryAddress:
?????? PostalCode:319087
?????? AddressLine1:1033 WS St.
?????? AddressLine2:Tima Road
?????? BillingAddress:
?????? Receiver:Mr William
?????? PostalCode:672993
?????? AddressLine1:1033 WS St.
?????? AddressLine2:Tima Road
????
????怎么樣,是不是很輕松? XMLBean的威力.
六、利用XMLBean寫XML文件????利用XMLBean創(chuàng)建一個(gè)XML文檔也是一件輕而易舉的事.我們?cè)僭黾右粋€(gè)Method,
????請(qǐng)看一下的Java Class:
????
????public void createCustomer() {
????try {
????????// Create Document
????????CustomersDocument doc = CustomersDocument.Factory.newInstance();
????????// Add new customer
????????CustomerType customer = doc.addNewCustomers().addNewCustomer();
????????// set customer info
????????customer.setId(3);
????????customer.setFirstname("Jessica");
????????customer.setLastname("Lim");
????????customer.setGender("female");
????????customer.setPhoneNumber("1234567");
????????// Add new address
????????AddressType address = customer.addNewAddress();
????????// Add new PrimaryAddress
????????PrimaryAddressType primaryAddress = address.addNewPrimaryAddress();
????????primaryAddress.setPostalCode("350106");
????????primaryAddress.setAddressLine1("#25-1");
????????primaryAddress.setAddressLine2("SHINSAYAMA 2-CHOME");
????????// Add new BillingAddress
????????BillingAddressType billingAddress = address.addNewBillingAddress();
????????billingAddress.setReceiver("Ms Danielle");
????????billingAddress.setPostalCode("350107");
????????billingAddress.setAddressLine1("#167");
????????billingAddress.setAddressLine2("NORTH TOWER HARBOUR CITY");
????????File xmlFile = new File(filename);
????????doc.save(xmlFile);
????????} catch (Exception ex) {
????????????????ex.printStackTrace();
????????}
??}
????
????修改main method.
????
????public static void main(String[] args) {
????String filename = "F://JavaTest//Eclipse//XMLBean//xml//customers_new.xml";
????????CustomerXMLBean customerXMLBean = new CustomerXMLBean(filename);
????????customerXMLBean.createCustomer();
????}
????
????運(yùn)行,打開customers_new.xml:
????
????<?xml version="1.0" encoding="UTF-8"?>
????<Customers>
????<customer>
????????????<id>3</id>
????????????<gender>female</gender>
????????????<firstname>Jessica</firstname>
????????????<lastname>Lim</lastname>
????????????<phoneNumber>1234567</phoneNumber>
????????????<address>
????????????????????<primaryAddress>
???????????????????????? <postalCode>350106</postalCode>
???????????????????????? <addressLine1>#25-1</addressLine1>
?????????????????????????????????????? <addressLine2>SHINSAYAMA 2-CHOME</addressLine2>
????????????????????</primaryAddress>
????????????????????<billingAddress>
????????????????????????<receiver>Ms Danielle</receiver>
????????????????????????<postalCode>350107</postalCode>
?????????????????????? <addressLine1>#167</addressLine1>
?????????????????????? <addressLine2>NORTH TOWER HARBOUR CITY</addressLine2>
????????????????????</billingAddress>
????????????????????</address>
????????????</customer>
????</Customers>
????
七、利用XMLBean修改XML文件????我們?cè)僭黾右粋€(gè)Method:
????
??????public void updateCustomer(int id,String lastname) {
???????? try {
????????File xmlFile = new File(filename);
????????CustomersDocument doc = CustomersDocument.Factory.parse(xmlFile);
????????CustomerType[] customers = doc.getCustomers().getCustomerArray();
??????
????????for (int i = 0; i < customers.length; i++) {
?????????? CustomerType customer = customers[i];
??????????if(customer.getId()==id){
????????????????customer.setLastname(lastname);
????????????????break;
????????????}
????????}
????????doc.save(xmlFile);
???????? } catch (Exception ex) {
??????????ex.printStackTrace();
???????? }
?? ????????}
????
????main method:
????
????public static void main(String[] args) {
???? String filename = "F://JavaTest//Eclipse//XMLBean//xml//customers_new.xml";
????????????????????
????CustomerXMLBean customerXMLBean = new CustomerXMLBean(filename);
????????????????????
????customerXMLBean.updateCustomer(3,"last");
????}
????
????運(yùn)行之后,我們將會(huì)看到客戶編號(hào)為3的客戶的lastname已經(jīng)改為last.
八、利用XMLBean刪除一個(gè)customer????再增加一個(gè)Method:
????
????public void deleteCustomer(int id) {
???? try {
??????File xmlFile = new File(filename);
???? CustomersDocument doc = CustomersDocument.Factory.parse(xmlFile);
????CustomerType[] customers = doc.getCustomers().getCustomerArray();
?? for (int i = 0; i < customers.length; i++) {
????????CustomerType customer = customers[i];
????????if(customer.getId()==id){
????????????????????????customer.setNil() ;
????????????????????????break;
?????????????? }
?? }
?? doc.save(xmlFile);
?? } catch (Exception ex) {
????????ex.printStackTrace();
????????}
?? }
???????? main method:
????
????public static void main(String[] args) {
????String filename = "F://JavaTest//Eclipse//XMLBean//xml//customers_new.xml";
????????????????????
????CustomerXMLBean customerXMLBean = new CustomerXMLBean(filename);
????????????????????
????customerXMLBean.deleteCustomer(3);
????}
????????
運(yùn)行,我們將會(huì)看到客戶編號(hào)為3的客戶的資料已經(jīng)被刪除.
九、查詢XML????除了本文在以上講述的,利用XMLBean能輕輕松松完成XML的讀寫操作外,結(jié)合XPath和XQuery,
?? XMLBean還能完成象SQL查詢數(shù)據(jù)庫一樣方便地查詢XML數(shù)據(jù). 關(guān)于XML查詢以及如何創(chuàng)建XML數(shù)據(jù)庫, 我將在另一篇文章里討論.
十、結(jié)束語????XMLBean能幫助我們輕易讀寫XML,這將有助于我們降低XML的學(xué)習(xí)和使用,有了這個(gè)基礎(chǔ),
????開發(fā)人員將為學(xué)習(xí)更多地XML相關(guān)技術(shù)和Web Services,JMS等其他J2EE技術(shù)打下良好地基礎(chǔ).
關(guān)于作者:葉楓:熱愛Java和Oracle. 在軟件開發(fā)有近10年, 目前在國(guó)外一家美國(guó)大公司擔(dān)任SA, 負(fù)責(zé)技術(shù)研究。作者Blog:
http://blog.matrix.org.cn/page/葉楓