key words: Digester  解析xml

假设有下列xml文件:
<?xml version='1.0' encoding='utf-8'?>
<address-book>
    
<contact myType="individual">
        
<name>Zane Pasolini</name>
        
<address>999 W. Prince St.</address>
        
<city>New York</city>
        
<province>NY</province>
        
<postalcode>10013</postalcode>
        
<country>USA</country>
        
<telephone>1-212-345-6789</telephone>
    
</contact>
    
<contact myType="business">
        
<name>SAMOFIX d.o.o.</name>
        
<address>Ilica 47-2</address>
        
<city>Zagreb</city>
        
<province></province>
        
<postalcode>10000</postalcode>
        
<country from="cn">Croatia</country>
        
<telephone>385-1-123-4567</telephone>
    
</contact>
</address-book>

这是一份常用到的文件,现在我们需要将之映射到java bean,用Digester解析显得非常简单
public class AddressBookParser
{
    
/**
     * Prints the contact information to standard output.
     *
     * 
@param contact the <code>Contact</code> to print out
     
*/
    
public void addContact(Contact contact)
    {
        System.out.println(
"TYPE: " + contact.getType());
        System.out.println(
"NAME: " + contact.getName());
        System.out.println(
"    ADDRESS:    " + contact.getAddress());
        System.out.println(
"    CITY:       " + contact.getCity());
        System.out.println(
"    PROVINCE:   " + contact.getProvince());
        System.out.println(
"    POSTALCODE: " + contact.getPostalcode());
        System.out.println(
"    COUNTRY:    " + contact.getCountry());
        System.out.println(
"    COUNTRY-From:    " + contact.getCountryFrom());
        System.out.println(
"    TELEPHONE:  " + contact.getTelephone());
    }

    
/**
     * Configures Digester rules and actions, parses the XML file specified
     * as the first argument.
     *
     * 
@param args command line arguments
     
*/
    
public static void main(String[] args) throws IOException, SAXException
    {
        
// instantiate Digester and disable XML validation
        Digester digester = new Digester();
        digester.setValidating(
false);

        
// instantiate AddressBookParser class
        digester.addObjectCreate("address-book", AddressBookParser.class );
        
// instantiate Contact class
        digester.addObjectCreate("address-book/contact", Contact.class );

        
// set type property of Contact instance when 'type' attribute is found
        
//对有属性的值通过setProperties方法

        digester.addSetProperties(
"address-book/contact",         "myType""type" );

        
// set different properties of Contact instance using specified methods
        
//addCallMethod与addBeanPropertySetter等价
        
// 参数 0代表一个参数,默认就是当前读的数据

        digester.addCallMethod(
"address-book/contact/name",       "setName"0);
        digester.addCallMethod(
"address-book/contact/address",    "setAddress"0);
        digester.addCallMethod(
"address-book/contact/address",    "setAddress",0);
        digester.addCallMethod(
"address-book/contact/city",       "setCity"0);
        digester.addCallMethod(
"address-book/contact/province",   "setProvince"0);
        digester.addCallMethod(
"address-book/contact/postalcode""setPostalcode"0);
        digester.addCallMethod(
"address-book/contact/country",    "setCountry"0);



        
//增加country的属性 : from
        digester.addSetProperties("address-book/contact/country","from","countryFrom");
        digester.addCallMethod(
"address-book/contact/telephone",  "setTelephone"0);

        
// call 'addContact' method when the next 'address-book/contact' pattern is seen
        digester.addSetNext("address-book/contact",               "addContact" );

        
// now that rules and actions are configured, start the parsing process
        AddressBookParser abp = (AddressBookParser) digester.parse(new File("c:\\addressbook.xml"));
    }

    
/**
     * JavaBean class that holds properties of each Contact entry.
     * It is important that this class be public and static, in order for
     * Digester to be able to instantiate it.
     
*/
    
public static class Contact
    {
        
private String type;
        
private String name;
        
private String address;
        
private String city;
        
private String province;
        
private String postalcode;
        
private String country;
        //增加一个country的属性: from
        private String countryFrom;
        private String telephone;

        
public void setType(String newType)
        {
            type 
= newType;
        }
        
public String getType()
        {
            
return type;
        }

        
public void setName(String newName)
        {
            name 
= newName;
        }
        
public String getName()
        {
            
return name;
        }

        
public void setAddress(String newAddress)
        {
            address 
= newAddress;
        }
        
public String getAddress()
        {
            
return address;
        }

        
public void setCity(String newCity)
        {
            city 
= newCity;
        }
        
public String getCity()
        {
            
return city;
        }

        
public void setProvince(String newProvince)
        {
            province 
= newProvince;
        }
        
public String getProvince()
        {
            
return province;
        }

        
public void setPostalcode(String newPostalcode)
        {
            postalcode 
= newPostalcode;
        }
        
public String getPostalcode()
        {
            
return postalcode;
        }

        
public void setCountry(String newCountry)
        {
            country 
= newCountry;
        }
        
public String getCountry()
        {
            
return country;
        }

        
public void setTelephone(String newTelephone)
        {
            telephone 
= newTelephone;
        }
        
public String getTelephone()
        {
            
return telephone;
        }

        
public String getCountryFrom() {
            
return countryFrom;
        }

        
public void setCountryFrom(String countryFrom) {
            
this.countryFrom = countryFrom;
        }
    }
}


AjaxChat 中的读取房间信息的方式显得更简洁
房间的xml配置文件如下:
<rooms>
  
<room id="1" name="General Topics" />
  
<room id="2" name="Programming" />
  
<room id="3" name="Movies" />
  
<room id="4" name="Music" />
  
<room id="5" name="Television" />
</rooms>

解析代码如下 :
public synchronized void init(InputStream isConfigFile) {

        log.debug(
"init()");
        
if (isConfigFile != null) {
            
// Read in rooms config and create beans, hand off to DAO.
            Digester digester = new Digester();
            digester.setValidating(
false);
            digester.push(
this);
            digester.addObjectCreate(
"rooms/room",
                    
"org.apache.struts.apps.ajaxchat.dto.RoomDTO");
            //注意这里,如果xl的属性名称和bean的属性名称完全对应,则直接提供xml的位置即可
            digester.addSetProperties(
"rooms/room");
            digester.addSetNext(
"rooms/room""addRoom");
            
try {
                digester.parse(isConfigFile);
                log.info(
"***** Rooms = " + rooms);
            } 
catch (IOException ioe) {
                ioe.printStackTrace();
            } 
catch (SAXException se) {
                se.printStackTrace();
            }
        }

    } 
// End init().

如果在xml文件中增加非attribute则更改后的配置文件如下:

<rooms>
  
<room id="1" name="General Topics" />
  
<room id="2" name="Programming" />
  
<room id="3" name="Movies" />
  
<room id="4" name="Music" />
  
<room id="5" name="Television" />
  
<room>
    
<id>6</id>
    
<name>shit</name>
  
</room>
  
<room>
    
<id>7</id>
    
<name>haha</name>
  
</room>
</rooms>
对应的解析如下:
public synchronized void init(InputStream isConfigFile) {

        log.debug(
"init()");
        
if (isConfigFile != null) {
            
// Read in rooms config and create beans, hand off to DAO.
            Digester digester = new Digester();
            digester.setValidating(
false);
            digester.push(
this);
            digester.addObjectCreate(
"rooms/room",
                    
"org.apache.struts.apps.ajaxchat.dto.RoomDTO");
            digester.addSetProperties(
"rooms/room");
            //增加addCallMethod方法
            digester.addCallMethod(
"rooms/room/id","setId",0);
            digester.addCallMethod(
"rooms/room/name","setName",0);
            digester.addSetNext(
"rooms/room""addRoom");
            
try {
                digester.parse(isConfigFile);
                log.info(
"***** Rooms = " + rooms);
            } 
catch (IOException ioe) {
                ioe.printStackTrace();
            } 
catch (SAXException se) {
                se.printStackTrace();
            }
        }

    } 
// End init().