Google Analytics

2014年7月17日 星期四

使用Apache Commons Digester將xml資料轉換成java物件模型

簡介

Apache Commons的Digester套件可以將以xml格式表示的資料,剖析後轉成Java的model物件。

假設我們的資料格式如下:
<?xml version='1.0'?>
<addressBook>
  <person id="1" category="acquaintance">
    <name>Gonzo</name>
    <email type="business">gonzo@muppets.com</email>
    <address>
      <type>home</type>
      <street>123 Maine Ave.</street>
      <city>Las Vegas</city>
      <state>NV</state>
      <zip>01234</zip>
      <country>USA</country>
    </address>
    <address>
      <type>business</type>
      <street>234 Maple Dr.</street>
      <city>Los Angeles</city>
      <state>CA</state>
      <zip>98765</zip>
      <country>USA</country>
    </address>
  </person>

  <person id="2" category="rolemodel">
    <name>Kermit</name>
    <email type="business">kermit@muppets.com</email>
    <email type="home">kermie@acme.com</email>
    <address>
      <type>business</type>
      <street>987 Brown Rd</street>
      <city>Las Cruces</city>
      <state>NM</state>
      <zip>75321</zip>
      <country>USA</country>
    </address>
  </person>
</addressBook>

首先,我們需要準備AddressBook、Persion、Address的類別,並建立對應的屬性與getter/setter方法,來映射這份XML的資料。接下來就輪到Digester上場了(完整source code按此)。

由AddressBook類別的main方法開始:
public static void main(String[] args) {
           logger.info("main() - start");
          
           try {
                     AddressBook addressBook = new AddressBook("example.xml");
                     logger.info("addressBooktoString() = " + addressBook.toString());
                    
           } catch (Exception ex) {
                     logger.error("main() - exception: ", ex);
           }
          
           logger.info("main() - end");

}
指定了"example.xml"檔案為來源資料,使用XML中的root tag的映射物件的建構子,最後期望是能完整映射出整份XML的資料。

建構子中呼叫了parse()方法負責主要的剖析與映射工作:
public AddressBook(String fileName) throws Exception {
           super();
           this.parse(fileName);
}

parse()方法中展示了使用Digester的基本程式寫法架構,並再次呼叫addDigesterRules()方法負責物件與屬性的映射工作:
protected void parse(String fileName) throws IOException, FileNotFoundException, SAXException, IllegalArgumentException {
          
           if ((fileName == null) || (fileName.toString().length() <= 0)) {
                     throw new IllegalArgumentException("parameter 'fileName' is required");
           }
          
           File file = new File(fileName);
           logger.debug("file = " + file.getAbsolutePath());
          
           if (!file.exists()) {
                     throw new FileNotFoundException(String.format("the file '%s' is not exist.", file.getAbsolutePath()));
           }
          
           // Create a Digester instance
           Digester digester = new Digester();
           digester.push(this);
          
            // Add rules to the digester that will be triggered while parsing occurs.
           this.addDigesterRules(digester);
          
           // Parse the input file.
           digester.parse(file);

}

addDigesterRules()方法內容:
protected void addDigesterRules(Digester digester) {
           digester.addObjectCreate("addressBook/person", Person.class);
           digester.addSetProperties("addressBook/person");
           digester.addSetNext("addressBook/person", "addPerson");
          
           digester.addCallMethod("addressBook/person/name", "setName", 1);
           digester.addCallParam("addressBook/person/name", 0);
          
           digester.addCallMethod("addressBook/person/email", "addEmail", 2);
           digester.addCallParam("addressBook/person/email", 0, "type");
           digester.addCallParam("addressBook/person/email", 1);
          
           digester.addObjectCreate("addressBook/person/address", Address.class);
           digester.addSetNext("addressBook/person/address", "addAddress");
           digester.addSetNestedProperties("addressBook/person/address");
}

執行結果:
[2014/07/18 14:34:17]  INFO tw.blogspot.saminjava.demo.digester.AddressBook:142 - main() - start
[2014/07/18 14:34:18]  INFO tw.blogspot.saminjava.demo.digester.AddressBook:146 - addressBooktoString() = tw.blogspot.saminjava.demo.digester.AddressBook@444cee32[personList=[tw.blogspot.saminjava.demo.digester.Person@23394894[id=1,name=Gonzo,emailMap={business=gonzo@muppets.com},addressList=[tw.blogspot.saminjava.demo.digester.Address@5cbfe9d[type=home,street=123 Maine Ave.,city=Las Vegas,state=NV,zip=01234,country=USA], tw.blogspot.saminjava.demo.digester.Address@13b8f864[type=business,street=234 Maple Dr.,city=Los Angeles,state=CA,zip=98765,country=USA]]], tw.blogspot.saminjava.demo.digester.Person@54bb7759[id=2,name=Kermit,emailMap={home=kermie@acme.com, business=kermit@muppets.com},addressList=[tw.blogspot.saminjava.demo.digester.Address@5f989f84[type=business,street=987 Brown Rd,city=Las Cruces,state=NM,zip=75321,country=USA]]]]]
[2014/07/18 14:34:18]  INFO tw.blogspot.saminjava.demo.digester.AddressBook:152 - main() - end