通用xml转Object 记录
直接上代码,基于dom4j解析xml转obj
package com.baiyang.oms.modular.ningpocang.util;
import com.baiyang.oms.modular.ningpocang.model.response.QueryInventoryResp;
import org.apache.commons.beanutils.PropertyUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* 说明:XML工具类
*
* @author:wangjunpeng
* @Date:2018/12/20
*/
public class XmlUtil {
/**
* 通用返回响应实体
* 基于 dom4j
*
* @param xmlStr
* @param <T>
* @return
*/
public static <T> T xmlToObject(String xmlStr, Class<T> t) {
System.out.println(xmlStr);
try {
Document doc = DocumentHelper.parseText(xmlStr);
// 解析第一层跟目录-mo层
Element element = doc.getRootElement();
return analyzeXml(t, element);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 递归解析xml
* 支持List
*
* @param t
* @param el
* @return
*/
private static <T> T analyzeXml(Class<T> t, Element el) throws Exception {
T tt = t.newInstance();
Iterator it = el.elementIterator();
while (it.hasNext()) {
Element el2 = (Element) it.next();
String name = el2.getName();
String text = el2.getText();
Class<?> childClazz = PropertyUtils.getPropertyType(tt, name);
if (childClazz == null) continue;
if (List.class.getTypeName().equals(childClazz.getName())) {
Field field = searchFields(getAllFields(tt), name);
Type type = field.getGenericType();
if (type == null) continue;
// 如果是泛型参数的类型
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
//得到泛型里的class类型对象
Class<?> genericClazz = (Class<?>) pt.getActualTypeArguments()[0];
List<?> list = parseXml2List(el2, genericClazz);
PropertyUtils.setProperty(tt, name, list);
}
continue;
}
Object child = childClazz.newInstance();
if (!(child instanceof String)) {
child = analyzeXml(childClazz, el2);
PropertyUtils.setProperty(tt, name, child);
} else {
PropertyUtils.setProperty(tt, name, text);
}
}
return tt;
}
/**
* 解析xml中List
*
* @param el
* @param cls
* @return
* @throws Exception
*/
private static List<?> parseXml2List(Element el, Class<?> cls) throws Exception {
List<Object> lists = new ArrayList<>();
Iterator it = el.elementIterator();
while (it.hasNext()) {
Element el2 = (Element) it.next();
String name = el2.getName();
String text = el2.getText();
Object obj = analyzeXml(cls, el2);
lists.add(obj);
}
return lists;
}
/**
* 获取所有一个对象类中以及父类中的属性信息
*
* @param object
* @return
*/
private static Field[] getAllFields(Object object) {
Class clazz = object.getClass();
List<Field> fieldList = new ArrayList<>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
/**
* 查询所有filed中指定name
*
* @param fields 所有对象属性数组
* @param name 变量名
* @return
*/
private static Field searchFields(Field[] fields, String name) {
String internedName = name.intern();
for (int i = 0; i < fields.length; i++) {
if (fields[i].getName() == internedName) {
return fields[i];
}
}
return null;
}
public static void main(String[] args) {
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<response>\n" +
" <flag>success|failure</flag>\n" +
" <code>响应码</code>\n" +
" <message>响应信息</message>\n" +
" <items> \n" +
" <item> \n" +
" <warehouseCode>仓库编码, string (50) </warehouseCode> \n" +
" <itemCode>商品编码, string (50) , 必填</itemCode> \n" +
" <itemId>仓储系统商品ID, string (50),条件必填</itemId> \n" +
" <inventoryType>库存类型,string (50) , ZP=正品, CC=残次,JS=机损, XS= 箱损, ZT=在途库存</inventoryType> \n" +
" <quantity>正品实物在库库存量,int,必填</quantity> \n" +
" <lockQuantity>冻结库存数量,int,必填 </lockQuantity>\n" +
" <batchCode>批次编码, string (50) </batchCode> \n" +
" <productDate>商品生产日期 YYYY-MM-DD</productDate> \n" +
" <expireDate>商品过期日期YYYY-MM-DD</expireDate> \n" +
" <produceCode>生产批号, string (50) </produceCode> \n" +
" <extendProps>扩展属性 \n" +
" <key1>value1</key1> \n" +
" <key2>value2</key2> \n" +
" </extendProps> \n" +
" </item> \n" +
" </items> \n" +
"</response>\n";
QueryInventoryResp resp = xmlToBaseResponse(xml, QueryInventoryResp.class);
System.out.println(resp.toString());
}
}
QueryInventoryResp 实体类代码
package com.baiyang.oms.modular.ningpocang.model.response;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import java.util.List;
/**
* 说明:库存查询返回实体
*
* @author:wangjunpeng
* @Date:2018/12/21
*/
@Data
@XStreamAlias("response")
public class QueryInventoryResp {
/**
* success|failure
*/
private String flag;
/**
* 返回状态码
*/
private String code;
/**
* 返回状态描述
*/
private String message;
List<QueryInventoryItem> items;
}
QueryInventoryItem 实体
package com.baiyang.oms.modular.ningpocang.model.response;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import java.util.Map;
/**
* 说明:库存信息
*
* @author:wangjunpeng
* @Date:2018/12/21
*/
@Data
@XStreamAlias("item")
public class QueryInventoryItem {
/**
* 仓库编码
*/
private String warehouseCode;
/**
* 商品编码
*/
private String itemCode;
/**
* 仓储系统商品ID
*/
private String itemId;
/**
* 库存类型,string (50) , ZP=正品, CC=残次,JS=机损, XS= 箱损, ZT=在途库存
*/
private String inventoryType;
/**
* 正品实物在库库存量
*/
private String quantity;
/**
* 冻结库存数量
*/
private String lockQuantity;
/**
* 批次编码
*/
private String batchCode;
/**
* 商品生产日期 YYYY-MM-DD
*/
private String productDate;
/**
* 商品过期日期YYYY-MM-DD
*/
private String expireDate;
/**
* 生产批号, string (50)
*/
private String produceCode;
// /**
// * 扩展属性
// */
// private Map<String, String> extendProps;
}