[工具库]JOXMLBuilder工具类——一键把多个bean对象数据转换为XML格式数据

本人大四即将毕业的准程序员(JavaSE、JavaEE、android等)一枚,小项目也做过一点,于是乎一时兴起就写了一些工具。

我会在本博客中陆续发布一些平时可能会用到的工具。

代码质量可能不是很好,大家多担待!

代码或者思路有不妥之处,还希望大牛们能不吝赐教哈!

 

以下代码为本人原创,转载请注明:

本文转载,来自:http://www.cnblogs.com/tiantianbyconan/archive/2013/02/19/2917398.html

 

JOXMLBuilder工具类:一键把多个域对象数据转换为XML格式数据,方便用于数据的传输和交互。功能类似于通过Gson来生成Json数据。

源码如下:

View Code
  1 package com.wangjie.extrautil.joxmlbuilder;
  2 
  3 import java.lang.reflect.Field;
  4 import java.lang.reflect.Method;
  5 import java.util.ArrayList;
  6 import java.util.Arrays;
  7 import java.util.Iterator;
  8 import java.util.List;
  9 import java.util.Set;
 10 
 11 /**
 12  * 
 13  * @author wangjie
 14  * @version 创建时间:2013-2-3 下午3:49:59
 15  */
 16 public class JOXMLBuilder {
 17     private List<?> list; // 传入的List数据
 18     private StringBuilder result = null;
 19     private List<String> includes = null; // 要包含的属性列表
 20     private List<String> excludes = null; // 要排除的属性列表
 21     
 22     /**
 23      * 默认构造方法。<br>
 24      * 使用此默认的构造方法之后必须要调用setList()传入List
 25      */
 26     public JOXMLBuilder() {
 27         
 28     }
 29     /**
 30      * 此构造方法会把list中每项的所有属性信息都会生成在xml中。
 31      * @param list 所要生成xml的List数据源。
 32      */
 33     public JOXMLBuilder(List<?> list) {
 34         this.list = list;
 35     }
 36     /**
 37      * 此构造方法提供list中每项属性信息的<b>包含</b>和<b>排除</b>。<br>
 38      * <ol>
 39      * <li>使用includes,不使用excludes:只生成在includes中的信息<br>
 40      * <li>不使用includes,使用excludes:只生成不在excludes中的信息<br>
 41      * <li>既使用includes,又使用exclude(不建议):<br>
 42      *  - 如果includes中和excludes中的信息不冲突,则生成不在excludes中的信息<br>
 43      *  - 如果includes中和excludes中的信息冲突(某个属性都出现在这两个数组中),则冲突部分的信息还是会生成<br>
 44      * <li>includes和excludes都不使用,则会把list中每项的所有属性信息都会生成在xml中
 45      * </ol>
 46      * @param list 所要生成Json的List数据源。
 47      * @param includes 所要包含的属性名称数组。
 48      * @param excludes 所要排除的属性名称数组。
 49      */
 50     public JOXMLBuilder(List<?> list, String[] includes, String[] excludes) {
 51         this.list = list;
 52         this.includes = null == includes || includes.length == 0 ? null : Arrays.asList(includes);
 53         this.excludes = null == excludes || excludes.length == 0 ? null : Arrays.asList(excludes);
 54     }
 55     /**
 56      * 返回正在进行生成xml文件的信息来源List。
 57      * @author wangjie
 58      * @return 返回正在进行生成xml文件的信息来源List。
 59      */
 60     public List<?> getList() {
 61         return list;
 62     }
 63     /**
 64      * 可使用此方法来传入、替换JOXMLBuilder对象中的List对象。
 65      * @author wangjie
 66      * @param list 所要生成xml的List数据源。
 67      * @return 返回当前JOXMLBuilder对象
 68      */
 69     public JOXMLBuilder setList(List<?> list) {
 70         this.list = list;
 71         return this;
 72     }
 73     /**
 74      * 设置包含的属性信息。
 75      * @author wangjie
 76      * @param incFieldName 要包含的属性名
 77      * @return 返回当前JOXMLBuilder对象
 78      */
 79     public JOXMLBuilder setIncludes(String... incFieldName) {
 80         this.includes = null == incFieldName || incFieldName.length == 0 ? null : Arrays.asList(incFieldName);
 81         return this;
 82     }
 83     /**
 84      * 设置排除的属性信息。
 85      * @author wangjie
 86      * @param excFieldName 要排除的属性名
 87      * @return 返回当前JOXMLBuilder对象
 88      */
 89     public JOXMLBuilder setExcludes(String... excFieldName) {
 90         this.excludes = null == excFieldName || excFieldName.length == 0 ? null : Arrays.asList(excFieldName);
 91         return this;
 92     }
 93     /**
 94      * 获得指定Class类型的所有属性,并打印在控制台上。
 95      * @author wangjie
 96      */
 97     public Field[] getFields(Class<?> clazz) {
 98         Field[] fields = clazz.getDeclaredFields();
 99         System.out.print("fields of the class that named " + clazz.getName() + ": ");
100         for(Field field : fields){
101             System.out.print(field.getName() + ", ");
102         }
103         System.out.println();
104         return fields;
105     }
106     
107     /**
108      * 根据list中的对象来生成对应的xml文件。
109      * @author wangjie
110      * @return 返回生成的xml字符串。
111      * @throws Exception 如果List检验不通过,则抛出异常
112      */
113     public StringBuilder xmlBuild() throws Exception{
114         //检验传入的List是否有效
115         checkValidityList();
116         //XML文件开始生成-------------------------
117         result = new StringBuilder("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
118         xmlSubBuild(list); // 递归生成
119         return result;
120     }
121     /**
122      * 生成xml可递归部分的子数据(根据某些对象组成的List来生成属性xml文件)。
123      * @author wangjie
124      * @param list 
125      */
126     private void xmlSubBuild(List<?> list){
127         Class<?> clazz = list.get(0).getClass(); // 获取对应的Class对象
128         Object curObj = null; // 每次循环当前的类对象(资源)
129         int listLength = list.size(); // 类对象个数
130         String simpleName = clazz.getSimpleName(); // 获取类名(不含包名)
131         
132         result.append("<" + simpleName + "All>"); // 根标签开始
133         
134         for(int i = 0; i < listLength; i++){
135             curObj = list.get(i);
136             xmlSubSubBuild(curObj, list); // 子数据递归
137         }
138         
139         result.append("</" + simpleName + "All>"); // 根标签结束
140     }
141     /**
142      * 生成xml可递归部分的子子数据(根据某个对象来生成属性xml文件)。
143      * @author wangjie
144      * @param curObj 要生成xml文件的那个对象 
145      * @param list curObj参数属于的那个List
146      */
147     private void xmlSubSubBuild(Object curObj, List<?> list){
148         String fieldName = ""; // 每次要调用的属性名
149         String methodName = ""; // 每次要调用的方法名
150         Method method = null;; // 每次要调用的方法
151         Object value = ""; // 每次要获得的属性值(子标签)
152         
153         Class<?> clazz = curObj.getClass();
154         Field[] fields = getFields(clazz); // 获得对应类型的所有变量
155         int fieldsLength = fields.length; // 类对象的属性数量
156         
157         String simpleName = clazz.getSimpleName(); // 获取类名(不含包名)
158         
159         result.append("<" + simpleName + ">");
160         
161         
162         for(int j = 0; j < fieldsLength; j++){
163             fieldName = fields[j].getName(); // 获取对应属性名
164             
165             if(list == this.list){ // 只在最外层的类的属性中进行排除包含
166                 // 使用includes,不使用excludes:只生成在includes中的信息
167                 if(null != includes && null == excludes){
168                     if(!includes.contains(fieldName)){
169                         continue;
170                     }
171                 }
172                 
173                 //不使用includes,使用excludes:只生成不在excludes中的信息
174                 if(null == includes && null != excludes){ // 只使用了不包含
175                     if(excludes.contains(fieldName)){
176                         continue;
177                     }
178                 }
179                 
180                 //既使用includes,又使用exclude(不建议):
181                 //- 如果includes中和excludes中的信息不冲突,则生成不在excludes中的信息
182                 //- 如果includes中和excludes中的信息冲突(某个属性都出现在这两个数组中),则冲突部分的信息还是会生成
183                 if(null != includes && null != excludes){ // 既使用了包含,又使用了不包含
184                     if(!includes.contains(fieldName) && excludes.contains(fieldName)){
185                         continue;
186                     }
187                 }
188             }
189             
190             methodName = getGetterMethodNameByFieldName(fields[j]);
191             try {
192                 method = clazz.getDeclaredMethod(methodName, new Class[]{});
193                 method.setAccessible(true);
194                 value = method.invoke(curObj, new Object[]{});
195                 //*********************************************************
196                 if(fields[j].getType() == List.class){ // 如果属性是List类型
197                     List<?> subList = (List<?>)value;
198                     xmlSubBuild(subList); // 子数据递归
199                 }else if(fields[j].getType() == Set.class){ // 如果属性是Set类型的
200                     Set<?> subSet = (Set<?>)value;
201                     Iterator<?> iter = subSet.iterator();
202                     List<Object> subList = new ArrayList<Object>(); 
203                     while(iter.hasNext()){
204                         subList.add(iter.next());
205                     }
206                     xmlSubBuild(subList); // 子数据递归
207                 }
208                 // 如果ClassLoader不是null表示该类不是启动类加载器加载的,不是Java API的类,是自己写的java类
209                 else if(null != fields[j].getType().getClassLoader()){ 
210                     xmlSubSubBuild(value, null); // 子子数据递归
211                 }
212                 else{ // 其它类型都认为是普通文本类型
213                     value = value.toString();
214                     // 添加子元素(类属性)标签
215                     result.append("<" + fieldName + ">")
216                             .append(value)
217                             .append("</" + fieldName + ">");
218                 }
219                 //*********************************************************
220             } catch (Exception e) {
221                 e.printStackTrace();
222             }
223             
224         }
225         result.append("</" + simpleName + ">");
226     }
227     
228     /**
229      * <ol>通过属性Field对象来获取getter方法的方法名。<br>
230      * 如果是boolean或Boolean类型(正则表达式来判断):isBorrow-->isBorrow();isborrow-->isIsborrow();<br>
231      * 否则:borrow-->getBorrow();
232      * </ol>
233      * @author wangjie
234      * @param field 要生成getter方法的对应属性对象。
235      * @return 返回getter方法的方法名。
236      */
237     private String getGetterMethodNameByFieldName(Field field){
238         String methodName = null;
239         String fieldName = field.getName();
240         // 解析属性对应的getter方法名
241         // 判断是否是boolean或Boolean类型:isBorrow-->isBorrow();isborrow-->isIsborrow()
242         if(field.getType() == boolean.class || field.getType() == Boolean.class){
243             if(fieldName.matches("^is[A-Z].*")){
244                 methodName = fieldName;
245             }else{
246                 methodName = "is" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
247             }
248         }else{
249             methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
250         }
251         return methodName;
252     }
253     
254     /**
255      * 检验传入的List的合法性(List是不是为null、长度是不是为0、是不是每项都是同一个类型)。
256      * @author wangjie
257      * @throws Exception 如果List为null, 或者长度为, 或者每项不是同一个类型, 抛出异常
258      */
259     private void checkValidityList() throws Exception{
260         if(null == list){
261             throw new Exception("请保证传入的List不为null");
262         }
263         int size = list.size();
264         if(list.size() == 0){
265             throw new Exception("请保证传入的List长度不为0");
266         }
267         for(int i = 1; i < size; i++){
268             if(list.get(0).getClass() != list.get(i).getClass()){
269                 throw new Exception("请保证传入的List每项都是同一个类型");
270             }
271         }
272         
273     }
274     
275     
276 }

 

使用方法如下:
例如:
Student类(该类有属性name,age,isBoy,books等属性;其中books属性是一个List,存放Book对象):

1 private String name;
2 private int age;
3 private boolean isBoy;
4 private List<Book> books;
5 //并实现getter和setter方法;

 

Book类(该类有属性name,author,number,length,width,isBorrowed等属性):

1 private String name;
2 private String author;
3 private int number;
4 private float length;
5 private float width;
6 private boolean isBorrowed;
7 //并实现getter和setter方法;

 

现在有一个List<Student>类型的数据,通过以下代码把该List转换为xml:

 1 List<Student> list = new ArrayList<Student>();
 2 
 3 //构建几个Student对象,放入list中
 4 //……
 5 
 6 //完整数据版(不使用includes和excludes)
 7 JOXMLBuilder jOXMLBuilder = new JOXMLBuilder(list);
 8 jOXMLBuilder.xmlBuild().toString();
 9 
10 //或者使用包括/排除:
11 JOXMLBuilder jOXMLBuilder = new JOXMLBuilder(list, new String[]{"name", "age"}, null);
12 jOXMLBuilder.xmlBuild().toString();
13 
14 //或者使用方法链风格:
15 new JOXMLBuilder().setExcludes("name", "age").xmlBuild().toString();

 

转换之后的xml(完整数据版(不使用includes和excludes)):

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <StudentAll>
 3         <Student>
 4                 <name>hello</name>
 5                 <age>23</age>
 6                 <isBoy>true</isBoy>
 7                 <BookAll>
 8                         <Book>
 9                                 <name>book1</name>
10                                 <author>author1</author>
11                                 <number>123</number>
12                                 <length>23.5</length>
13                                 <width>18.0</width>
14                                 <isBorrowed>true</isBorrowed>
15                         </Book>
16                         <Book>
17                                 <name>book2</name>
18                                 <author>author2</author>
19                                 <number>43</number>
20                                 <length>42.23</length>
21                                 <width>30.57</width>
22                                 <isBorrowed>false</isBorrowed>
23                         </Book>
24                 </BookAll>
25         </Student>
26 
27         <Student>
28                 <name>world</name>
29                 <age>22</age>
30                 <isBoy>false</isBoy>
31                 <BookAll>
32                          <Book>
33                                 <name>book1</name>
34                                 <author>author1</author>
35                                 <number>123</number>
36                                 <length>23.5</length>
37                                 <width>18.0</width>
38                                 <isBorrowed>true</isBorrowed>
39                         </Book>
40                         <Book>
41                                 <name>book3</name>
42                                 <author>author3</author>
43                                 <number>875</number>
44                                 <length>20.59</length>
45                                 <width>15.08</width>
46                                 <isBorrowed>false</isBorrowed>
47                         </Book>
48                         <Book>
49                                 <name>book4</name>
50                                 <author>author4</author>
51                                 <number>165</number>
52                                 <length>22.75</length>
53                                 <width>19.61</width>
54                                 <isBorrowed>true</isBorrowed>
55                         </Book>
56                 </BookAll>
57         </Student>
58 </StudentAll>

 

 

posted @ 2013-02-19 17:14  天天_byconan  阅读(1825)  评论(0编辑  收藏  举报