package xmlToObject.xmlUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.tree.DefaultElement;
import xmlToObject.xmlUtils.annotation.ListProperty;
import xmlToObject.xmlUtils.annotation.XmlAttribute;
import xmlToObject.xmlUtils.annotation.XmlSupport;
/**
*
* @ClassName: XMLUtils
* @Description: (这里用一句话描述这个类的作用)
* @author zhangdd
* @date 2017年11月3日 下午3:22:43
*/
public class XMLUtils {
public final static String xml_text = "AttrText";//表示有取属性值的标签的 TEXT标记
/**
* 将element解析到object 一、 object中的字段只能是 1对象类型 2字符类型 3list
* 4object(但是必须用自定义对象实例化) 二、element list下的节点名称都要一样
*
* @param xml
* @param object
* @throws InstantiationException
* @throws IllegalAccessException
* @throws DocumentException
*/
public static void xml2Obj(String xml, Object object)
throws InstantiationException, IllegalAccessException,
DocumentException {
Document document = xml2Doc(xml);
doc2Obj(document, object);
}
/**
* 将xml解析成document
*
* @param xml
* @return
* @throws DocumentException
*/
public static Document xml2Doc(String xml) throws DocumentException {
return DocumentHelper.parseText(xml);
}
/**
* 将document解析到object
*
* @param document
* @param object
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void doc2Obj(Document document, Object object)
throws InstantiationException, IllegalAccessException {
Element root = document.getRootElement();
ele2Obj(object, root);
}
/**
* 将element解析到object 一、 object中的字段只能是 1对象类型 2字符类型 3list
* 4object(但是必须用自定义对象实例化) 二、element list下的节点名称都要一样
*
* @param object
* @param parent
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static void ele2Obj(Object object, Element parent)
throws InstantiationException, IllegalAccessException {
// 先判断object和element是否匹配
isRightObj(object, parent);
Class<?> clazz = object.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 私有变量允许访问
field.setAccessible(true);
// String类型的 如果xml有该节点 则增加该值
if (field.getType() == String.class) {
String attribute = getAttribute(field);
if (xml_text.equals(attribute)) {// 取标签的值,如果沒有屬性value则取text
field.set(object, parent.getText());
}else if (attribute == null) {// 取标签节点名称
Element son = parent.element(field.getName().toUpperCase());
if(son==null){
son = parent.element(field.getName());//兼容 区分大小写的做法
}
if(son==null){
son = parent.element(field.getName().toLowerCase());
}
if (son != null) {
field.set(object, son.getText());
}
} else {// 取标签的属性值
Attribute attr = parent.attribute(attribute.toUpperCase());
if(attr ==null){
attr = parent.attribute(attribute);
}
if(attr ==null){
attr = parent.attribute(attribute.toLowerCase());
}
if (attr != null) {
field.set(object, attr.getValue());
}
}
}
// list类型 如果xml有该节点 则处理该节点下的
else if (field.getType() == List.class) {
Element son = parent.element(field.getName().toUpperCase());
if(son==null){
son = parent.element(field.getName());//兼容 区分大小写的做法
}
if(son==null){
son = parent.element(field.getName().toLowerCase());
}
if (son != null) {
// List节点下的节点
List<Element> grandSons = getSons(son);
if (grandSons.size() > 0) {
Class<?> fieldClazz = getListClass(clazz, field);
// 新建该字段类型的list对象
List<Object> list = new ArrayList<Object>();
// 解析list里的内容
for (Element grandSon : grandSons) {
Object fieldObject = fieldClazz.newInstance();
ele2Obj(fieldObject, grandSon);
list.add(fieldObject);
}
// 该list类型的字段赋值
field.set(object, list);
}
}
}
// 实体类型
else {
Object fieldObject = null;
// 如果是object类型的 必须有初始化对象
if (field.getType() == Object.class) {
fieldObject = field.get(object);
if (fieldObject == null) {
throw new RuntimeException(clazz.getName() + "该对象的"
+ field.getName() + "字段为Object类型,必须实例化才能解析xml!");
}
} else {
fieldObject = field.getType().newInstance();
}
String nodeName = getNodeName(fieldObject);
Element son = parent.element(nodeName);
if (son != null) {
ele2Obj(fieldObject, son);
field.set(object, fieldObject);
}
}
}
}
/**
* 判断object和element是否匹配
*
* @param object
* @param element
*/
private static void isRightObj(Object object, Element element) {
if (element == null) {
throw new RuntimeException("element为空!");
}
// 该对象是否有注释类
XmlSupport xmlSupport = object.getClass().getAnnotation(
XmlSupport.class);
if (xmlSupport == null) {
throw new RuntimeException(object.getClass().getCanonicalName()
+ "该对象没有XmlSupport注释类,不支持xml解析!");
}
// 对象是否匹配该element
if (!element.getName().equals(xmlSupport.nodeName())) {
throw new RuntimeException(object.getClass().getCanonicalName()
+ "该对象不适合" + element.getName() + "该节点!");
}
}
/**
* 得到element的所有子element
*
* @param parent
* @return
*/
private static List<Element> getSons(Element parent) {
List<Element> sons = new ArrayList<Element>();
List<?> list = parent.elements();
for (Object object : list) {
if (object.getClass() == DefaultElement.class) {
sons.add((Element) object);
}
}
return sons;
}
/**
* 获取类 的注释对象 申明的 nodeName 用于解析xml
*
* @param object
* @return
*/
private static String getNodeName(Object object) {
return getNodeName(object.getClass());
}
/**
* 获取类 的注释对象 申明的 nodeName 用于解析xml
*
* @param object
* @return
*/
private static String getNodeName(Class<?> clazz) {
XmlSupport xmlSupport = clazz.getAnnotation(XmlSupport.class);
if (xmlSupport == null) {
throw new RuntimeException(clazz.getCanonicalName()
+ "该对象没有XmlSupport注释类,不支持xml解析!");
}
return xmlSupport.nodeName();
}
private static Class<?> getListClass(Class<?> clazz, Field field) {
ListProperty listProperty = field.getAnnotation(ListProperty.class);
if (listProperty == null) {
throw new RuntimeException(clazz.getCanonicalName() + "该对象的"
+ field.getName() + "字段没有ListProperty注释类,不支持xml解析!");
}
return listProperty.clazz();
}
/**
* 获取类 的注释对象 申明的 Attribute 用于解析xml
*
* @param object
* @return
*/
private static String getAttribute(Field field) {
XmlAttribute xmlAttribute = field.getAnnotation(XmlAttribute.class);
return xmlAttribute == null ? null : xmlAttribute.attribute();
}
}