Castor-解析xml的另外一种方法

众所周知,xml解析一般有SAX和DOM两种方式。

SAX是基于事件驱动的行解析,具有速度快,占用内存小的优点,但是实现麻烦,代码可读性较差。

DOM是基于树状结构的解析,也就是其将整个xml文档看作一棵树,然后按照不同的分支/节点解析,更具面向对象的风格。缺点就是其需要将整个xml读到内存中,所以占用内存较多,而且比较慢。

实际应用中,很多场景是:程序将xml中的数据解析出来后,然后生成一些java对象来保持这些数据。于是需要在代码中频繁调用创建对象、get/set等的代码。


0.下面是一个使用DOM解析文档的例子。

Address.java

  1. /**
  2. *
  3. */
  4. package com.hayden.model;
  5. /**
  6. * @author HaydenWang
  7. *
  8. */
  9. public class Address implements java.io.Serializable {
  10. private static final long serialVersionUID = 1863183127959586043L;
  11. private Long id;
  12. private String detail;
  13. public Long getId() {
  14. return id;
  15. }
  16. public void setId(Long id) {
  17. this.id = id;
  18. }
  19. public String getDetail() {
  20. return detail;
  21. }
  22. public void setDetail(String detail) {
  23. this.detail = detail;
  24. }
  25. @Override
  26. public String toString() {
  27. return "Address [detail=" + detail + ", id=" + id + "]";
  28. }
  29. @Override
  30. public int hashCode() {
  31. final int prime = 31;
  32. int result = 1;
  33. result = prime * result + ((detail == null) ? 0 : detail.hashCode());
  34. result = prime * result + ((id == null) ? 0 : id.hashCode());
  35. return result;
  36. }
  37. @Override
  38. public boolean equals(Object obj) {
  39. if (this == obj)
  40. return true;
  41. if (obj == null)
  42. return false;
  43. if (getClass() != obj.getClass())
  44. return false;
  45. Address other = (Address) obj;
  46. if (detail == null) {
  47. if (other.detail != null)
  48. return false;
  49. } else if (!detail.equals(other.detail))
  50. return false;
  51. if (id == null) {
  52. if (other.id != null)
  53. return false;
  54. } else if (!id.equals(other.id))
  55. return false;
  56. return true;
  57. }
  58. }
/** * */ package com.hayden.model; /** * @author HaydenWang * */ public class Address implements java.io.Serializable { private static final long serialVersionUID = 1863183127959586043L; private Long id; private String detail; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getDetail() { return detail; } public void setDetail(String detail) { this.detail = detail; } @Override public String toString() { return "Address [detail=" + detail + ", id=" + id + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((detail == null) ? 0 : detail.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Address other = (Address) obj; if (detail == null) { if (other.detail != null) return false; } else if (!detail.equals(other.detail)) return false; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }

User.java

  1. /**
  2. *
  3. */
  4. package com.hayden.model;
  5. import java.util.Date;
  6. /**
  7. * @author HaydenWang
  8. *
  9. */
  10. public class User {
  11. private Long id;
  12. private String name;
  13. private Address address;
  14. private Date createDate;
  15. public Long getId() {
  16. return id;
  17. }
  18. public void setId(Long id) {
  19. this.id = id;
  20. }
  21. public String getName() {
  22. return name;
  23. }
  24. public void setName(String name) {
  25. this.name = name;
  26. }
  27. public Address getAddress() {
  28. return address;
  29. }
  30. public void setAddress(Address address) {
  31. this.address = address;
  32. }
  33. public Date getCreateDate() {
  34. return createDate;
  35. }
  36. public void setCreateDate(Date createDate) {
  37. this.createDate = createDate;
  38. }
  39. @Override
  40. public int hashCode() {
  41. final int prime = 31;
  42. int result = 1;
  43. result = prime * result + ((address == null) ? 0 : address.hashCode());
  44. result = prime * result
  45. + ((createDate == null) ? 0 : createDate.hashCode());
  46. result = prime * result + ((id == null) ? 0 : id.hashCode());
  47. result = prime * result + ((name == null) ? 0 : name.hashCode());
  48. return result;
  49. }
  50. @Override
  51. public boolean equals(Object obj) {
  52. if (this == obj)
  53. return true;
  54. if (obj == null)
  55. return false;
  56. if (getClass() != obj.getClass())
  57. return false;
  58. User other = (User) obj;
  59. if (address == null) {
  60. if (other.address != null)
  61. return false;
  62. } else if (!address.equals(other.address))
  63. return false;
  64. if (createDate == null) {
  65. if (other.createDate != null)
  66. return false;
  67. } else if (!createDate.equals(other.createDate))
  68. return false;
  69. if (id == null) {
  70. if (other.id != null)
  71. return false;
  72. } else if (!id.equals(other.id))
  73. return false;
  74. if (name == null) {
  75. if (other.name != null)
  76. return false;
  77. } else if (!name.equals(other.name))
  78. return false;
  79. return true;
  80. }
  81. @Override
  82. public String toString() {
  83. return "User [address=" + address + ", createDate=" + createDate
  84. + ", id=" + id + ", name=" + name + "]";
  85. }
  86. }
/** * */ package com.hayden.model; import java.util.Date; /** * @author HaydenWang * */ public class User { private Long id; private String name; private Address address; private Date createDate; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((address == null) ? 0 : address.hashCode()); result = prime * result + ((createDate == null) ? 0 : createDate.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; User other = (User) obj; if (address == null) { if (other.address != null) return false; } else if (!address.equals(other.address)) return false; if (createDate == null) { if (other.createDate != null) return false; } else if (!createDate.equals(other.createDate)) return false; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "User [address=" + address + ", createDate=" + createDate + ", id=" + id + ", name=" + name + "]"; } }

Domparser.java

  1. /**
  2. *
  3. */
  4. package com.hayden.dom;
  5. import java.text.ParseException;
  6. import java.text.SimpleDateFormat;
  7. import java.util.Date;
  8. import org.apache.log4j.Logger;
  9. import org.w3c.dom.Document;
  10. import org.w3c.dom.Node;
  11. import org.w3c.dom.NodeList;
  12. import com.hayden.castor.XmlUtil;
  13. import com.hayden.model.Address;
  14. import com.hayden.model.User;
  15. /**
  16. * @author HaydenWang
  17. *
  18. */
  19. public class DomParser {
  20. private static final Logger logger = Logger.getLogger(DomParser.class);
  21. private static final String FORMAT = "yyyy-MM-dd";
  22. public User parseUser(String fileName) {
  23. Document doc = XmlUtil.getDocumentFromFile(fileName);
  24. Node node = doc.getFirstChild();
  25. User user = new User();
  26. if ("user".equals(node.getNodeName())) {
  27. NodeList childNodes = node.getChildNodes();
  28. int length = childNodes.getLength();
  29. for (int i = 0; i < length; i++) {
  30. Node subNode = childNodes.item(i);
  31. String nodeName = subNode.getNodeName();
  32. if ("address".equals(nodeName)) {// this is address node
  33. Address addr = parseAddress(subNode);
  34. user.setAddress(addr);
  35. } else if ("name".equals(nodeName)) { // this is name node
  36. String userName = getNodeValue(subNode);
  37. user.setName(userName);
  38. } else if ("id".equals(nodeName)) {
  39. String idString = getNodeValue(subNode);
  40. user.setId(Long.parseLong(idString));
  41. }else if("create-date".equals(nodeName)){
  42. String dateString = getNodeValue(subNode);
  43. Date date = parseDate(dateString);
  44. user.setCreateDate(date);
  45. }
  46. }
  47. }
  48. return user;
  49. }
  50. private Address parseAddress(Node addrNode) {
  51. Address addr = new Address();
  52. NodeList nodeList = addrNode.getChildNodes();
  53. int length = nodeList.getLength();
  54. for (int i = 0; i < length; i++) {
  55. Node node = nodeList.item(i);
  56. String nodeName = node.getNodeName();
  57. if ("id".equals(nodeName)) {
  58. String idString = getNodeValue(node);
  59. addr.setId(Long.parseLong(idString));
  60. } else if ("details".equals(nodeName)) {
  61. addr.setDetail(getNodeValue(node));
  62. }
  63. }
  64. return addr;
  65. }
  66. /**
  67. * get the value for the node with format <name>helen</name>
  68. *
  69. * @param node
  70. * @return
  71. */
  72. private String getNodeValue(Node node) {
  73. String nodeValue = null;
  74. if (null != node) {
  75. NodeList childNodeList = node.getChildNodes();
  76. if (childNodeList != null) {
  77. for (int i = 0, j = childNodeList.getLength(); i < j; i++) {
  78. Node currentNode = childNodeList.item(i);
  79. nodeValue = currentNode.getNodeValue();
  80. break;
  81. }
  82. } else {
  83. logger.debug("The node is empty");
  84. }
  85. logger.debug(" The nodeName: " + node.getNodeName()
  86. + ", and the value: " + nodeValue);
  87. } else {
  88. logger.warn("The node is null, so can't take its value");
  89. }
  90. return nodeValue;
  91. }
  92. private static final Date parseDate(String input){
  93. SimpleDateFormat formatter = new SimpleDateFormat(FORMAT);
  94. Date date = null;
  95. try {
  96. date = formatter.parse((String) input);
  97. } catch (ParseException px) {
  98. throw new IllegalArgumentException(px.getMessage());
  99. }
  100. return date;
  101. }
  102. }
/** * */ package com.hayden.dom; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.hayden.castor.XmlUtil; import com.hayden.model.Address; import com.hayden.model.User; /** * @author HaydenWang * */ public class DomParser { private static final Logger logger = Logger.getLogger(DomParser.class); private static final String FORMAT = "yyyy-MM-dd"; public User parseUser(String fileName) { Document doc = XmlUtil.getDocumentFromFile(fileName); Node node = doc.getFirstChild(); User user = new User(); if ("user".equals(node.getNodeName())) { NodeList childNodes = node.getChildNodes(); int length = childNodes.getLength(); for (int i = 0; i < length; i++) { Node subNode = childNodes.item(i); String nodeName = subNode.getNodeName(); if ("address".equals(nodeName)) {// this is address node Address addr = parseAddress(subNode); user.setAddress(addr); } else if ("name".equals(nodeName)) { // this is name node String userName = getNodeValue(subNode); user.setName(userName); } else if ("id".equals(nodeName)) { String idString = getNodeValue(subNode); user.setId(Long.parseLong(idString)); }else if("create-date".equals(nodeName)){ String dateString = getNodeValue(subNode); Date date = parseDate(dateString); user.setCreateDate(date); } } } return user; } private Address parseAddress(Node addrNode) { Address addr = new Address(); NodeList nodeList = addrNode.getChildNodes(); int length = nodeList.getLength(); for (int i = 0; i < length; i++) { Node node = nodeList.item(i); String nodeName = node.getNodeName(); if ("id".equals(nodeName)) { String idString = getNodeValue(node); addr.setId(Long.parseLong(idString)); } else if ("details".equals(nodeName)) { addr.setDetail(getNodeValue(node)); } } return addr; } /** * get the value for the node with format <name>helen</name> * * @param node * @return */ private String getNodeValue(Node node) { String nodeValue = null; if (null != node) { NodeList childNodeList = node.getChildNodes(); if (childNodeList != null) { for (int i = 0, j = childNodeList.getLength(); i < j; i++) { Node currentNode = childNodeList.item(i); nodeValue = currentNode.getNodeValue(); break; } } else { logger.debug("The node is empty"); } logger.debug(" The nodeName: " + node.getNodeName() + ", and the value: " + nodeValue); } else { logger.warn("The node is null, so can't take its value"); } return nodeValue; } private static final Date parseDate(String input){ SimpleDateFormat formatter = new SimpleDateFormat(FORMAT); Date date = null; try { date = formatter.parse((String) input); } catch (ParseException px) { throw new IllegalArgumentException(px.getMessage()); } return date; } }

通过上面的代码可以看出,有很多重复性的体力活(频繁判断节点的内容,然后set到对象中),而且当我们需要给这些对象增加或者修改一些属性的时候,就需要修改解析xml的程序。

那么是否有工具可以帮助实现这些事情呢?这就是Castor等Xml-Object mapping的工具做的事情。

Castor中有两个核心的操作:

  • marshaller:将对象转换成xml
  • unmarshaller: 从xml中解析并且生成java对象。

下面分别看看Castor在几种不同场景下的使用。

<!--[if !supportLists]-->1. <!--[endif]-->默认情况下,Castor会自动扫描类中的set/get方法,会自动将该属性和xml中的节点对应起来。如果属性不是String类型,在marshaller的时候将调用其toString()方法,同样在unmarshaller的时候,也会自动将其转型到所需类型。下面是一个使用Castor默认配置的例子。

  1. /**
  2. *
  3. */
  4. package com.hayden.castor;
  5. import static org.junit.Assert.fail;
  6. import java.io.FileReader;
  7. import java.io.FileWriter;
  8. import java.util.Date;
  9. import org.exolab.castor.xml.Marshaller;
  10. import org.exolab.castor.xml.Unmarshaller;
  11. import org.junit.Assert;
  12. import org.junit.Before;
  13. import org.junit.Test;
  14. import com.hayden.model.Address;
  15. import com.hayden.model.User;
  16. /**
  17. * @author HaydenWang
  18. *
  19. */
  20. public class SimpletestCastor {
  21. private User user;
  22. @Before
  23. public void init() {
  24. Address addr = new Address();
  25. addr.setId(100l);
  26. addr.setDetail("Baidu Building");
  27. user = new User();
  28. user.setId(1111L);
  29. user.setName("Helen");
  30. user.setAddress(addr);
  31. user.setCreateDate(new Date());
  32. }
  33. @Test
  34. public void simpleTest() {
  35. try {
  36. FileWriter writer = new FileWriter("simpleTest.xml");
  37. Marshaller.marshal(user, writer);
  38. // Create a Reader to the file to unmarshal from
  39. FileReader reader = new FileReader("simpleTest.xml");
  40. // Marshal the user object
  41. User userFromXml = (User) Unmarshaller.unmarshal(User.class, reader);
  42. System.out.println(userFromXml);
  43. Assert.assertEquals(user, userFromXml);
  44. } catch (Exception e) {
  45. e.printStackTrace();
  46. fail(e.getMessage());
  47. }
  48. }
  49. }
/** * */ package com.hayden.castor; import static org.junit.Assert.fail; import java.io.FileReader; import java.io.FileWriter; import java.util.Date; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.hayden.model.Address; import com.hayden.model.User; /** * @author HaydenWang * */ public class SimpletestCastor { private User user; @Before public void init() { Address addr = new Address(); addr.setId(100l); addr.setDetail("Baidu Building"); user = new User(); user.setId(1111L); user.setName("Helen"); user.setAddress(addr); user.setCreateDate(new Date()); } @Test public void simpleTest() { try { FileWriter writer = new FileWriter("simpleTest.xml"); Marshaller.marshal(user, writer); // Create a Reader to the file to unmarshal from FileReader reader = new FileReader("simpleTest.xml"); // Marshal the user object User userFromXml = (User) Unmarshaller.unmarshal(User.class, reader); System.out.println(userFromXml); Assert.assertEquals(user, userFromXml); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } } }

<!--[if !supportLists]-->2. <!--[endif]-->当默认的mapping不能满足要求时,比如有的时候我们可能需要去节点的某个属性的值map到对象的属性,有的时候则是将某个节点的值map到对象的属性,这个时候我们就需要自己定义mapping文件。

userMapping.xml

  1. <?xml version="1.0"?>
  2. <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.org/mapping.dtd">
  3. <mapping>
  4. <class name="com.hayden.model.Address">
  5. <map-to xml="address" />
  6. <field name="id" type="java.lang.Long">
  7. <bind-xml name="id" node="element" />
  8. </field>
  9. <field name="detail" type="java.lang.String">
  10. <bind-xml name="detail" node="element" />
  11. </field>
  12. </class>
  13. <class name="com.hayden.model.User">
  14. <map-to xml="user" />
  15. <field name="id" type="java.lang.Long">
  16. <bind-xml name="id" node="element" />
  17. </field>
  18. <field name="name" type="java.lang.String">
  19. <bind-xml name="name" node="element" />
  20. </field>
  21. <field name="address" type="com.hayden.model.Address">
  22. <bind-xml name="address" node="element" />
  23. </field>
  24. <field name="type" type="java.lang.Integer">
  25. <bind-xml name="type" node="element" />
  26. </field>
  27. </class>
  28. </mapping>
<?xml version="1.0"?> <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.org/mapping.dtd"> <mapping> <class name="com.hayden.model.Address"> <map-to xml="address" /> <field name="id" type="java.lang.Long"> <bind-xml name="id" node="element" /> </field> <field name="detail" type="java.lang.String"> <bind-xml name="detail" node="element" /> </field> </class> <class name="com.hayden.model.User"> <map-to xml="user" /> <field name="id" type="java.lang.Long"> <bind-xml name="id" node="element" /> </field> <field name="name" type="java.lang.String"> <bind-xml name="name" node="element" /> </field> <field name="address" type="com.hayden.model.Address"> <bind-xml name="address" node="element" /> </field> <field name="type" type="java.lang.Integer"> <bind-xml name="type" node="element" /> </field> </class> </mapping>

CastorMappingTest.java

  1. /**
  2. *
  3. */
  4. package com.hayden.castor;
  5. import static org.junit.Assert.fail;
  6. import java.io.FileReader;
  7. import java.io.FileWriter;
  8. import org.exolab.castor.mapping.Mapping;
  9. import org.exolab.castor.xml.Marshaller;
  10. import org.exolab.castor.xml.Unmarshaller;
  11. import org.junit.Assert;
  12. import org.junit.Before;
  13. import org.junit.Test;
  14. import com.hayden.model.Address;
  15. import com.hayden.model.User;
  16. /**
  17. * @author HaydenWang
  18. *
  19. */
  20. public class CastorMappingTest {
  21. private User user;
  22. @Before
  23. public void init() {
  24. Address addr = new Address();
  25. addr.setId(100l);
  26. addr.setDetail("Baidu Building");
  27. user = new User();
  28. user.setId(1111L);
  29. user.setName("Helen");
  30. user.setAddress(addr);
  31. user.setType(User.TYPE_COMMON_USER);
  32. }
  33. @Test
  34. public void mappingTest() {
  35. try { // Load Mapping
  36. Mapping mapping = new Mapping();
  37. mapping.loadMapping("file:conf//userMapping.xml");
  38. Marshaller marshaller = new Marshaller();
  39. marshaller.setMapping(mapping);
  40. FileWriter writer = new FileWriter("out//userMappingTest.xml");
  41. marshaller.setWriter(writer);
  42. marshaller.marshal(user);
  43. // Create a Reader to the file to unmarshal from
  44. FileReader reader = new FileReader("out//userMappingTest.xml");
  45. // Create a new Unmarshaller
  46. Unmarshaller unmarshaller = new Unmarshaller(mapping);
  47. unmarshaller.setClass(User.class);
  48. // Unmarshal the user object
  49. User userFromXml = (User) unmarshaller.unmarshal(reader);
  50. System.out.println(userFromXml);
  51. Assert.assertEquals(user, userFromXml);
  52. } catch (Exception e) {
  53. e.printStackTrace();
  54. fail(e.getMessage());
  55. }
  56. }
  57. }
/** * */ package com.hayden.castor; import static org.junit.Assert.fail; import java.io.FileReader; import java.io.FileWriter; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.hayden.model.Address; import com.hayden.model.User; /** * @author HaydenWang * */ public class CastorMappingTest { private User user; @Before public void init() { Address addr = new Address(); addr.setId(100l); addr.setDetail("Baidu Building"); user = new User(); user.setId(1111L); user.setName("Helen"); user.setAddress(addr); user.setType(User.TYPE_COMMON_USER); } @Test public void mappingTest() { try { // Load Mapping Mapping mapping = new Mapping(); mapping.loadMapping("file:conf//userMapping.xml"); Marshaller marshaller = new Marshaller(); marshaller.setMapping(mapping); FileWriter writer = new FileWriter("out//userMappingTest.xml"); marshaller.setWriter(writer); marshaller.marshal(user); // Create a Reader to the file to unmarshal from FileReader reader = new FileReader("out//userMappingTest.xml"); // Create a new Unmarshaller Unmarshaller unmarshaller = new Unmarshaller(mapping); unmarshaller.setClass(User.class); // Unmarshal the user object User userFromXml = (User) unmarshaller.unmarshal(reader); System.out.println(userFromXml); Assert.assertEquals(user, userFromXml); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } } }

<!--[if !supportLists]-->3. <!--[endif]-->以上的例子都是直接将xml中的值赋给对象的属性,可是有的时候,我们需要将这些值进行包装。如上面例子中的用户的type属性,在代码中是Long类型,可是我们希望在xml中是有意义的字符,如对于type为1的时候,输出“admin”。对于这种情况,这个时候我们就需要写一些FieldHandler来解决这类问题。

UserTypeHandler.java

  1. package com.hayden.castor;
  2. import org.exolab.castor.mapping.GeneralizedFieldHandler;
  3. import com.hayden.model.User;
  4. public class UserTypeHandler extends GeneralizedFieldHandler {
  5. @Override
  6. public Object convertUponGet(Object value) {
  7. Long type = (Long) value;
  8. if (User.TYPE_ADMIN.equals(type)) {
  9. return "admin";
  10. } else {
  11. return "common user";
  12. }
  13. }
  14. @Override
  15. public Object convertUponSet(Object value) {
  16. String typeString = (String) value;
  17. if ("admin".equals(typeString)) {
  18. return User.TYPE_ADMIN;
  19. } else {
  20. return User.TYPE_COMMON_USER;
  21. }
  22. }
  23. @Override
  24. public Class getFieldType() {
  25. return Long.class;
  26. }
  27. }
package com.hayden.castor; import org.exolab.castor.mapping.GeneralizedFieldHandler; import com.hayden.model.User; public class UserTypeHandler extends GeneralizedFieldHandler { @Override public Object convertUponGet(Object value) { Long type = (Long) value; if (User.TYPE_ADMIN.equals(type)) { return "admin"; } else { return "common user"; } } @Override public Object convertUponSet(Object value) { String typeString = (String) value; if ("admin".equals(typeString)) { return User.TYPE_ADMIN; } else { return User.TYPE_COMMON_USER; } } @Override public Class getFieldType() { return Long.class; } }

fieldHandlerMapping.xml

  1. <?xml version="1.0"?>
  2. <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.org/mapping.dtd">
  3. <mapping>
  4. <class name="com.hayden.model.Address">
  5. <map-to xml="address" />
  6. <field name="id" type="java.lang.Long">
  7. <bind-xml name="id" node="element" />
  8. </field>
  9. <field name="detail" type="java.lang.String">
  10. <bind-xml name="detail" node="element" />
  11. </field>
  12. </class>
  13. <class name="com.hayden.model.User">
  14. <map-to xml="user" />
  15. <field name="id" type="java.lang.Long">
  16. <bind-xml name="id" node="element" />
  17. </field>
  18. <field name="name" type="java.lang.String">
  19. <bind-xml name="name" node="element" />
  20. </field>
  21. <field name="address" type="com.hayden.model.Address">
  22. <bind-xml name="address" node="element" />
  23. </field>
  24. <field name="type" type="java.lang.String" handler="com.hayden.castor.UserTypeHandler">
  25. <bind-xml name="type" node="element" />
  26. </field>
  27. </class>
  28. </mapping>
<?xml version="1.0"?> <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.org/mapping.dtd"> <mapping> <class name="com.hayden.model.Address"> <map-to xml="address" /> <field name="id" type="java.lang.Long"> <bind-xml name="id" node="element" /> </field> <field name="detail" type="java.lang.String"> <bind-xml name="detail" node="element" /> </field> </class> <class name="com.hayden.model.User"> <map-to xml="user" /> <field name="id" type="java.lang.Long"> <bind-xml name="id" node="element" /> </field> <field name="name" type="java.lang.String"> <bind-xml name="name" node="element" /> </field> <field name="address" type="com.hayden.model.Address"> <bind-xml name="address" node="element" /> </field> <field name="type" type="java.lang.String" handler="com.hayden.castor.UserTypeHandler"> <bind-xml name="type" node="element" /> </field> </class> </mapping>

FieldHandlerMappingTest.java

  1. /**
  2. *
  3. */
  4. package com.hayden.castor;
  5. import static org.junit.Assert.fail;
  6. import java.io.FileReader;
  7. import java.io.FileWriter;
  8. import org.exolab.castor.mapping.Mapping;
  9. import org.exolab.castor.xml.Marshaller;
  10. import org.exolab.castor.xml.Unmarshaller;
  11. import org.junit.Assert;
  12. import org.junit.Before;
  13. import org.junit.Test;
  14. import com.hayden.model.Address;
  15. import com.hayden.model.User;
  16. /**
  17. * @author HaydenWang
  18. *
  19. */
  20. public class FieldHandlerMappingTest {
  21. private User user;
  22. @Before
  23. public void init() {
  24. Address addr = new Address();
  25. addr.setId(100l);
  26. addr.setDetail("Baidu Building");
  27. user = new User();
  28. user.setId(1111L);
  29. user.setName("Helen");
  30. user.setAddress(addr);
  31. user.setType(User.TYPE_COMMON_USER);
  32. }
  33. @Test
  34. public void mappingTest() {
  35. try { // Load Mapping
  36. Mapping mapping = new Mapping();
  37. mapping.loadMapping("file:conf//fieldHandlerMapping.xml");
  38. Marshaller marshaller = new Marshaller();
  39. marshaller.setMapping(mapping);
  40. FileWriter writer = new FileWriter("out//fieldHandlerTest.xml");
  41. marshaller.setWriter(writer);
  42. marshaller.marshal(user);
  43. // Create a Reader to the file to unmarshal from
  44. FileReader reader = new FileReader("out//fieldHandlerTest.xml");
  45. // Create a new Unmarshaller
  46. Unmarshaller unmarshaller = new Unmarshaller(mapping);
  47. unmarshaller.setClass(User.class);
  48. // Unmarshal the user object
  49. User userFromXml = (User) unmarshaller.unmarshal(reader);
  50. System.out.println(userFromXml);
  51. Assert.assertEquals(user, userFromXml);
  52. } catch (Exception e) {
  53. e.printStackTrace();
  54. fail(e.getMessage());
  55. }
  56. }
  57. }
/** * */ package com.hayden.castor; import static org.junit.Assert.fail; import java.io.FileReader; import java.io.FileWriter; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.hayden.model.Address; import com.hayden.model.User; /** * @author HaydenWang * */ public class FieldHandlerMappingTest { private User user; @Before public void init() { Address addr = new Address(); addr.setId(100l); addr.setDetail("Baidu Building"); user = new User(); user.setId(1111L); user.setName("Helen"); user.setAddress(addr); user.setType(User.TYPE_COMMON_USER); } @Test public void mappingTest() { try { // Load Mapping Mapping mapping = new Mapping(); mapping.loadMapping("file:conf//fieldHandlerMapping.xml"); Marshaller marshaller = new Marshaller(); marshaller.setMapping(mapping); FileWriter writer = new FileWriter("out//fieldHandlerTest.xml"); marshaller.setWriter(writer); marshaller.marshal(user); // Create a Reader to the file to unmarshal from FileReader reader = new FileReader("out//fieldHandlerTest.xml"); // Create a new Unmarshaller Unmarshaller unmarshaller = new Unmarshaller(mapping); unmarshaller.setClass(User.class); // Unmarshal the user object User userFromXml = (User) unmarshaller.unmarshal(reader); System.out.println(userFromXml); Assert.assertEquals(user, userFromXml); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } } }

以上只是Castor的基本使用方法。

更多请参见:

http://www.castor.org/

此外,sun的xerecs具有类似的功能。

转载于:https://my.oschina.net/u/175660/blog/55924

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值