xml工具类
自定义注解ixml
import java.lang.annotation.*;
/**
* @classname: ixml
* @description: 注意:当前判断新建节点映射对象是根据类成员变量所有标注当前注解的字段值都不为null,
* 所以:
* 一 :所有nodename都必须存在于xml文件中(区分大小写)
* 二 :所有相同node节点和attributename都必须相同,个数都保持一致
* @1"<code curcode="21000090000000011001" packlayer="3" flag="0" />"
* @2“<code curcode="21000080000000019897" packlayer="2" flag="0" parentcode="21000090000000011001"/>”
* 1比2少一个 parentcode ,造成只读取了2这一条数据,可以给1 添加一个parentcode=“” 空字符串即可
* 三:如果不确定某个节点或属性一定有值,标注该注解的成员变量类型用string
* @date: 2023/3/20 14:24
* @author: ph9527
* @version: 1.0
*/
@retention(retentionpolicy.runtime)
@target(elementtype.field)
public @interface ixml {
/**
* 当前字段所属xml的标签名称
*
* @return
* @注意1: 默认取值为标签的内容,如果是标签的属性值,添加“attributename”
* @注意2: 如果不需要attribute的信息不要填写 (不要填写 不要填写 不要填写) attributename
*/
string nodename();
/**
* 标签的属性名称
*
* @return
* @注意1: 当该字段的值为xml中的属性描述的值时,该属性“attributename”必填
* @注意2: 如果不需要该值,不要填写 不要填写 不要填写 不要填写
*/
string attributename() default "";
/**
* 是否子集,当为true时,nodename可以填写任何值,
*
* @return
*/
boolean isson() default false;
/**
* 日期转换格式
*
* @return
*/
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;
/**
* @classname: xmlutils
* @description: todo
* @date: 2023/3/20 14:24
* @author: ph9527
* @version: 1.0
*/
public class xmlutils {
/**
* xml结构
*/
static class nodexml {
//节点名称
private string nodename;
//节点值
private string nodevalue;
//属性名称
private list<attribute> attributes;
private list<nodexml> sonxmlnodes;
}
/**
* xml属性
*/
static class attribute {
//属性名称
private string attributename;
//属性值
private string attributevalue;
}
/**
* 实体类与xml映射
*/
static class classnode {
//node名称
private string nodename;
//attribute名称
private string attributename;
//class字段名称
private string fieldname;
//当前字段所在clazz
private class clazz;
//父级class对象
private class parentclass;
//节点级别
private integer level;
//节点的值
private string value;
//true:当前类成员变量值为node的值; false:当前成员变量值为所属node的attribute的值
private boolean isnode;
private list<classnode> sons;
}
/**
* 读取xml文件
*
* @param xmlfile
* @param clazz
* @param <t>
* @return
*/
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对象
document = db.parse(xmlfile);
} catch (exception e) {
e.printstacktrace();
}
if (document != null) {
element rootelement = document.getdocumentelement();
//获取整个xml节点信息
nodexml nodexml = getnodexmlinfo(rootelement);
//获取当前entity的所有注解@ixml的属性
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;
}
/**
* 获取class与node的所有映射
*
* @param clazz
* @param parentclass
* @param rs
* @param level
* @return
*/
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();
//如果ixml.attributename为空则field的值为node 反之值为attribute的值
if (strisnotblank(attributename)) {
// field的值为attribute的值
classnode = setclassnode(fieldname, nodename, attributename, false, clazz, parentclass, level);
} else {
// field的值为node的值
classnode = setclassnode(fieldname, nodename, null, true, clazz, parentclass, level);
}
} else {
level++;
//子集
classnode = setclassnodesons(field, clazz, level);
}
if (classnode != null) {
rs.add(classnode);
}
}
}
return rs;
}
/**
* 设置classnode子集
*
* @param field
* @param parentclass
* @param level
* @return
*/
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;
}
/**
* 获取list的泛型类型
*
* @param field
* @return
*/
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;
}
/**
* 设置classnode信息
*
* @param fieldname
* @param attributename
* @param isnode
* @param clazz
* @param parentclass
* @param level
* @return
*/
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;
}
/**
* 设置值
*
* @param nodexml
* @param data
* @param sourceclazz
* @param resourceclassnodes
* @param <t>
*/
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);
//添加一个null,多循环一次,添加最后一个对象到list
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);
}
}
}
}
}
}
/**
* 获取当前对象的父级对象
*
* @param parentclass
* @param nowobjlevel
* @return
*/
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;
}
/**
* 获取当前对象有注解@ixml且isson=true的list
*
* @param nowparentobj
* @return
*/
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;
}
/**
* 获取所有字段的值
*
* @param nodexml 当前节点
* @param resourceclassnodes
* @param classnodevaluemappings
* @param <t>
* @throws instantiationexception
* @throws illegalaccessexception
*/
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);
}
}
}
/**
* 填充值到当前对象
*
* @param classnode
* @param value
* @param nowobject
*/
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);
}
}
}
/**
* 获取需要设置值的字段
*
* @param classnode
* @param nowobject
* @return
*/
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;
}
/**
* 从xml获取值
*
* @param classnode
* @param nodexml
* @return
*/
private static string getvaluefromxml(classnode classnode, nodexml nodexml) {
boolean isnode = classnode.isnode;
if (isnode) {//field值为node的值
return nodexml.nodevalue;
} else {//field值为node属性值
string attributename = classnode.attributename;
list<attribute> attributes = nodexml.attributes;
for (attribute attribute : attributes) {
if (attribute.attributename.equals(attributename)) {
return attribute.attributevalue;
}
}
}
return null;
}
/**
* 检测当前对象所有标有注解ixml的属性都已赋值(子集属性除外)
*
* @param nowobject
* @return
*/
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;
}
/**
* 根据nodename查询classnode
*
* @param nodename
* @param resourceclassnodes
* @param classnodes
* @return
*/
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);
}
}
}
/**
* 获取整个xml节点的信息
*
* @param rootelement
* @return
*/
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;
}
/**
* 获取节点相关信息
*
* @param nodelist
*/
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;
}
/**
* 设置节点相关信息
*
* @param nodeitem
* @return
*/
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;
}
/**
* 获取属性相关信息
*
* @param attributes
* @return
*/
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;
}
/**
* 检测节点名称不为空
*
* @param nodename
* @return
*/
private static boolean checknodename(string nodename) {
return nodename != null && nodename.trim() != "" && !nodename.trim().equals("#text");
}
/**
* 检验字符串不为空
*
* @param str
* @return
*/
private static boolean strisnotblank(string str) {
return str != null && !str.trim().equals("");
}
}
示例xml文件
<?xml version="1.0" encoding="utf-8"?>
<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>10</count>
<money>100</money>
</detail>
<detail>
<goodename>香蕉</goodename>
<count>20</count>
<money>100</money>
</detail>
<detail>
<goodename>橘子</goodename>
<count>30</count>
<money>100</money>
</detail>
</orderdetails>
</order>
</event>
</events>
</document>示例xml相关实体类—order
import java.util.date;
import java.util.list;
/**
* @classname: order
* @description: todo
* @date: 2023/4/10 11:21
* @author: ph9527
* @version: 1.0
*/
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;
/**
* @classname: orderdetail
* @description: todo
* @date: 2023/4/10 11:25
* @author: ph9527
* @version: 1.0
*/
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));
}
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论