xml文本格式是网络通信中最常用的格式,最近特别研究了一下如何解析xml文本并转换为对象,现在分享一下我最近的学习成果~
先列一下本例中需要解析的xml文本:
Xml代码
- <results name="list">
- <row pubtime="2016-04-13 16:40:13" author="APP" id="140" title="什么是公告" content="公告,是公开宣告。" />
- <row pubtime="2016-04-13 16:36:50" author="网站" id="138" title="12345678" content="12345678" />
- <row pubtime="2016-04-06 15:02:44" author="网站" id="134" title="关于网站用户注册流程说明1" content="关于用户注册流程说明" />
- <row pubtime="2016-03-30 18:32:13" author="APP" id="126" title="关于网站使用说明" content="测试" />
- <row pubtime="2016-03-30 18:29:26" author="网站" id="125" title="关于手机App使用说明" content="123" />
- </results>
讲一下我的思路,我选择使用XStream来解析xml文本,因为xstream在转换对象方面会比dom4j更优秀一些,它是通过注解方式来声明对应结点的,在操作上会更直观方便。首先会将整个文本转换成一个Results类对象,而每一个row结点作为一个HashMap放入到Results类对象的List列表中,最后会将每一个HashMap读取出来通过JAVA的反射机制转换为Info对象,并生成List列表。
Info类代码 下载
- public class Info {
- private String id;
- private String title;
- private String content;
- private String author;
- private String pubtime;
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public String getContent() {
- return content;
- }
- public void setContent(String content) {
- this.content = content;
- }
- public String getAuthor() {
- return author;
- }
- public void setAuthor(String author) {
- this.author = author;
- }
- public String getPubtime() {
- return pubtime;
- }
- public void setPubtime(String pubtime) {
- this.pubtime = pubtime;
- }
- @Override
- public String toString() {
- return "Info [author=" + author + ", content=" + content + ", id=" + id
- + ", pubtime=" + pubtime + ", title=" + title + "]";
- }
- }
Row类代码 下载
- @XStreamConverter(RowConverter.class)
- public class Row extends HashMap<String, String> {
- private static final long serialVersionUID = 5619951409573339302L;
- }
Results代码
- @XStreamAlias("results")
- public class Results {
- @XStreamAlias("name")
- @XStreamAsAttribute
- private String name;
- @XStreamImplicit(itemFieldName = "row")
- private List<Row> rows;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public List<Row> getRows() {
- return rows;
- }
- public void setRows(List<Row> rows) {
- this.rows = rows;
- }
- }
Rowconverter类代码 下载
- public class RowConverter extends AbstractCollectionConverter {
- public RowConverter(Mapper mapper) {
- super(mapper);
- // TODO Auto-generated constructor stub
- }
- @Override
- public boolean canConvert(Class arg0) {
- // TODO Auto-generated method stub
- return Row.class.equals(arg0);
- }
- @Override
- public void marshal(Object arg0, HierarchicalStreamWriter writer,
- MarshallingContext arg2) {
- // TODO Auto-generated method stub
- Row map = (Row) arg0;
- for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
- Map.Entry entry = (Map.Entry) iterator.next();
- writer.addAttribute(entry.getKey().toString(), entry.getValue().toString());
- }
- }
- @Override
- public Object unmarshal(HierarchicalStreamReader reader,
- UnmarshallingContext context) {
- // TODO Auto-generated method stub
- Row map = new Row();
- populateMap(reader, context, map);
- return map;
- }
- protected void populateMap(HierarchicalStreamReader reader, UnmarshallingContext context, Row map) {
- Iterator<String> iterator = reader.getAttributeNames();
- while (iterator.hasNext()) {
- Object key = iterator.next();
- String value = reader.getAttribute((String) key);
- map.put(key.toString(), value.toString());
- }
- }
- }
RowConverter是一个转换器类,作用是将每一个row结点转变一个HashMap。
测试类下载:
Java代码
- public class Xstream {
- private static String xml;
- public static void main(String[] args) throws Exception{
- //初始化
- init();
- XStream xstream = new XStream(new XppDriver(new XmlFriendlyReplacer("_-", "_")));
- //解析xml文本
- xstream.processAnnotations(Results.class);
- Results results = (Results) xstream.fromXML(xml);
- //将解析出来的Results类对象转化成list列表
- List<Info> list = createList(Info.class,results);
- for(int i=0;i<list.size();i++){
- //打印
- Info info = list.get(i);
- System.out.println(info.toString());
- }
- }
- public static void init(){
- //初始化xml文本
- xml ="<results name=\"list\"><row pubtime=\"2016-04-13 16:40:13\" author=\"APP\" id=\"140\" title=\"什么是公告\" content=\"公告,是公开宣告。\" /><row pubtime=\"2016-04-13 16:36:50\" author=\"网站\" id=\"138\" title=\"12345678\" content=\"12345678\" /><row pubtime=\"2016-04-06 15:02:44\" author=\"网站\" id=\"134\" title=\"关于网站用户注册流程说明1\" content=\"关于用户注册流程说明\" /><row pubtime=\"2016-03-30 18:32:13\" author=\"APP\" id=\"126\" title=\"关于网站使用说明\" content=\"测试\" /><row pubtime=\"2016-03-30 18:29:26\" author=\"网站\" id=\"125\" title=\"关于手机App使用说明\" content=\"123\" /></results>";
- }
- public static <T> List createList(Class<T> clz ,Results results) throws Exception{
- List list = new ArrayList();
- for(Row row :results.getRows()){
- //根据class和Row生成对象放入list
- list.add(createObject(clz,row));
- }
- return list;
- }
- public static <T> T createObject(Class<T> clazz ,Row row) throws Exception{
- //初始化对象
- T obj = clazz.newInstance();
- //遍历Info类中所有方法
- for (Method method : clazz.getDeclaredMethods()) {
- String methodName = method.getName();
- Class[] perams = method.getParameterTypes();
- //找到set开头,长度大于3,并且入参数量为1的方法
- if (methodName.startsWith("set") && methodName.length() > 3 && perams.length == 1) {
- String temp = methodName.substring(3, methodName.length());
- //拿到属性名称
- String fieldName = temp.toLowerCase();
- //根据属性名称从HashMap中拿到对应的值
- String value = row.get(fieldName);
- 下载
- if(value != null){
- //拿到该方法入参的Class,根据入参类型来决定调用方法形式
- Class paramClass = perams[0];
- if (String.class.equals(paramClass)) {
- method.invoke(obj, value);
- } else if (Integer.class.equals(paramClass) || int.class.equals(paramClass)) {
- method.invoke(obj, Integer.valueOf(value));
- } else if (Long.class.equals(paramClass) || long.class.equals(paramClass)) {
- method.invoke(obj, Long.valueOf(value));
- } else if (BigDecimal.class.equals(paramClass)) {
- method.invoke(obj, new BigDecimal(value));
- } else if (Boolean.class.equals(paramClass) || boolean.class.equals(paramClass)) {
- if(value.equals("true")||value.equals("TRUE"))
- method.invoke(obj, true);
- if(value.equals("false")||value.equals("FALSE"))
- method.invoke(obj, false);
- }
- }
- }
- }
- return obj;
- }
- }
最后是输出效果:
Java代码
- Info [author=APP, content=公告,是公开宣告。, id=140, pubtime=2016-04-13 16:40:13, title=什么是公告]
- Info [author=网站, content=12345678, id=138, pubtime=2016-04-13 16:36:50, title=12345678]
- Info [author=网站, content=关于用户注册流程说明, id=134, pubtime=2016-04-06 15:02:44, title=关于网站用户注册流程说明1]
- Info [author=APP, content=测试, id=126, pubtime=2016-03-30 18:32:13, title=关于网站使用说明]
- Info [author=网站, content=123, id=125, pubtime=2016-03-30 18:29:26, title=关于手机App使用说明]