您的位置:首页 > 编程语言 > Java开发

将List<T>生成XML文档(字串),将XML文档(字串)解析成List<T>,适用于任何对象的

2016-10-07 00:00 417 查看
很多刚开始涉猎web开发的猿友可能会遇到一个情况,就是将服务器端的数据传回前端,如果前端是浏览器的话是没有什么问题的,把服务器的各种对象属性通过OGNL或者JSTL等等很轻松的呈现出来。可如果前端是JavaSE开发的桌面应用或者Android应用,就比较麻烦了。

这时我们只能传回去一些Header或者Content,也就是头和字串,所以也就产生了把字串格式规划好,传回去然后按照一定的规则解析出来,得到需要的属性,而我们常用的无非是XML与JSON两种格式数据。

对于JSON与XML在性能与格式上各有优点,XMl格式统一,符合标准,安全,缺点就是格式复杂,前后端解析需要大量的代码,JSON的话格式简单,易于读写,但是相对XML通用性还不是特别强。

使用XML传输对象的时候,往往我们需要将一个对象的各种属性转化成字符串构建成一个XML,然后解析的时候再将XML文件或者字符串取出来,赋值给对象的属性,由此生成一个具有有效属性的对象。

而每个对象的属性必然是不同的,所以经常我们会为每个对象写一套解析方法,所以庞大的代码工作量就产生了,那么有没有简单一点的方法呢?我是这样做的,话不多说,先上效果图。

public class Person {
static final private String SPLIT_MARK = "#";

private int id;
private String username;// 账号
private String password;// 密码
private String name;// 名称
private String bound;// 绑定
...
}

执行代码

public static void main(String[] args) {
Person person = new Person();
person.setId(2);
person.setName("xiao南瓜");
person.setUsername("abc");
person.setPassword("123");
person.setBound("!@#");
String sXml=ParseList(Arrays.asList(person), Person.class);
System.out.println(sXml);
}

结果



图截取不下来,在文件中或者浏览器格式是很好的,把输出结果给大家复制出来看

<?xml version="1.0" encoding="UTF-8"?>
<_persons><_person><person_id>2</person_id><person_username>abc</person_username><person_password>123</person_password><person_name>xiao南瓜</person_name><person_bound>!@#</person_bound></_person></_persons>

然后再将生成的xml字符串转回对象

public static void main(String[] args) {
Person person = new Person();
person.setId(2);
person.setName("xiao南瓜");
person.setUsername("abc");
person.setPassword("123");
person.setBound("!@#");
String sXml = ParseList(Arrays.asList(person), Person.class);
List<Person> persons = ParseXML(sXml, Person.class);
Person person2 = persons.get(0);
System.out.println(person);
System.out.println(person2);
}

结果(重写的toString方法)



这就是List与XML的正向逆向解析,如果是一个对象就将这个对象转换为List即可。

再测试一个Java对象

public class Location {
private int id;
private double longi;// 经度
private double lati;// 纬度
private String address;// 位置描述
private Timestamp lastTime;// 最后修改时间
private String recordPath;// 位置记录存储路径
private Person person;// 何人的位置
...
}

public static void main(String[] args) {
Person person=new Person();
person.setId(7);

Location location=new Location();
location.setId(3);
location.setLongi(12.34);
location.setLati(56.78);
location.setLastTime(new Timestamp(System.currentTimeMillis()));
location.setAddress("山西");
location.setRecordPath("F:\\");
location.setPerson(person);

String sXml=ParseList(Arrays.asList(location), Location.class);
List<Location> locations=ParseXML(sXml, Location.class);
Location location2=locations.get(0);
System.out.println(location);
System.out.println(location2);
}

结果



这些自定义的JavaBean有一些特点需要记住

1.所有属性只能是8种基本类型,即byte,short,int,long,float,double,boolean,String以及Timestamp。

2.可以有其他类型对象作为属性,但其他类型对象也必须符合这些规则。

3.对象中必须有id属性,名字必须是id且必须是int类型,这是为了标识null对象与标识其他对象(外键)做的。

4.null对象也会解析成xml,只不过id为-1,表示null对象,当然如果xml中如果有id属性为-1的也会解析成null对象。

5.所有外键(其他自定义的对象作为属性)在xml中只会保存id属性,为了防止外键为自己时的无限迭代。

因为我们服务器的大多数Bean都是数据库来的,或者存或者取,所以虽然支持的类型不多,不过也应该够用了。前台用的话只要把响应的Bean的class与这个模型拷贝过去即可。

希望能帮助大家。

如果有什么不对或者更好的建议,希望大家提出来,谢谢,因为是第一次写,不足之处多多指教。

模型源码,使用方式以及思路注释里都有

public class BeanModel2 {
private static final String ATTR_ID = "id";// bean的id属性
private static final int NULL_ID = -1;

// 根据bean自动构建xml的root名字
public static String GetRootName(Class<?> bean) {
String root_name = "_" + bean.getSimpleName().toLowerCase() + "s";
return root_name;
}

// 根据bean自动构建xml的child名字
public static String GetElemName(Class<?> bean) {
String elem_name = "_" + bean.getSimpleName().toLowerCase();
return elem_name;
}

// 根据bean和field构建xml中child的attribute名字
public static String GetAttrName(Class<?> bean, Field field) {
String attr_name = bean.getSimpleName().toLowerCase() + "_"
+ field.getName();
return attr_name;
}

// 根据field与element获取此field对应的value
@SuppressWarnings("finally")
public static <T> String GetAttrValue(Field field, T elem) {
String value = "";
try {
Class<?> type = field.getType();// 获取此field的类型
/*
* 下面依次处理 八种基本类型 Timestamp类型 其他类型(带有id属性的bean类型)
*/
if (type.equals(Byte.class) || type.equals(byte.class)) {
value = field.getByte(elem) + "";
} else if (type.equals(Short.class) || type.equals(short.class)) {
value = field.getShort(elem) + "";
} else if (type.equals(Integer.class) || type.equals(int.class)) {
value = field.getInt(elem) + "";
} else if (type.equals(Long.class) || type.equals(long.class)) {
value = field.getLong(elem) + "";
} else if (type.equals(Float.class) || type.equals(float.class)) {
value = field.getFloat(elem) + "";
} else if (type.equals(Double.class) || type.equals(double.class)) {
value = field.getDouble(elem) + "";
} else if (type.equals(Boolean.class) || type.equals(boolean.class)) {
value = field.getBoolean(elem) + "";
} else if (type.equals(String.class)) {
value = (String) field.get(elem);
} else if (type.equals(Timestamp.class)) {
value = ((Timestamp) field.get(elem)).getTime() + "";
} else {
// 如果这个类型有id这个属性,说明它是个外键
Field attr_id = type.getDeclaredField(ATTR_ID);
// 并且此属性不为null
if (attr_id != null && field.get(elem) != null) {
attr_id.setAccessible(true);
value = attr_id.getInt(field.get(elem)) + "";
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} finally {
return value == null ? "" : value;
}
}

public static <T> void SetAttrValue(Field field, T elem, String value) {
try {
Class<?> type = field.getType();
if (type.equals(Byte.class) || type.equals(byte.class)) {
try {
field.setByte(elem, Byte.parseByte(value));
} catch (NumberFormatException e) {
// 数字格式化异常,未做任何处理
}
} else if (type.equals(Short.class) || type.equals(short.class)) {
try {
field.setShort(elem, Short.parseShort(value));
} catch (NumberFormatException e) {
// 数字格式化异常,未做任何处理
}
} else if (type.equals(Integer.class) || type.equals(int.class)) {
try {
field.setInt(elem, Integer.parseInt(value));
} catch (NumberFormatException e) {
field.setInt(elem, NULL_ID);
}
} else if (type.equals(Long.class) || type.equals(long.class)) {
try {
field.setLong(elem, Long.parseLong(value));
} catch (NumberFormatException e) {
// 数字格式化异常,未做任何处理
}
} else if (type.equals(Float.class) || type.equals(float.class)) {
try {
field.setFloat(elem, Float.parseFloat(value));
} catch (NumberFormatException e) {
// 数字格式化异常,未做任何处理
}
} else if (type.equals(Double.class) || type.equals(double.class)) {
try {
field.setDouble(elem, Double.parseDouble(value));
} catch (NumberFormatException e) {
// 数字格式化异常,未做任何处理
}
} else if (type.equals(Boolean.class) || type.equals(boolean.class)) {
try {
field.setBoolean(elem, Boolean.parseBoolean(value));
} catch (Exception e) {
e.printStackTrace();
}
} else if (type.equals(String.class)) {
field.set(elem, value);
} else if (type.equals(Timestamp.class)) {
try {
field.set(elem, new Timestamp(Long.parseLong(value)));
} catch (NumberFormatException e) {
// 如果格式化异常,说明这个Timestamp是个null字串,当么它的值也为null
field.set(elem, null);
}
} else {
Field attr_id = type.getDeclaredField(ATTR_ID);
if (attr_id != null) {
attr_id.setAccessible(true);
Object external = type.newInstance();
try {
attr_id.setInt(external, Integer.parseInt(value));
field.set(elem, external);
} catch (NumberFormatException e) {
// 如果格式化出现异常,那么这个外键为null
field.set(elem, null);
}
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}

public static <T> String ParseList(List<T> list, Class<?> bean) {
Document document = DocumentHelper.createDocument();// 获取document
document.setXMLEncoding("UTF-8");// 设置编码
Element root = document.addElement(GetRootName(bean));// 创建根元素

Field[] fields = bean.getDeclaredFields();// 获得bean的所有属性
for (T elem : list) {// 开始迭代传入的list
Element child = root.addElement(GetElemName(bean));// 创建子元素

for (Field field : fields) {// 迭代属性并且赋值
int mod = field.getModifiers();
if (Modifier.isFinal(mod) || Modifier.isStatic(mod)
|| Modifier.isPublic(mod)) {
continue;
}
field.setAccessible(true);// 打破封装性
String attr_name = GetAttrName(bean, field);// 获取bean属性对应的xml文件中的名字
String attr_value = GetAttrValue(field, elem);// 获取此属性对应的值
// System.out.println(attr_name+"="+attr_value);
child.addElement(attr_name).setText(attr_value);// 创建属性并赋值
}
}

return document.asXML();
}

@SuppressWarnings({ "unchecked", "finally" })
public static <T> List<T> ParseXML(String content, Class<?> bean) {
List<T> elements = new ArrayList<T>();// 构建一个空的list
try {
Document document = DocumentHelper.parseText(content);// 根据传入的content获取document
Element rootElement = document.getRootElement();// 获取根元素

Field[] fields = bean.getDeclaredFields();// 获取此bean的所有属性
// 迭代根元素下所有的子元素
for (Iterator<Element> childs = rootElement.elements().iterator(); childs
.hasNext();) {
T element = (T) bean.newInstance();// 根据bean创建一个对象
Element child = childs.next();// 依次获取子元素
for (Field field : fields) {
int mod = field.getModifiers();
if (Modifier.isFinal(mod) || Modifier.isStatic(mod)
|| Modifier.isPublic(mod)) {
continue;
}
field.setAccessible(true);
String attr_name = GetAttrName(bean, field);// 获取属性名
Element param = child.element(attr_name);
;// 根据属性名获取属性
String attr_value = param.getText();// 获取属性值
SetAttrValue(field, element, attr_value);// 设置属性值
// System.out.println("->"+attr_name+"="+attr_value);
}

// 判断该element是否==null?
Field field_id = bean.getDeclaredField(ATTR_ID);
if (field_id != null) {
field_id.setAccessible(true);
if (field_id.getInt(element) == NULL_ID) {
elements.add(null);
continue;
}
}

elements.add(element);// 把初始化好的element添加到elements中
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} finally {
return elements;
}
}

/*
* 将一个文件读取出来解析成列表
*/
@SuppressWarnings("finally")
public static <T> List<T> ReadListByFile(String path, Class<?> bean) {
List<T> elements = new ArrayList<T>();// 构建一个空的list
try {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File(path));
Element rootElement = document.getRootElement();// 获取根元素

Field[] fields = bean.getDeclaredFields();// 获取此bean的所有属性
// 迭代根元素下所有的子元素
for (Iterator<Element> childs = rootElement.elements().iterator(); childs
.hasNext();) {
T element = (T) bean.newInstance();// 根据bean创建一个对象
Element child = childs.next();// 依次获取子元素
for (Field field : fields) {
int mod = field.getModifiers();
if (Modifier.isFinal(mod) || Modifier.isStatic(mod)
|| Modifier.isPublic(mod)) {
continue;
}
field.setAccessible(true);
String attr_name = GetAttrName(bean, field);// 获取属性名
Element param = child.element(attr_name);
;// 根据属性名获取属性
String attr_value = param.getText();// 获取属性值
SetAttrValue(field, element, attr_value);// 设置属性值
// System.out.println("->"+attr_name+"="+attr_value);
}

// 判断该element是否==null?
Field field_id = bean.getDeclaredField(ATTR_ID);
if (field_id != null) {
field_id.setAccessible(true);
if (field_id.getInt(element) == NULL_ID) {
elements.add(null);
continue;
}
}

elements.add(element);// 把初始化好的element添加到elements中
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return elements;
}
}

/*
* 将一个列表写入文件
*/
public static <T> void WriteFileByList(String path, List<T> list,
Class<?> bean) {
/*
* 从这里开始与ParseList是一样的
*/
Document document = DocumentHelper.createDocument();// 获取document
document.setXMLEncoding("UTF-8");// 设置编码
Element root = document.addElement(GetRootName(bean));// 创建根元素

Field[] fields = bean.getDeclaredFields();// 获得bean的所有属性
for (T elem : list) {// 开始迭代传入的list
Element child = root.addElement(GetElemName(bean));// 创建子元素

for (Field field : fields) {// 迭代属性并且赋值
int mod = field.getModifiers();
if (Modifier.isFinal(mod) || Modifier.isStatic(mod)
|| Modifier.isPublic(mod)) {
continue;
}
field.setAccessible(true);// 打破封装性
String attr_name = GetAttrName(bean, field);// 获取bean属性对应的xml文件中的名字
String attr_value = GetAttrValue(field, elem);// 获取此属性对应的值
// System.out.println(attr_name+"="+attr_value);
child.addElement(attr_name).setText(attr_value);// 创建属性并赋值
}
}

/*
* 这里就是把Parse的返回字串转化为了保存为文件而已
*/
FileOutputStream fos = null;
XMLWriter writer = null;
try {
fos = new FileOutputStream(path);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
writer = new XMLWriter(fos, format);
writer.write(document);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

public static <T> void AddElementsByList(String path, List<T> list,
Class<?> bean) {
SAXReader saxReader = new SAXReader();
Document document = null;
try {
document = saxReader.read(new File(path));
} catch (Exception e) {
e.printStackTrace();
return;
}

Element root = document.getRootElement();
Field[] fields = bean.getDeclaredFields();// 获得bean的所有属性
for (T elem : list) {// 开始迭代传入的list
Element child = root.addElement(GetElemName(bean));// 创建子元素

for (Field field : fields) {// 迭代属性并且赋值
int mod = field.getModifiers();
if (Modifier.isFinal(mod) || Modifier.isStatic(mod)
|| Modifier.isPublic(mod)) {
continue;
}
field.setAccessible(true);// 打破封装性
String attr_name = GetAttrName(bean, field);// 获取bean属性对应的xml文件中的名字
String attr_value = GetAttrValue(field, elem);// 获取此属性对应的值
// System.out.println(attr_name+"="+attr_value);
child.addElement(attr_name).setText(attr_value);// 创建属性并赋值
}
}

/*
* 这里就是把Parse的返回字串转化为了保存为文件而已
*/
FileOutputStream fos = null;
XMLWriter writer = null;
try {
fos = new FileOutputStream(path);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
writer = new XMLWriter(fos, format);
writer.write(document);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java XMLBeans