利用XMLBean轻轻松松读写XML

  一、关于XML解析

  XML在Java应用程序里变得越来越重要, 广泛应用于数据存储和
交换. 比如我们常见的配置文件,都是以XML方式存储的. XML还应用
于Java Message Service和Web Services等技术作为数据交换.
因此,正确读写XML文档是XML应用的基础.
  Java提供了SAX和DOM两种方式用于解析XML,但即便如此,要读写一个
稍微复杂的XML,也不是一件容易的事.

二、XMLBean简介

    Hibernate已经成为目前流行的面向Java环境的对象/关系数据库映射工具.
在Hibernate等对象/关系数据库映射工具出现之前,对数据库的操作是
通过JDBC来实现的,对数据库的任何操作,开发人员都要自己写SQL语句
来实现. 对象/关系数据库映射工具出现后,对数据库的操作转成对
JavaBean的操作,极大方便了数据库开发. 所以如果有一个类似的工具能够
实现将对XML的读写转成对JavaBean的操作,将会简化XML的读写,即使对XML
不熟悉的开发人员也能方便地读写XML. 这个工具就是XMLBean.

三、准备XMLBean和XML文档

   XMLBean是Apache的一个开源项目,可以从http://www.apache.org下载,
最新的版本是2.3.0. 解压后目录如下:
xmlbean2.3.0
     +---bin
     +---docs
     +---lib
     +---samples
     +---schemas

其他设置参照前一篇:  使用Eclipse开发XMLBeans项目
另外还要准备一个XML文档(customers.xml),
在本文的例子里,我们将对这个文档进行读写操作. 文档源码如下:
<? xml version="1.0" encoding="UTF-8" ?>
< Customers  xmlns ="http://xmlbeans.apache.org/samples/template/xmlbean" >
    
< 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 >


这是一个客户的数据模型,每个客户都有客户编号(ID),姓名,性别(gender),
电话号码(phoneNumber)和地址,其中地址有两个: 首要地址(PrimaryAddress)
和帐单地址(BillingAddress),每个地址有邮编,地址1,和地址2组成.
其中帐单地址还有收件人(receiver).

四、XMLBean使用步骤

    和其他面向Java环境的对象/关系数据库映射工具的使用步骤一样,
在正式使用XMLBean前,我们要作两个准备.

    1. 生成XML Schema文件

       什么是XML Schema文件? 正常情况下,每个XML文件都有一个Schema文件,
       XML Schema文件是一个XML的约束文件,它定义了XML文件的结构和元素.
       以及对元素和结构的约束. 通俗地讲,如果说XML文件是数据库里的记录,
       那么Schema就是表结构定义.

       为什么需要这个文件? XMLBean需要通过这个文件知道一个XML文件的
       结构以及约束,比如数据类型等. 利用这个Schema文件,XMLBean将会产生
       一系列相关的Java Classes来实现对XML的操作. 而作为开发人员,则是
       利用XMLBean产生的Java Classes来完成对XML的操作而不需要SAX或DOM.

       怎样产生这个Schema文件呢? 如果对于熟悉XML的开发人员,可以自己来
       写这个Schema文件,对于不熟悉XML的开发人员,可以通过一些工具来完成.
       比较有名的如XMLSPY和Stylus Studio都可以通过XML文件来生成Schema
       文件. 加入我们已经生成这个Schema文件(customer.xsd):
       
<? xml version="1.0" encoding="UTF-8" ?>
< xs:schema  targetNamespace ="http://xmlbeans.apache.org/samples/template/xmlbean"
    xmlns:po
="http://xmlbeans.apache.org/samples/template/xmlbean"
    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
="po: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 ="po:addressType"   />
        
</ xs:sequence >
    
</ xs:complexType >
    
< xs:complexType  name ="addressType" >
        
< xs:sequence >
            
< xs:element  name ="primaryAddress"  type ="po:primaryAddressType"   />
            
< xs:element  name ="billingAddress"  type ="po: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. 利用ANT工具来生成Java Classes
ANT文件可以参照下面文件作成:
<!--
Copyright 2004 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 
-->
< project  name ="SampleTemplate"  default ="build" >

    
< property  environment ="env" />

    
< path  id ="SampleTemplate.path" >
        
< path  refid ="xmlbeans.path" />
        
< fileset  dir ="lib"  includes ="*.jar" />
        
< pathelement  path ="build/classes" />
    
</ path >

    
< target  name ="init"  depends  = "clean" >
        
< property  name ="xmlbeans.home"  value ="${env.XMLBEANS_HOME}" />
        
< echo  message ="xmlbeans.home: ${xmlbeans.home}" />

        
<!--  check for xbean.jar from binary distribution  -->
        
< available
            
property ="xmlbeans.lib"
            value
="${xmlbeans.home}/lib"
            file
="${xmlbeans.home}/lib/xbean.jar"   />

        
<!--  check for xbean.jar compiled from source  -->
        
< available
            
property ="xmlbeans.lib"
            value
="${xmlbeans.home}/build/lib"
            file
="${xmlbeans.home}/build/lib/xbean.jar"   />

        
< fail  message ="Set XMLBEANS_HOME in your enviornment."
            unless
="xmlbeans.lib" />

        
< echo  message ="xmlbeans.lib: ${xmlbeans.lib}" />
        
< path  id ="xmlbeans.path" >
            
< fileset  dir ="${xmlbeans.lib}"  includes ="*.jar" />
        
</ path >

        
< taskdef  name ="xmlbean"
            classname
="org.apache.xmlbeans.impl.tool.XMLBean"
            classpathref
="xmlbeans.path" />
    
</ target >

    
<!--  ========================== clean ====  -->

    
< target  name ="clean" >
        
< delete  dir ="build" />
        
< delete  file ="lib/schemas.jar" />
        
< delete  dir ="XMLBeansSrc" />
        
< mkdir  dir ="XMLBeansSrc" />
    
</ target >

    
<!--  ========================== build ====  -->

    
< target  name ="build"  depends ="init,schemas.jar,SampleTemplate.classes" >
    
</ target >

    
< target  name ="schemas.check" >
        
< uptodate  property ="schemas.notRequired"
            targetfile
="lib/schemas.jar" >
            
< srcfiles  dir ="schemas"  includes ="**/*.xsd" />
        
</ uptodate >
    
</ target >

    
< target  name ="schemas.jar"  depends ="init,schemas.check"
        unless
="schemas.notRequired" >

        
< xmlbean  schema ="schemas"
            destfile
="lib/schemas.jar"
            srcgendir
="XMLBeansSrc"
            classpathref
="xmlbeans.path"
            debug
="on"
            
/>
    
</ target >

    
< target  name ="SampleTemplate.classes"  depends ="init" >
        
< mkdir  dir ="build/classes" />
        
< javac  srcdir ="src"
            destdir
="build/classes"
            classpathref
="SampleTemplate.path"
            debug
="on"
            source
="1.5"
            
/>
    
</ target >

    
<!--  ========================== run ====  -->

    
< target  name ="run"  depends ="init,build" >
        
< echo  message ="============================== running SampleTemplate" />
        
< java
            
classname ="org.apache.xmlbeans.samples.template.SampleTemplate"
            classpathref
="SampleTemplate.path"
            fork
="true" >
            
< arg  line ="xml/hello.xml" />
            
< arg  line ="xml/bad.xml" />
        
</ java >
    
</ target >

    
<!--  ========================== test ====  -->

    
< target  name ="test"  depends ="init,build" >
        
< echo  message ="============================== testing SampleTemplate" />
        
< java
            
classname ="org.apache.xmlbeans.samples.template.SampleTemplateTest"
            classpathref
="SampleTemplate.path"
            fork
="true" >
            
< arg  line ="xml/hello.xml" />
            
< arg  line ="xml/bad.xml" />
        
</ java >
    
</ target >

</ project >


       其实, 生成的Java源代码没有多大作用,我们要的是jar文件.我们先看一下生成文件一览:
XMLBeansSrc/org/apache/xmlbeans/samples/template/xmlbean下生成的Classes.
 CustomersDocument.java                          -- 整个XML文档的Java Class映射
 CustomerType.java                                     -- 节点sustomer的映射
 AddressType.java                                         -- 节点address的映射
 BillingAddressType.java                               -- 节点billingAddress的映射
 PrimaryAddressType.java                                -- 节点primaryAddress的映射
XMLBeansSrc/org/apache/xmlbeans/samples/template/xmlbean/impl下生成的Classes是上面文件的接口类.


       好了,到此我们所有的准备工作已经完成了. 下面就开始进入重点:利用刚才生成的jar文件读写XML.

五、利用XMLBean读XML文件
六、利用XMLBean写XML文件
七、利用XMLBean修改XML文件
八、利用XMLBean删除一个customer



    新建一个Java Class: CustomerXMLBean.  源码如下:
    

package  com.sample.reader;

import  java.io.File;

import  org.apache.xmlbeans.XmlOptions;
import  org.apache.xmlbeans.samples.template.xmlbean.AddressType;
import  org.apache.xmlbeans.samples.template.xmlbean.BillingAddressType;
import  org.apache.xmlbeans.samples.template.xmlbean.CustomerType;
import  org.apache.xmlbeans.samples.template.xmlbean.CustomersDocument;
import  org.apache.xmlbeans.samples.template.xmlbean.PrimaryAddressType;

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();
        }

    }


    
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();
        }

    }


    
private void insertCustomer() {
        
try {
            File xmlFile 
= new File(filename);
            
// Create Document
            CustomersDocument doc = CustomersDocument.Factory.parse(xmlFile);
            
// Add new customer
            CustomersDocument.Customers customer = doc.getCustomers();
            CustomerType importCustomer 
= customer.addNewCustomer();
            
// set customer info
            importCustomer.setId(3);
            importCustomer.setFirstname(
"Jessica3");
            importCustomer.setLastname(
"Lim");
            importCustomer.setGender(
"female");
            importCustomer.setPhoneNumber(
"1234567");
            
// Add new address
            AddressType address = importCustomer.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");
            importCustomer 
= customer.insertNewCustomer(1);
            
// set customer info
            importCustomer.setId(4);
            importCustomer.setFirstname(
"Jessica4");
            importCustomer.setLastname(
"Lim");
            importCustomer.setGender(
"female");
            importCustomer.setPhoneNumber(
"1234567");
            
// Add new address
            address = importCustomer.addNewAddress();
            
// Add new PrimaryAddress
            primaryAddress = address.addNewPrimaryAddress();
            primaryAddress.setPostalCode(
"350106");
            primaryAddress.setAddressLine1(
"#25-1");
            primaryAddress.setAddressLine2(
"SHINSAYAMA 2-CHOME");
            
// Add new BillingAddress
            billingAddress = address.addNewBillingAddress();
            billingAddress.setReceiver(
"Ms Danielle");
            billingAddress.setPostalCode(
"350107");
            billingAddress.setAddressLine1(
"#167");
            billingAddress.setAddressLine2(
"NORTH TOWER HARBOUR CITY");
            XmlOptions xmlOptions 
= new XmlOptions();
            xmlOptions.setSavePrettyPrint();
            doc.save(xmlFile, xmlOptions);
        }
 catch (Exception ex) {
            ex.printStackTrace();
        }

    }


    
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();
        }

    }


    
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();
        }

    }


    
private void println(String str) {
        System.out.println(str);
    }


    
public static void main(String[] args) {
        String filename 
= "xml/customers.xml";
        CustomerXMLBean customerXMLBean 
= new CustomerXMLBean(filename);
        customerXMLBean.customerReader();
        filename 
= "xml/customers2.xml";
        customerXMLBean 
= new CustomerXMLBean(filename);
        customerXMLBean.createCustomer();
        filename 
= "xml/customersForUpdate.xml";
        customerXMLBean 
= new CustomerXMLBean(filename);
        customerXMLBean.updateCustomer(
2"test");
        filename 
= "xml/customersForDeleteAndInsert.xml";
        customerXMLBean 
= new CustomerXMLBean(filename);
        customerXMLBean.deleteCustomer(
2);
        customerXMLBean.insertCustomer();
    }

}


    运行它,参看输出结果:
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的威力.

   
    九、查询XML

    除了本文在以上讲述的,利用XMLBean能轻轻松松完成XML的读写操作外,结合XPath和XQuery,
   XMLBean还能完成象SQL查询数据库一样方便地查询XML数据. 关于XML查询以及如何创建XML数据库, 我将在另一篇文章里讨论.



十、结束语
    XMLBean能帮助我们轻易读写XML,这将有助于我们降低XML的学习和使用,有了这个基础,
    开发人员将为学习更多地XML相关技术和Web Services,JMS等其他J2EE技术打下良好地基础.


本文参考文献:叶枫 利用XMLBean轻轻松松读写XML
http://blog.matrix.org.cn/page/叶枫

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值