xml工具类
自定义注解IXml
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface IXml {
String nodeName();
String attributeName() default "";
boolean isSon() default false;
String dateFormat() default "";
}
工具类 XmlUtils
package com.ph.xml;
import com.ph.xml.annotation.IXml;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class XmlUtils {
static class NodeXml {
private String nodeName;
private String nodeValue;
private List<Attribute> attributes;
private List<NodeXml> sonXmlNodes;
}
static class Attribute {
private String attributeName;
private String attributeValue;
}
static class ClassNode {
private String nodeName;
private String attributeName;
private String fieldName;
private Class clazz;
private Class parentClass;
private Integer level;
private String value;
private Boolean isNode;
private List<ClassNode> sons;
}
public static <T> List<T> readXml(File xmlFile, Class<T> clazz) {
List<T> data = new ArrayList<>();
Document document = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
document = db.parse(xmlFile);
} catch (Exception e) {
e.printStackTrace();
}
if (document != null) {
Element rootElement = document.getDocumentElement();
NodeXml nodeXml = getNodeXMlInfo(rootElement);
List<ClassNode> rs = new ArrayList<>();
List<ClassNode> resourceClassNodes = getAllFieldMapForClass(clazz, null, rs, 0);
if (nodeXml != null) {
try {
setData(nodeXml, data, clazz, resourceClassNodes);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return data;
}
private static List<ClassNode> getAllFieldMapForClass(Class clazz, Class parentClass, List<ClassNode> rs, Integer level) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
IXml ixml = field.getAnnotation(IXml.class);
if (null != ixml) {
String fieldName = field.getName();
ClassNode classnode = null;
if (!ixml.isSon()) {
String nodeName = ixml.nodeName();
String attributeName = ixml.attributeName();
if (strIsNotBlank(attributeName)) {
classnode = setClassNode(fieldName, nodeName, attributeName, false, clazz, parentClass, level);
} else {
classnode = setClassNode(fieldName, nodeName, null, true, clazz, parentClass, level);
}
} else {
level++;
classnode = setClassNodeSons(field, clazz, level);
}
if (classnode != null) {
rs.add(classnode);
}
}
}
return rs;
}
private static ClassNode setClassNodeSons(Field field, Class parentClass, Integer level) {
Class clazz = getGenericClassForList(field);
ClassNode classNode = null;
if (clazz != null) {
List<ClassNode> classNodes = new ArrayList<>();
List<ClassNode> classNodeSons = getAllFieldMapForClass(clazz, parentClass, classNodes, level);
classNode = new ClassNode();
classNode.sons = classNodeSons;
classNode.fieldName = field.getName();
}
return classNode;
}
private static Class getGenericClassForList(Field field) {
Class clazz = null;
if (field.getType() == List.class) {
Type genericType = field.getGenericType();
if (genericType != null && genericType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genericType;
clazz = (Class<?>) pt.getActualTypeArguments()[0];
}
}
return clazz;
}
private static ClassNode setClassNode(String fieldName, String nodeName, String attributeName, Boolean isNode, Class clazz, Class parentClass, Integer level) {
ClassNode classNode = new ClassNode();
classNode.fieldName = fieldName;
classNode.attributeName = attributeName;
classNode.nodeName = nodeName;
classNode.isNode = isNode;
classNode.clazz = clazz;
classNode.parentClass = parentClass;
classNode.level = level;
return classNode;
}
private static <T> void setData(NodeXml nodeXml, List<T> data, Class<T> sourceClazz, List<ClassNode> resourceClassNodes) throws Exception {
List nowObjLevel = new ArrayList();
List<ClassNode> classNodeValuesMapping = new ArrayList<>();
getNodeValueToClassNodeValue(nodeXml, resourceClassNodes, classNodeValuesMapping);
classNodeValuesMapping.add(null);
Object nowObject = sourceClazz.newInstance();
nowObjLevel.add(nowObject);
List sonList = getSonList(nowObject);
if (classNodeValuesMapping.size() > 1) {
for (ClassNode classNode : classNodeValuesMapping) {
if (classNode != null) {
Class nodeClazz = classNode.clazz;
Boolean isFill = checkNowObjectIsFill(nowObject);
if (isFill) {
if (nowObject.getClass().getTypeName().equals(sourceClazz.getTypeName())) {
data.add((T) nowObject);
} else {
if (sonList != null) {
sonList.add(nowObject);
}
}
nowObject = nodeClazz.newInstance();
Integer nowLevel = classNode.level;
if ((nowLevel + 1) <= nowObjLevel.size()) {
nowObjLevel.set(nowLevel, nowObject);
} else {
nowObjLevel.add(nowObject);
}
Class parentClass = classNode.parentClass;
if (parentClass != null) {
Object nowParentObj = findParentObj(parentClass, nowObjLevel);
sonList = getSonList(nowParentObj);
}
}
nodeValueToObject(classNode, classNode.value, nowObject);
} else {
if (nowObject.getClass().getTypeName().equals(sourceClazz.getTypeName())) {
data.add((T) nowObject);
} else {
if (sonList != null) {
sonList.add(nowObject);
}
}
}
}
}
}
private static Object findParentObj(Class parentClass, List nowObjLevel) {
String typeName = parentClass.getTypeName();
for (Object obj : nowObjLevel) {
if (obj.getClass().getTypeName().equals(typeName)) {
return obj;
}
}
return null;
}
private static List getSonList(Object nowParentObj) throws Exception {
Class clazz = nowParentObj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
IXml Ixml = field.getAnnotation(IXml.class);
if (Ixml != null && Ixml.isSon()) {
Object sonList = field.get(nowParentObj);
if (sonList != null) {
return (List) sonList;
} else {
List newSonList = new ArrayList<>();
field.set(nowParentObj, newSonList);
return newSonList;
}
}
}
return null;
}
private static <T> void getNodeValueToClassNodeValue(NodeXml nodeXml, List<ClassNode> resourceClassNodes, List<ClassNode> classNodeValueMappings) throws Exception {
String nodeName = nodeXml.nodeName;
List<ClassNode> classNodes = new ArrayList<>();
findClassNodeByNodeName(nodeName, resourceClassNodes, classNodes);
if (classNodes.size() > 0) {
for (ClassNode classNode : classNodes) {
String value = getValueFromXml(classNode, nodeXml);
ClassNode newClassNode = new ClassNode();
newClassNode.nodeName = classNode.nodeName;
newClassNode.fieldName = classNode.fieldName;
newClassNode.attributeName = classNode.attributeName;
newClassNode.clazz = classNode.clazz;
newClassNode.parentClass = classNode.parentClass;
newClassNode.isNode = classNode.isNode;
newClassNode.level = classNode.level;
newClassNode.value = value;
classNodeValueMappings.add(newClassNode);
}
}
List<NodeXml> sonXmlNodes = nodeXml.sonXmlNodes;
if (sonXmlNodes != null && sonXmlNodes.size() > 0) {
for (NodeXml sonXmlNode : sonXmlNodes) {
getNodeValueToClassNodeValue(sonXmlNode, resourceClassNodes, classNodeValueMappings);
}
}
}
private static void nodeValueToObject(ClassNode classNode, String value, Object nowObject) {
Field field = getFieldFromClassNode(classNode, nowObject);
if (value != null && field != null) {
try {
field.setAccessible(true);
Class<?> type = field.getType();
if (type == Double.class || type == double.class) {
Double newValue = Double.valueOf(value);
field.set(nowObject, newValue);
} else if (type == Long.class || type == long.class) {
Long newValue = Long.valueOf(value);
field.set(nowObject, newValue);
} else if (type == Date.class) {
IXml iXml = field.getAnnotation(IXml.class);
if (iXml != null) {
String dateFormat = iXml.dateFormat();
if (strIsNotBlank(dateFormat)) {
SimpleDateFormat format = new SimpleDateFormat(dateFormat);
Date newValue = format.parse(value);
field.set(nowObject, newValue);
}
}
} else if (type == Integer.class || type == int.class) {
Integer newValue = Integer.valueOf(value);
field.set(nowObject, newValue);
} else {
field.set(nowObject, value);
}
} catch (IllegalAccessException | ParseException | IllegalArgumentException e) {
throw new RuntimeException("属性:[" + classNode.fieldName + "]与value : " + value + " 类型转换异常 " + e);
}
}
}
private static Field getFieldFromClassNode(ClassNode classNode, Object nowObject) {
String fieldName = classNode.fieldName;
Class<?> clazz = nowObject.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.getName().equals(fieldName)) {
return field;
}
}
return null;
}
private static String getValueFromXml(ClassNode classNode, NodeXml nodeXml) {
Boolean isNode = classNode.isNode;
if (isNode) {
return nodeXml.nodeValue;
} else {
String attributeName = classNode.attributeName;
List<Attribute> attributes = nodeXml.attributes;
for (Attribute attribute : attributes) {
if (attribute.attributeName.equals(attributeName)) {
return attribute.attributeValue;
}
}
}
return null;
}
private static Boolean checkNowObjectIsFill(Object nowObject) throws Exception {
Class nowClass = nowObject.getClass();
Field[] fields = nowClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
IXml ixml = field.getAnnotation(IXml.class);
if (ixml != null && !ixml.isSon()) {
Object obj = field.get(nowObject);
if (obj == null) {
return false;
}
}
}
return true;
}
private static void findClassNodeByNodeName(String nodeName, List<ClassNode> resourceClassNodes, List<ClassNode> classNodes) {
for (ClassNode classNode : resourceClassNodes) {
if (classNode.sons == null) {
if (nodeName.equals(classNode.nodeName)) {
classNodes.add(classNode);
}
} else {
findClassNodeByNodeName(nodeName, classNode.sons, classNodes);
}
}
}
private static NodeXml getNodeXMlInfo(Element rootElement) {
NodeXml nodeXml = null;
if (rootElement != null) {
nodeXml = new NodeXml();
nodeXml.nodeName = rootElement.getNodeName();
nodeXml.nodeValue = strIsNotBlank(rootElement.getNodeValue()) ? rootElement.getNodeValue() : "";
NamedNodeMap attributes = rootElement.getAttributes();
List<Attribute> attributeInfo = getAttributeInfo(attributes);
nodeXml.attributes = attributeInfo;
NodeList childNodes = rootElement.getChildNodes();
if (childNodes != null && childNodes.getLength() > 0) nodeXml.sonXmlNodes = getSonNodeInfo(childNodes);
}
return nodeXml;
}
private static List<NodeXml> getSonNodeInfo(NodeList nodeList) {
List<NodeXml> nodeXmlList = new ArrayList<>();
int nodeLength = nodeList.getLength();
for (int i = 0; i < nodeLength; i++) {
Node nodeItem = nodeList.item(i);
String nodeName = nodeItem.getNodeName();
if (checkNodeName(nodeName)) {
NodeXml nodeXml = setNodeInfo(nodeItem);
NodeList childNodes = nodeItem.getChildNodes();
if (childNodes != null && childNodes.getLength() > 0) nodeXml.sonXmlNodes = getSonNodeInfo(childNodes);
nodeXmlList.add(nodeXml);
}
}
return nodeXmlList;
}
private static NodeXml setNodeInfo(Node nodeItem) {
NodeXml nodeXml = new NodeXml();
nodeXml.nodeName = nodeItem.getNodeName();
Node firstChild = nodeItem.getFirstChild();
if (firstChild != null) {
nodeXml.nodeValue = firstChild.getNodeValue();
}
NamedNodeMap attributes = nodeItem.getAttributes();
List<Attribute> attributeList = getAttributeInfo(attributes);
nodeXml.attributes = attributeList;
return nodeXml;
}
private static List<Attribute> getAttributeInfo(NamedNodeMap attributes) {
List<Attribute> attributeList = new ArrayList<>();
int attributeLength;
if (attributes != null && (attributeLength = attributes.getLength()) > 0) {
for (int j = 0; j < attributeLength; j++) {
Node attributeNode = attributes.item(j);
Attribute attribute = new Attribute();
attribute.attributeName = attributeNode.getNodeName();
attribute.attributeValue = strIsNotBlank(attributeNode.getNodeValue()) ? attributeNode.getNodeValue() : "";
attributeList.add(attribute);
}
}
return attributeList;
}
private static Boolean checkNodeName(String nodeName) {
return nodeName != null && nodeName.trim() != "" && !nodeName.trim().equals("#text");
}
private static Boolean strIsNotBlank(String str) {
return str != null && !str.trim().equals("");
}
}
示例xml文件
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="订单XML Schema-3.0.xsd" License="00120-100290-002">
<Events version="3.0">
<Event name="Order">
<Order orderNo="D181101004" orderTime="2023-01-01" buyer="小明" moneyTotal="300">
<OrderDetails>
<Detail>
<GoodeName>芒果GoodeName>
<Count>10Count>
<Money>100Money>
Detail>
<Detail>
<GoodeName>香蕉GoodeName>
<Count>20Count>
<Money>100Money>
Detail>
<Detail>
<GoodeName>橘子GoodeName>
<Count>30Count>
<Money>100Money>
Detail>
OrderDetails>
Order>
Event>
Events>
Document>
示例xml相关实体类—Order
import java.util.Date;
import java.util.List;
public class Order {
@IXml(nodeName = "Order", attributeName = "orderNo")
private String orderNo;
@IXml(nodeName = "Order", attributeName = "orderTime", dateFormat = "yyyy-MM-dd")
private Date orderTime;
@IXml(nodeName = "Order", attributeName = "buyer")
private String buyer;
@IXml(nodeName = "Order", attributeName = "moneyTotal")
private Double moneyTotal;
@IXml(nodeName = "这里名称随便写,或者空字符串都行", isSon = true)
private List<OrderDetail> details;
public Order(String orderNo, Date orderTime, String buyer, Double moneyTotal, List<OrderDetail> details) {
this.orderNo = orderNo;
this.orderTime = orderTime;
this.buyer = buyer;
this.moneyTotal = moneyTotal;
this.details = details;
}
public Order() {
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public Date getOrderTime() {
return orderTime;
}
public void setOrderTime(Date orderTime) {
this.orderTime = orderTime;
}
public String getBuyer() {
return buyer;
}
public void setBuyer(String buyer) {
this.buyer = buyer;
}
public Double getMoneyTotal() {
return moneyTotal;
}
public void setMoneyTotal(Double moneyTotal) {
this.moneyTotal = moneyTotal;
}
public List<OrderDetail> getDetails() {
return details;
}
public void setDetails(List<OrderDetail> details) {
this.details = details;
}
@Override
public String toString() {
return "Order{" +
"orderNo='" + orderNo + '\'' +
", orderTime=" + orderTime +
", buyer='" + buyer + '\'' +
", moneyTotal=" + moneyTotal +
", details=" + details +
'}';
}
}
示例xml相关实体类—OrderDetail
import java.util.Date;
public class OrderDetail {
@IXml(nodeName = "GoodeName")
private String goodName;
@IXml(nodeName = "Count")
private Integer count;
@IXml(nodeName = "Money")
private Double money;
public OrderDetail(String goodName, Integer count, Double money) {
this.goodName = goodName;
this.count = count;
this.money = money;
}
public OrderDetail() {
}
public String getGoodName() {
return goodName;
}
public void setGoodName(String goodName) {
this.goodName = goodName;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "OrderDetail{" +
"goodName='" + goodName + '\'' +
", count=" + count +
", money=" + money +
'}';
}
}
测试方法
public static void main(String[] args) throws Exception {
File file = new File("D:\\PH\\Desktop\\工作\\测试xml\\订单.xml");
List<Order> relations = XmlUtils.readXml(file, Order.class);
relations.stream().forEach(item -> System.out.println(item));
}