[工具库]JOXMLBuilder工具类——一键把多个bean对象数据转换为XML格式数据
本人大四即将毕业的准程序员(JavaSE、JavaEE、android等)一枚,小项目也做过一点,于是乎一时兴起就写了一些工具。
我会在本博客中陆续发布一些平时可能会用到的工具。
代码质量可能不是很好,大家多担待!
代码或者思路有不妥之处,还希望大牛们能不吝赐教哈!
以下代码为本人原创,转载请注明:
本文转载,来自:http://www.cnblogs.com/tiantianbyconan/archive/2013/02/19/2917398.html
JOXMLBuilder工具类:一键把多个域对象数据转换为XML格式数据,方便用于数据的传输和交互。功能类似于通过Gson来生成Json数据。
源码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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>