利用dom4j和反射解析XML数据为自定义对象或者Map结合

根据项目的需求,需要将别的语言的中XML配置文件解析入到数据库,自己研究了两天,两种常用结果,一种用递归把整个节点解析为一个Map对象,一种是利用反射解析为指定的自定义对象。

需要的jar包

<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>

第一种:节点解析为Map对象
先看看我的config.xml文件,文件太大,只复制一部分

<?xml version="1.0" encoding="utf-8"?>
<config>
	<global>
		<ChannelNum>4</ChannelNum>  //通道数量,取值范围1-8,缺省为1
		<ChannelIDs>1,2,3,4</ChannelIDs> //通道ID集合,在原型相机中仅需要考虑单通道场景,缺省为1
		<DeviceID> AI001 </DeviceID>  //盒子设备ID,缺省为空
		<ResizeWidth> 1280 </ResizeWidth>    //图像resize的宽
		<ResizeHeight> 720 </ResizeHeight>   //图像resize的高
		<bWriteLogFile> 1 </bWriteLogFile>  //是否写入日志:0-不写入;1-写入
		<LogFilePath> ./data/log </LogFilePath>  //日志文件存储的目录,缺省为空
		<MaxLogFileSize> 512 </MaxLogFileSize>   //单个日志文件最大尺寸(单位为KB)
		<MaxLogFilesSpace> 200000 </MaxLogFilesSpace>   //日志文件最大存储空间(单位为KB)
		<AlarmPicFilePath> ./data/alarmpic </AlarmPicFilePath>  //告警抓拍图存储的目录,缺省为空
		<MaxAlarmPicFilesSpace> 800000 </MaxAlarmPicFilesSpace>   //告警抓拍图最大存储空间(单位为KB)
		<EnableRtspServer> 0 </EnableRtspServer>  //是否使能RTSP SERVER:0-不使能;1-使能
		<RtspServerPort> 88 </RtspServerPort>  //RTSP SERVER的端口
		<EnableProxyServer> 0 </EnableProxyServer> //是否使能代理SERVER:0-不使能;1-使能
		<ProxyServerAddr> 192.168.2.107 </ProxyServerAddr>  //代理SERVER IP地址,仅支持IPV4地址,缺省为空
		<ProxyServerPort> 6061 </ProxyServerPort>  //代理SERVER的端口,缺省为6061			
		<EnableSyncTime2IPC> 0 </EnableSyncTime2IPC>  //是否使能同步时间到相机:0-不使能;1-使能
		<EnableSyncTimeFromAPI> 0 </EnableSyncTimeFromAPI>  //是否使能从API接口同步时间到盒子设备:0-不使能;1-使能	
		<TTUServerPort>6061</TTUServerPort><VersionID>47</VersionID> //配置文件版本号ID
		<LinkProxyClientNum/>//TTU注册代理数量
		<UAVWorkPath>/home/catkin_ws</UAVWorkPath>//无人机自动化巡检程序的工作目录 
		<ModbusChannelNum> 0 </ModbusChannelNum>  //MODBUS通道数量
		<ModbusChannelIDs> DIN只读开关量,DO可写开关量,AIN只读模拟量 </ModbusChannelIDs>  //MODBUS通道SLAVE ID列表
		<ModbusAutoNum> 0 </ModbusAutoNum>  //MODBUS自动化数量
		<ModbusAutoIDs> 自动化提升井,自动化调节池,自动化风机,自动化抽吸泵,自动化异常监测 </ModbusAutoIDs>  //MODBUS自动化ID列表
	</global>
</config>

第一步:读到文件以后创建Document


    /**
     * 创建 Document
     *
     * @param filePath
     * @return
     * @throws IOException
     * @throws DocumentException
     */
    private static Document createDocument(String filePath) throws IOException, DocumentException {
        InputStream in = new FileInputStream(filePath);
        String xml = IOUtils.toString(in);
        SAXReader saxReader = new SAXReader();
        return saxReader.read(new ByteArrayInputStream(xml.getBytes()));
    }

第二步:用递归解析xml数据

    /**
     * 将一个节点下的所有数据转换为一个Map集合
     *
     * @param element
     * @return
     */
    private static Map<String, Object> eleToMap(Element element) {
        Map<String, Object> map = new HashMap<>();
        List<Element> elements = (List<Element>) element.elements();
        if (elements.size() > 0) {
            Map<String, Object> childMap = new HashMap<>();
            for (Element ele : elements) {
                Map<String, Object> eleToMap = eleToMap(ele);
                childMap.putAll(eleToMap);
            }
            map.put(element.getName(), childMap);
        } else {
            map.put(element.getName(), getEleVal(element));
        }
        return map;
    }

第三步:测试数据是否读取的到


public static void main(String[] args) throws IOException, DocumentException, IllegalAccessException, ClassNotFoundException, InstantiationException {

		//xml文件地址
        String filePath = "C:\\Users\\Administrator\\Desktop\\config.xml";
        //读取文件创建Document
        Document document = XmlUtils.createDocument(filePath);
        //根节点
        Element rootElement = document.getRootElement();
        //将整个节点转换为map对象
        Map<String, Object> map = eleToMap(rootElement);
		
		//测试数据是否读到
        Map config = (Map) map.get("config");
        Map global = (Map) config.get("global");
        String versionId = (String) global.get("VersionID");
        System.out.println(versionId);
}

第五步:读取成功
在这里插入图片描述
在这里插入图片描述

第二种:利用反射将节点解析为指定的自定义对象
第一步:自定义对象,对象里的属性名称要和xml里的标签名称对应

@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class Global {

    @ApiModelProperty(name = "ChannelNum", value = "通道数量,取值范围1-8,缺省为1")
    private Integer ChannelNum;

    @ApiModelProperty(name = "ChannelIDs", value = "通道ID集合,在原型相机中仅需要考虑单通道场景,缺省为1")
    private String ChannelIDs;

    @ApiModelProperty(name = "DeviceID", value = "盒子设备ID,缺省为空")
    private String DeviceID;

    @ApiModelProperty(name = "ModbusChannelNum", value = "MODBUS通道数量")
    private Integer ModbusChannelNum;

    @ApiModelProperty(name = "ModbusChannelIDs", value = "MODBUS通道SLAVE ID列表")
    private String ModbusChannelIDs;

    @ApiModelProperty(name = "ModbusAutoNum", value = "MODBUS自动化数量")
    private Integer ModbusAutoNum;

    @ApiModelProperty(name = "ModbusAutoIDs", value = "MODBUS自动化ID列表")
    private String ModbusAutoIDs;

    @ApiModelProperty(name = "VersionID", value = "版本号")
    private Integer VersionID;
}

第二步:将节点解析为指定对象

    /**
     * 将节点转换为指定类型的对象
     *
     * @param element
     * @param clazz
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws ClassNotFoundException
     */
    private static <T> T eleToObj(Element element, Class<T> clazz) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Class c = Class.forName(clazz.getName());
        Object newInstance = c.newInstance();
        //读取到所有属性
        Field[] fields = clazz.getDeclaredFields();
        //遍历每一个属性并且从节点中找到对应属性赋值
        for (Field field : fields) {
            String eleVal = XmlUtils.getEleVal(element, field.getName());
            field.setAccessible(true);
            if (StringUtils.isNotEmpty(eleVal)) {
                //判断属性类型进行属性转换,可以不进行判断直接都转为String,这里只判断了两个,如果有需要可以根据自己的需求增减
                if (field.getType() == Integer.class) {
                    field.set(newInstance, Integer.parseInt(eleVal));
                }
                if (field.getType() == String.class) {
                    field.set(newInstance, eleVal);
                }
            }
        }
        return (T) newInstance;
    }

第二步:测试

public static void main(String[] args) throws IOException, DocumentException, IllegalAccessException, ClassNotFoundException, InstantiationException {

		//xml文件地址
        String filePath = "C:\\Users\\Administrator\\Desktop\\config.xml";
        //读取文件创建Document
        Document document = XmlUtils.createDocument(filePath);
        //根节点
        Element rootElement = document.getRootElement();
        //将整个节点转换为自定义对象
 		Element globalEle = XmlUtils.getEleByName(rootElement, "global");
        Global global = XmlUtils.eleToObj(globalEle, Global.class);
	
        System.out.println(global);
}

结果:
在这里插入图片描述
在这里插入图片描述

最后分享一下文件地址,我用的阿里云盘,https://www.aliyundrive.com/s/GWpyrXJ9a3z

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老鼠抗刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值