xstream xml模板_XStream – XStreamely使用Java中的XML数据的简便方法

xstream xml模板

有时候,我们不得不处理XML数据。 而且大多数时候,这不是我们一生中最快乐的一天。 甚至有一个术语“ XML地狱”描述了程序员必须处理许多难以理解的XML配置文件时的情况。 但是,不管喜欢与否,有时我们别无选择,这主要是因为客户端的说明中提到了诸如“使用以XML文件编写的配置”之类的内容。 在这种情况下, XStream附带了非常酷的功能,使处理XML的痛苦减轻了。

总览

XStream是一个小型库,用于在Java对象和XML之间序列化数据。 它重量轻,体积小,具有出色的API,最重要的是,它可以与自定义注释一起使用,也可以不包含不属于Java类所有者的自定义注释。

第一个例子

假设我们需要从xml文件加载配置:

<config><inputFile>/Users/tomek/work/mystuff/input.csv</inputFile><truststoreFile>/Users/tomek/work/mystuff/truststore.ts</truststoreFile><keystoreFile>/Users/tomek/work/mystuff/CN-user.jks</keystoreFile><!-- ssl stores passwords--><truststorePassword>password</truststorePassword><keystorePassword>password</keystorePassword><!-- user credentials --><user>user</user><password>secret</password>
</config>

我们想将其加载到Configuration对象中:

public class Configuration {private String inputFile;private String user;private String password;private String truststoreFile;private String keystoreFile;private String keystorePassword;private String truststorePassword;// getters, setters, etc.
}

因此,基本上我们要做的是:

FileReader fileReader = new FileReader("config.xml");  // load our xml file  XStream xstream = new XStream();     // init XStream// define root alias so XStream knows which element and which class are equivalentxstream.alias("config", Configuration.class);    Configuration loadedConfig = (Configuration) xstream.fromXML(fileReader);

仅此而已

更严重的事情

好的,但是前面的示例非常基础,因此现在让我们做些更复杂的事情:由真实WebService返回的真实XML。

<DATA xmlns=""><BAN><UPDATED_AT>2013-03-09</UPDATED_AT><TROUBLEMAKER><NAME1>JOHN</NAME1><NAME2>EXAMPLE</NAME2><AGE>24</AGE><NUMBER>ASD123123</NUMBER></TROUBLEMAKER></BAN><BAN><UPDATED_AT>2012-03-10</UPDATED_AT><TROUBLEMAKER><NAME1>ANNA</NAME1><NAME2>BAKER</NAME2><AGE>26</AGE><NUMBER>AXN567890</NUMBER></TROUBLEMAKER></BAN><BAN><UPDATED_AT>2010-12-05</UPDATED_AT><TROUBLEMAKER><NAME1>TOM</NAME1><NAME2>MEADOW</NAME2><NUMBER>SGH08945</NUMBER><AGE>48</AGE></TROUBLEMAKER></BAN>
</DATA>

我们这里提供的是用XML编写的简单禁令清单。 我们希望将其加载到Ban对象的集合中。 因此,让我们准备一些类(省略getters / setters / toString):

public class Data {private List bans = new ArrayList(); 
}public class Ban {private String dateOfUpdate;private Person person;
}public class Person {private String firstName;private String lastName;private int age;private String documentNumber;
}

如您所见,XML和Java类之间存在一些命名和类型不匹配的问题(例如,字段名1-> firstName,dateOfUpdate是String而不是Date),但这是出于某些示例目的。 因此,这里的目标是解析XML并使用包含正确数据的Ban实例的填充集合来获取Data对象。 让我们看看如何实现它。

解析注释

首先,更简单的方法是使用注释。 这是在我们可以修改将XML映射到的Java类的情况下的建议方法。
因此,我们有:

@XStreamAlias("DATA") // maps DATA element in XML to this class
public class Data {// Here is something more complicated. If we have list of elements that are // not wrapped in a element representing a list (like we have in our XML: // multiple <ban> elements not wrapped inside <bans> collection, // we have to declare that we want to treat these elements as an implicit list // so they can be converted to List of objects. @XStreamImplicit(itemFieldName = "ban") private List bans = new ArrayList();
}@XStreamAlias("BAN") // another mapping
public class Ban {/*We want to have different field names in Java classes sowe define what element should be mapped to each field*/@XStreamAlias("UPDATED_AT") // private String dateOfUpdate;@XStreamAlias("TROUBLEMAKER")private Person person;
}@XStreamAlias("TROUBLEMAKER")
public class Person {@XStreamAlias("NAME1")private String firstName;@XStreamAlias("NAME2")private String lastName;@XStreamAlias("AGE") // String will be auto converted to int valueprivate int age;@XStreamAlias("NUMBER")private String documentNumber;

实际的解析逻辑非常简短:

FileReader reader = new FileReader("file.xml");  // load fileXStream xstream = new XStream();xstream.processAnnotations(Data.class);     // inform XStream to parse annotations in Data classxstream.processAnnotations(Ban.class);      // and in two other classes... xstream.processAnnotations(Person.class);   // we use for mappingsData data = (Data) xstream.fromXML(reader); // parse// Print some data to console to see if results are correctSystem.out.println("Number of bans = " + data.getBans().size());Ban firstBan = data.getBans().get(0);System.out.println("First ban = " + firstBan.toString());

如您所见,注释非常易于使用,因此最终代码非常简洁。 但是在无法修改映射类的情况下该怎么办? 我们可以使用不需要对表示XML数据的Java类进行任何修改的其他方法。

解析无注释

当我们无法用注解充实我们的模型类时,还有另一种解决方案。 我们可以使用XStream对象的方法定义所有映射细节:

FileReader reader = new FileReader("file.xml");  // three first lines are easy, XStream xstream = new XStream();                 // same initialisation as in the xstream.alias("DATA", Data.class);               // basic example abovexstream.alias("BAN", Ban.class);             // two more aliases to map... xstream.alias("TROUBLEMAKER", Person.class); // between node names and classes// We want to have different field names in Java classes so// we have to use aliasField(<fieldInXml>, <mappedJavaClass>, <mappedFieldInJavaClass>)xstream.aliasField("UPDATED_AT", Ban.class, "dateOfUpdate"); xstream.aliasField("TROUBLEMAKER", Ban.class, "person");xstream.aliasField("NAME1", Person.class, "firstName");xstream.aliasField("NAME2", Person.class, "lastName");xstream.aliasField("AGE", Person.class, "age");  // notice here that XML will be auto-converted to int "age"xstream.aliasField("NUMBER", Person.class, "documentNumber");/*Another way to define implicit collection*/ xstream.addImplicitCollection(Bans.class, "bans");Data data = (Data) xstream.fromXML(reader);  // do the actual parsing// let's print results to check if data was parsedSystem.out.println("Number of bans = " + data.getBans().size());Ban firstBan = data.getBans().get(0);System.out.println("First ban = " + firstBan.toString());

如您所见,XStream允许轻松地将更复杂的XML结构转换为Java对象,如果XML不能满足我们的需求,它还可以通过使用不同的名称来调整结果。 但是有一件事情应该引起您的注意:我们正在将表示Date的XML转换为原始String,这与我们想要的结果不完全相同。 这就是为什么我们将添加转换器来为我们做一些工作的原因。

使用现有的自定义类型转换器

XStream库附带了一组针对大多数常见用例的内置转换器。 我们将使用DateConverter。 所以现在我们班的班级看起来像这样:

public class Ban {private Date dateOfUpdate;private Person person;
}

要使用DateConverter,我们只需将其注册为我们希望出现在XML数据中的日期格式即可:

xstream.registerConverter(new DateConverter("yyyy-MM-dd", new String[] {}));

就是这样。 现在,我们的对象不是String,而是填充了Date实例。 酷又容易! 但是,现有转换器未涵盖的类和情况又如何呢? 我们可以自己写。

从头开始编写自定义转换器

假设我们想知道多少天前完成更新,而不是dateOfUpdate:

public class Ban {private int daysAgo;private Person person;
}

当然,我们可以为每个Ban对象手动计算它,但是使用可以为我们完成这项工作的转换器看起来会更有趣。 我们的DaysAgoConverter必须实现Converter接口,因此我们必须实现三种带有签名的方法,这些方法看起来有些吓人:

public class DaysAgoConverter implements Converter {@Overridepublic void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {}@Overridepublic Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {}@Overridepublic boolean canConvert(Class type) {return false;}
}

最后一个很容易,因为我们将只转换Integer类。 但是,这些HierarchicalStreamWriter仍然剩下两种方法,MarshallingContext,HierarchicalStreamReader和UnmarshallingContext参数。 幸运的是,我们可以通过使用AbstractSingleValueConverter避免与它们打交道,它使我们免受如此低级的机制的攻击。 现在我们的班级看起来好多了:

public class DaysAgoConverter extends AbstractSingleValueConverter {@Overridepublic boolean canConvert(Class type) {return type.equals(Integer.class);}@Overridepublic Object fromString(String str) {return null;}public String toString(Object obj) {return null;}
}

另外,我们必须重写AbstractSingleValueConverter中定义的toString(Object obj)方法,因为我们要将Date存储在从Integer计算的XML中,而不是简单的Object.toString值,该值将从抽象父级中定义的默认toString返回。

实作

下面的代码非常简单,但是大多数有趣的行都被注释了。 我跳过了所有验证内容,以简化此示例。

public class DaysAgoConverter extends AbstractSingleValueConverter {private final static String FORMAT = "yyyy-MM-dd"; // default Date format that will be used in conversionprivate final DateTime now = DateTime.now().toDateMidnight().toDateTime(); // current day at midnightpublic boolean canConvert(Class type) {return type.equals(Integer.class);     // Converter works only with Integers}@Overridepublic Object fromString(String str) {SimpleDateFormat format = new SimpleDateFormat(FORMAT);try {Date date = format.parse(str);return Days.daysBetween(new DateTime(date), now).getDays();  // we simply calculate days between using JodaTime} catch (ParseException e) {throw new RuntimeException("Invalid date format in " + str);}}public String toString(Object obj) {if (obj == null) {return null;}Integer daysAgo = ((Integer) obj);return now.minusDays(daysAgo).toString(FORMAT); // here we subtract days from now and return formatted date string}
}

用法

要将自定义转换器用于特定字段,我们必须使用registerLocalConverter通知它XStream对象:

xstream.registerLocalConverter(Ban.class, "daysAgo", new DaysAgoConverter());

我们使用“本地”方法将此转换仅应用于特定字段,而不应用于XML文件中的每个Integer字段。 之后,我们将使用天数而不是日期填充Ban对象。

摘要

这就是我想在这篇文章中向您展示的全部内容。 现在,您已经掌握了XStream的功能以及如何使用它轻松将XML数据映射到Java对象的基本知识。如果您需要更高级的内容,请查看项目官方页面,因为它包含了很好的文档和示例。

参考: XStream –来自Code Hard Go Pro博客的JCG合作伙伴 Tomasz Dziurko的XStreamely 简单方法,可使用Java处理XML数据 。

翻译自: https://www.javacodegeeks.com/2013/04/xstream-xstreamely-easy-way-to-work-with-xml-data-in-java.html

xstream xml模板

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349361.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python知识点智能问答_基于知识图谱的智能问答机器人

研究背景及意义 智能问答是计算机与人类以自然语言的形式进行交流的一种方式&#xff0c;是人工智能研究的一个分支。 知识图谱本质上是一种语义网络&#xff0c;其结点代表实体&#xff08;entity&#xff09;或者概念&#xff08;concept&#xff09;&#xff0c;边代表实体/…

java会了还学什么_java都学哪些内容?学完之后可以做哪些工作?

展开全部阶段一&#xff1a;揭开企业开发神秘面纱 (4周32313133353236313431303231363533e78988e69d8331333431336163)1) Web开发基础&#xff1a;HTML语言、JavaScript、CSS、DOM等2) Oracle数据库基础&#xff1a;安装、配置Oracle数据库&#xff0c;熟练掌握SQL语句3) 操作系…

Java中的RAII

资源获取即初始化&#xff08; RAII &#xff09;是Bjarne Stroustrup用C 引入的一种用于异常安全资源管理的设计思想。 感谢垃圾回收&#xff0c;Java 没有此功能&#xff0c;但是我们可以使用try-with-resources实现类似的功能。 约翰哈德斯&#xff08;John Huddles&#x…

java去掉字符串中前后空格函数_Java去除字符串中的空格

1. String.trim()trim()是去掉首尾空格2.str.replace(" ", ""); 去掉所有空格&#xff0c;包括首尾、中间String str " hell o ";String str2 str.replaceAll(" ", "");System.out.println(str2);3.或者replaceAll("…

python3开发工具推荐_python开发工具有哪些?我推荐这5款python开发工具!

python开发工具有很多&#xff0c;目前我们用的比较多的是pycharm&#xff0c;除了pycharm还有文本编辑器像微软的vscode&#xff0c;sublime text都有非常好的插件&#xff0c;今天&#xff0c;我就把Python程序员使用频率比较高的5款开发工具推荐给大家&#xff0c;希望对大家…

java显示数据库 控件_WebLogic运用DB的Java控件访问数据库(1)

一、方法WebLogic页面与数据通信时&#xff0c;一般采用Java控件直接访问数据连接池&#xff0c;数据的直接操作都定义在Java控件中&#xff0c;页面流做为数据的逻辑处理单元&#xff0c;普通页面做为显示层。可以看出WebLogic这个方法是典型的三层结构&#xff0c;数据层(Jav…

python的实验报告怎么写_学号:20191221,《python实验设计》实验报告三

学号 2019-2020-2 《Python程序设计》实验三讲述课程&#xff1a;《Python程序设计》班级&#xff1a; 1912姓名&#xff1a; 何应霆学号&#xff1a;20191221实验西席&#xff1a;王志强实验日期&#xff1a;2020年5月16日必修/选修&#xff1a; 公选课1.实验内容建立服务端和…

eclipse juno_Eclipse Juno上带有GlassFish的JavaEE 7

eclipse junoJava EE 7很热。 前四个JSR最近通过了最终批准选票&#xff0c;与此同时GlassFish 4达到了升级版83。 如果您关注我的博客&#xff0c;那么您将了解NetBeans的大部分工作。 但是我确实认识到&#xff0c;那里还有其他IDE用户&#xff0c;他们也有权试用最新和最出色…

java 生成校验验证码_java 验证码生成与校验

java绘图相关类验证码工具类package dt2008.util;import javax.imageio.ImageIO;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.awt.*;import java.awt.image.BufferedImage;import java.io.IOException;import ja…

红黑树中nil结点_什么是红黑树?程序员面试必问!

点击上方java小组&#xff0c;选择“置顶公众号”优质文章&#xff0c;第一时间送达当在10亿数据中只需要进行10几次比较就能查找到目标时&#xff0c;不禁感叹编程之魅力&#xff01;人类之伟大呀&#xff01; —— 学红黑树有感。终于&#xff0c;在学习了几天的红黑树相关的…

杰克逊JSON解析错误-UnrecognizedPropertyException:无法识别的字段,未标记为可忽略[已解决]...

在解析从我们的一个RESTful Web服务接收到的JSON字符串时&#xff0c;我收到此错误“线程“ main”中的异常com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException&#xff1a;无法识别的字段“人”&#xff08;类Hello $ Person&#xff09;&#xff0c;不是标记…

mysql2008数据库配置_SQL Server 2008 R2 超详细安装图文教程

这篇文章主要介绍了SQL Server 2008 R2 超详细安装图文教程,需要的朋友可以参考下一、下载SQL Server 2008 R2安装文件二、将安装文件刻录成光盘或者用虚拟光驱加载&#xff0c;或者直接解压&#xff0c;打开安装文件&#xff0c;出现下面的界面安装SQL Server 2008 R2需要.NET…

hdfs读写流程_深度探索Hadoop分布式文件系统(HDFS)数据读取流程

一、开篇Hadoop分布式文件系统(HDFS)是Hadoop大数据生态最底层的数据存储设施。因其具备了海量数据分布式存储能力&#xff0c;针对不同批处理业务的大吞吐数据计算承载力&#xff0c;使其综合复杂度要远远高于其他数据存储系统。因此对Hadoop分布式文件系统(HDFS)的深入研究&a…

python可视化分析网易云音乐评论_Python数据可视化:网易云音乐歌单

网易云音乐2018年度听歌报告—遇见你&#xff0c;真好。相信有不少人在上周&#xff0c;应该已经看过自己网易云音乐的年度报告了。小F也是去凑凑热闹&#xff0c;瞅了一波自己的年度听歌报告。那么你在云村又听了多少首歌&#xff0c;听到最多的歌词又是什么呢?2018年你的年度…

mysql隔离级别验证_MySQL事务隔离级别以及验证

查询初始数据开启A事务  并做更新操作再另一端 B开始另一个事务查询 事务级别设置为读未提查询到事务未提交的数据 a的count修改为3 但是没有提交2 第二个级别 读已提交 避免脏读问题 但是有不可重复读问题回滚数据 修改隔离级别 确保都是 读已提交级别客户端A客户端B验证 脏…

登录样式:log4j 2,上下文,自动清除…全部不附加任何字符串!

日志记录-保持操作的时间跟踪-对于任何关键任务系统&#xff0c;无论大小&#xff0c;都至关重要。 我们的Project-X框架也是如此 &#xff0c;这就是为什么我们希望从一开始就正确地做到这一点。 基于我们在传奇的UltraESB上的登录经验&#xff0c; 上下文日志记录&#xff0…

python37安装失败_Linux 安装Python37

1、下载python3.7.0https://www.python.org/downloads/release/python-370/2、创建Linux的python37目录mkdir /usr/local/python373、解压python3.7.0源码tar zxvf python3.7.0.tar.zg4、配置编译参数./configure --prefix/usr/local/python375、make6、make install注意&#…

python string模块template_Python标准库笔记(1) — string模块

String模块包含大量实用常量和类&#xff0c;以及一些过时的遗留功能&#xff0c;并还可用作字符串操作。1. 常用方法常用方法描述str.capitalize()把字符串的首字母大写str.center(width)将原字符串用空格填充成一个长度为width的字符串&#xff0c;原字符串内容居中str.count…

注意力机制可视化_目标跟踪中的(STAM)时空注意力机制

目标跟踪分为单目标跟踪和多目标跟踪&#xff0c;单目标跟踪较为简单&#xff0c;这里我们只讨论多目标跟踪。多目标跟踪的遮挡问题多目标跟踪时特别容易发生目标间的相互遮挡&#xff0c;从而导致严重的预测偏移问题&#xff0c;如下图所示&#xff1a;红色框的行人在和蓝色框…

byteman_使用Byteman和JUnit进行故障注入

byteman我们的应用程序独立存在的时间已经很久了。 如今&#xff0c;应用程序是一种非常复杂的野兽&#xff0c;它们使用无数的API和协议相互通信&#xff0c;将数据存储在传统或NoSQL数据库中&#xff0c;通过网络发送消息和事件……例如&#xff0c;您多久考虑一次例如数据库…