近期研究 Java 物件與 XML 互轉,發現 Castor 是輕量級的優秀選擇。參考網上資料並修正其中錯誤,在 Eclipse 中完成一個完整範例:讀取 page.xml → 反序列化為 Java 物件 → 列印內容 → 序列化輸出 d.xml。完整代碼結構如下:
<HOMEPAGECOLLECTION name="this is sample">
<HOMEPAGECONTENT id="1">
<NAME>About Us</NAME>
<NAVLINK>1.JSP</NAVLINK>
<ICON>images/icon.gif</ICON>
<DESCRIPTION>An in-depth look at creating applications with XML.</DESCRIPTION>
</HOMEPAGECONTENT>
<HOMEPAGECONTENT id="2">
<NAME>Product|Service</NAME>
<NAVLINK>2.JSP</NAVLINK>
<ICON>images/icon.gif</ICON>
<DESCRIPTION>let's tak a look at our products.</DESCRIPTION>
</HOMEPAGECONTENT>
</HOMEPAGECOLLECTION>
package tryForCastor;
public class Homepagecontent implements java.io.Serializable {
private static final long serialVersionUID = 3689909565688657717L;
private Integer id;
private String name, navlink, icon, description;
// 無參建構子、getter/setter 略
}
package tryForCastor;
import java.util.*;
public class Homepagecollection implements java.io.Serializable {
private static final long serialVersionUID = 3545239128603309878L;
private String siteName;
private List<Homepagecontent> homepagecontents = new ArrayList<>();
public void addHomePageContent(Homepagecontent hpc) { homepagecontents.add(hpc); }
public List<Homepagecontent> getHomepagecontents() { return homepagecontents; }
public String getName() { return siteName; }
public void setName(String name) { this.siteName = name; }
}
<MAPPING>
<DESCRIPTION>a map file for our new template system</DESCRIPTION>
<CLASS name="Homepagecontent">
<MAP-TO xml="homepagecontent">
<FIELD name="id" type="integer">
<BIND-XML name="id" node="attribute"/>
</FIELD>
<FIELD name="name" type="string"><BIND-XML name="NAME"/></FIELD>
<FIELD name="navlink" type="string"><BIND-XML name="NAVLINK"/></FIELD>
<FIELD name="icon" type="string"><BIND-XML name="ICON"/></FIELD>
<FIELD name="description" type="string"><BIND-XML name="DESCRIPTION"/></FIELD>
</MAP-TO>
</CLASS>
<CLASS name="Homepagecollection">
<MAP-TO xml="homepagecollection">
<FIELD name="name" type="string">
<BIND-XML name="name" node="attribute"/>
</FIELD>
<FIELD name="homepagecontents" type="Homepagecontent" collection="collection"/>
</MAP-TO>
</CLASS>
</MAPPING>
關鍵點:node="attribute" 對應 XML 屬性;collection="collection" 聲明 List 集合映射;巢狀結構需層層對應。
package tryForCastor;
import java.io.*;
import java.util.*;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Marshaller;
import org.exolab.castor.xml.Unmarshaller;
public class tryCastor {
private Mapping mapping;
private String xmlFile;
public void HomePageHandle(String mapFile, String xmlFile) throws Exception {
this.xmlFile = xmlFile;
mapping = new Mapping();
mapping.loadMapping(mapFile);
}
public Homepagecollection read() throws Exception {
Unmarshaller un = new Unmarshaller(Homepagecollection.class);
un.setMapping(mapping);
FileReader in = new FileReader(xmlFile);
Homepagecollection hc = (Homepagecollection) un.unmarshal(in);
in.close();
return hc;
}
public FileWriter write(String outFile, Object obj) throws Exception {
FileWriter out = new FileWriter(outFile);
Marshaller mar = new Marshaller(out);
mar.setMapping(mapping);
mar.marshal(obj);
return out;
}
public static void main(String[] args) {
tryCastor tc = new tryCastor();
try {
tc.HomePageHandle("mapping.xml", "page.xml");
Homepagecollection hc = tc.read();
for (Homepagecontent h : hc.getHomepagecontents()) {
System.out.println(h.getDescription());
System.out.println(h.getIcon());
System.out.println(h.getName());
System.out.println(h.getNavlink());
System.out.println(h.getId());
System.out.println("+++++++++++++++++++++++");
}
FileWriter fw = tc.write("d.xml", hc);
if (fw != null) fw.close();
} catch (Exception e) { e.printStackTrace(); }
}
}
Castor 適合中小型專案、需精細控制 XML 結構的場景。掌握映射檔寫法,是驅動 Castor 的關鍵技能。