Google Analytics

顯示具有 xml 標籤的文章。 顯示所有文章
顯示具有 xml 標籤的文章。 顯示所有文章

2014年9月1日 星期一

使用XStream將java物件轉換成xml資料格式

簡介

之前介紹過Apache Commons Digester套件,可以將以xml格式表示的資料轉換成Java的model物件(請參考該網誌)。若要進行相反的動作,即將Java的model物件轉換成xml格式,可以使用XStream(http://xstream.codehaus.org/)套件。

XStream的使用方式如下:
XStream xstream = new XStream();

xstream.alias("addressBook", AddressBook.class);
xstream.alias("person", Person.class);
xstream.alias("address", Address.class);

xstream.addImplicitCollection(AddressBook.class, "personList"); // to avoid <personList> tag
xstream.addImplicitCollection(Person.class, "addressList"); // to avoid <addressList> tag

String xml = xstream.toXML(addressBook1);

logger.info("addressBook.toXML(use xstream) = " + xml);

執行結果:
[2014/09/01 11:27:54]  INFO tw.blogspot.saminjava.demo.xstream.AddressBook:171 - addressBook.toXML(use xstream) = <addressBook>
  <personList>
    <person>
      <id>1</id>
      <name>Gonzo</name>
      <emailMap>
        <entry>
          <string>business</string>
          <string>gonzo@muppets.com</string>
        </entry>
      </emailMap>
      <addressList>
        <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>
      </addressList>
    </person>
    <person>
      <id>2</id>
      <name>Kermit</name>
      <emailMap>
        <entry>
          <string>home</string>
          <string>kermie@acme.com</string>
        </entry>
        <entry>
          <string>business</string>
          <string>kermit@muppets.com</string>
        </entry>
      </emailMap>
      <addressList>
        <address>
          <type>business</type>
          <street>987 Brown Rd</street>
          <city>Las Cruces</city>
          <state>NM</state>
          <zip>75321</zip>
          <country>USA</country>
        </address>
      </addressList>
    </person>
  </personList>
</addressBook>

若是使用XStream產出XML格式,要反轉回Java物件,其使用方式如下:
AddressBook addressBook2 = (AddressBook)xstream.fromXML(xml);

logger.info("addressBook2.toString(use xstream) = " + addressBook2.toString());

執行結果:
[2014/09/01 11:44:03]  INFO tw.blogspot.saminjava.demo.xstream.AddressBook:175 - addressBook2.toString(use xstream) = tw.blogspot.saminjava.demo.xstream.AddressBook@11f2ee1[personList=[tw.blogspot.saminjava.demo.xstream.Person@3ecfff[id=1,name=Gonzo,emailMap={business=gonzo@muppets.com},addressList=[tw.blogspot.saminjava.demo.xstream.Address@1c99159[type=home,street=123 Maine Ave.,city=Las Vegas,state=NV,zip=01234,country=USA], tw.blogspot.saminjava.demo.xstream.Address@65a77f[type=business,street=234 Maple Dr.,city=Los Angeles,state=CA,zip=98765,country=USA]]], tw.blogspot.saminjava.demo.xstream.Person@1d7ad1c[id=2,name=Kermit,emailMap={home=kermie@acme.com, business=kermit@muppets.com},addressList=[tw.blogspot.saminjava.demo.xstream.Address@a61164[type=business,street=987 Brown Rd,city=Las Cruces,state=NM,zip=75321,country=USA]]]]]

XStream除了XML格式外,還可以另產出JSON格式,其使用方式如下:
xstream = new XStream(new JettisonMappedXmlDriver());

xstream.setMode(XStream.NO_REFERENCES);

xstream.alias("addressBook", AddressBook.class);
xstream.alias("person", Person.class);
xstream.alias("address", Address.class);

xstream.addImplicitCollection(AddressBook.class, "personList"); // to avoid <personList> tag
xstream.addImplicitCollection(Person.class, "addressList"); // to avoid <addressList> tag

String json = xstream.toXML(addressBook1);

logger.info("addressBook.toJSON(use xstream) = " + json);

執行結果:
[2014/09/01 11:50:04]  INFO tw.blogspot.saminjava.demo.xstream.AddressBook:195 - addressBook.toJSON(use xstream) = {"addressBook":{"person":[{"id":1,"name":"Gonzo","emailMap":[{"entry":{"string":["business","gonzo@muppets.com"]}}],"address":[{"type":"home","street":"123 Maine Ave.","city":"Las Vegas","state":"NV","zip":"01234","country":"USA"},{"type":"business","street":"234 Maple Dr.","city":"Los Angeles","state":"CA","zip":98765,"country":"USA"}]},{"id":2,"name":"Kermit","emailMap":[{"entry":[{"string":["home","kermie@acme.com"]},{"string":["business","kermit@muppets.com"]}]}],"address":{"type":"business","street":"987 Brown Rd","city":"Las Cruces","state":"NM","zip":75321,"country":"USA"}}]}}

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