如何用XStream将EventXML类序列化为含标签属性的目标XML?
实现目标XML格式的解决方案
要将EventXML类序列化为你期望的XML结构,核心是自定义XStream的序列化逻辑,把dateFormat字段转为myData元素的属性,同时按照dateFormat的值格式化日期内容。下面是具体实现步骤:
1. 完善EventXML类(添加Getter/Setter)
首先需要给类中所有私有字段添加Getter和Setter方法,方便自定义转换器访问字段值:
import java.util.Date; public class EventXML{ private String name; private String ip; private Date date; private String dateFormat; private String eventName; // Getters public String getName() { return name; } public String getIp() { return ip; } public Date getDate() { return date; } public String getDateFormat() { return dateFormat; } public String getEventName() { return eventName; } // Setters public void setName(String name) { this.name = name; } public void setIp(String ip) { this.ip = ip; } public void setDate(Date date) { this.date = date; } public void setDateFormat(String dateFormat) { this.dateFormat = dateFormat; } public void setEventName(String eventName) { this.eventName = eventName; } }
2. 实现自定义XStream转换器
创建一个EventXMLConverter类,手动控制XML的生成结构,完成两个关键需求:
- 将
dateFormat作为myData元素的属性 - 按照
dateFormat格式化date字段的内容
import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; public class EventXMLConverter implements Converter { @Override public boolean canConvert(Class type) { // 只处理EventXML类的序列化/反序列化 return type.equals(EventXML.class); } @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { EventXML event = (EventXML) source; // 序列化name字段 writer.startNode("name"); writer.setValue(event.getName()); writer.endNode(); // 序列化ip字段 writer.startNode("ip"); writer.setValue(event.getIp()); writer.endNode(); // 序列化myData元素(带dateFormat属性+格式化后的日期) writer.startNode("myData"); writer.addAttribute("dateFormat", event.getDateFormat()); // 按照指定格式和UTC时区格式化日期 SimpleDateFormat sdf = new SimpleDateFormat(event.getDateFormat()); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String formattedDate = sdf.format(event.getDate()); writer.setValue(formattedDate); writer.endNode(); // 序列化eventName字段 writer.startNode("eventName"); writer.setValue(event.getEventName()); writer.endNode(); } @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { // 如果需要反序列化XML到EventXML对象,实现此方法(可选) EventXML event = new EventXML(); reader.moveDown(); // 进入name节点 event.setName(reader.getValue()); reader.moveUp(); reader.moveDown(); // 进入ip节点 event.setIp(reader.getValue()); reader.moveUp(); reader.moveDown(); // 进入myData节点 event.setDateFormat(reader.getAttribute("dateFormat")); SimpleDateFormat sdf = new SimpleDateFormat(event.getDateFormat()); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); try { event.setDate(sdf.parse(reader.getValue())); } catch (ParseException e) { e.printStackTrace(); } reader.moveUp(); reader.moveDown(); // 进入eventName节点 event.setEventName(reader.getValue()); reader.moveUp(); return event; } }
3. 修改toXML方法,注册自定义转换器
在原有的toXML方法中,注册我们的自定义转换器,替换XStream的默认序列化逻辑:
import com.thoughtworks.xstream.XStream; public class EventXML{ // ... 之前的字段和Getter/Setter ... public String toXML(){ XStream xs = new XStream(); // 注册自定义转换器 xs.registerConverter(new EventXMLConverter()); String xmlContent = xs.toXML(this); // 添加XML声明 return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xmlContent; } }
效果验证
当你实例化EventXML并调用toXML()时,会生成你期望的XML结构:
<?xml version="1.0" encoding="UTF-8"?> <EventXML> <name>SuperFarmer</name> <ip>IPPPPPPP</ip> <myData dateFormat="HH:mm:ss dd/MM/yyyy">12:48:05 15/05/2018</myData> <eventName>CLICCA</eventName> </EventXML>
关键点说明
- 自定义转换器完全控制了XML的生成结构,确保
dateFormat成为myData的属性,而非单独元素 - 使用
SimpleDateFormat并指定UTC时区,保证日期格式化的一致性(和原XML中的UTC时间对应) - 如果不需要反序列化,可以省略
unmarshal方法的实现(但建议保留以保证功能完整性)
内容的提问来源于stack exchange,提问作者Francesco Ronchieri
相关产品推荐
相关产品推荐

