根据项目的需求,需要将别的语言的中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