xml是一个用途比较广泛的文件类型,在java里也自带解析xml的包,但是本文使用的是xstream来实现xml和对象之间的相互转换,xstream是一个第三方开源框架,使用起来比较方便,xstream官网地址: xstream官网,目前最新版本是1.4.19。
添加xstream的依赖,这里使用最新的1.4.19版本
com.thoughtworks.xstream
xstream
1.4.19
这里使用的是大疆无人机的地图文件template.kml :
xml文件参考文档:大疆云上API地址: 大疆云上API。
文件具体格式如下,基本包含了xml所有需要使用的示例。
注:文件虽然是.kml格式,但其实就是xml的格式。
Name
1637600807044
1637600875837
safely
goHome
goContinue
20
10
67
0
52
0
0
waypoint
0
0
WGS84
EGM96
100
100
GPS
7
7
usePointSetting
followWayline
toPointAndStopWithDiscontinuityCurvature
longitude,latitude
0
90.2
100
1
1
1
1
0
longitude,latitude
1
90.2
100
1
1
1
1
0
0
1
1
sequence
reachPoint
0
gimbalRotate
absoluteAngle
0
0
0
0
1
30
0
0
0
1
takePhoto
point1
0
根据xml文件的格式,创建出各个节点的对象,使用xstream的注解实现设置标签的功能,这里主要使用以下几个注解:
@XStreamAlias(“kml”):设置标签,内容为对象;
@XStreamImplicit(itemFieldName = “Placemark”):设置标签,内容为list
@XStreamAsAttribute:标签内属性
具体对象类:
最外层的Kml对象:
package com.thcb.xml.bean.template;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import lombok.Data;
/**
* Kml
*
* @author nhx
* @date 2022-07-29
*/
@Data
@XStreamAlias("kml")
public class Kml {
@XStreamAlias("xmlns")
@XStreamAsAttribute
private String xmlns;
@XStreamAlias("xmlns:wpml")
@XStreamAsAttribute
private String wpml;
@XStreamAlias("Document")
private Document document;
}
Document对象:
package com.thcb.xml.bean.template;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
/**
* Document
*
* @author nhx
* @date 2022-07-29
*/
@Data
@XStreamAlias("Document")
public class Document {
/**
* 文件创建作者
*/
@XStreamAlias("wpml:author")
private String author;
/**
* 文件创建时间(Unix Timestamp)
*/
@XStreamAlias("wpml:createTime")
private Long createTime;
/**
* 文件更新时间(Unix Timestamp)
*/
@XStreamAlias("wpml:updateTime")
private Long updateTime;
/**
* 任务信息
*/
@XStreamAlias("wpml:missionConfig")
private MissionConfig missionConfig;
/**
* 模板信息
*/
@XStreamAlias("Folder")
private Folder folder;
}
MissionConfig对象:
package com.thcb.xml.bean.template;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
/**
* MissionConfig
*
* @author nhx
* @date 2022-07-29
*/
@Data
@XStreamAlias("wpml:missionConfig")
public class MissionConfig {
/**
* 飞向首航点模式
*/
@XStreamAlias("wpml:flyToWaylineMode")
private String flyToWaylineMode;
/**
* 航线结束动作
*/
@XStreamAlias("wpml:finishAction")
private String finishAction;
/**
* 失控是否继续执行航线
*/
@XStreamAlias("wpml:exitOnRCLost")
private String exitOnRCLost;
/**
* 失控动作类型
*/
@XStreamAlias("wpml:executeRCLostAction")
private String executeRCLostAction;
/**
* 安全起飞高度
*/
@XStreamAlias("wpml:takeOffSecurityHeight")
private String takeOffSecurityHeight;
/**
* 全局航线过渡速度
*/
@XStreamAlias("wpml:globalTransitionalSpeed")
private String globalTransitionalSpeed;
/**
* 参考起飞点
*/
@XStreamAlias("wpml:takeOffRefPoint")
private String takeOffRefPoint;
/**
* 参考起飞点海拔高度
*/
@XStreamAlias("wpml:takeOffRefPointAGLHeight")
private String takeOffRefPointAGLHeight;
@XStreamAlias("wpml:globalRTHHeight")
private String globalRTHHeight;
/**
* 飞行器机型信息
*/
@XStreamAlias("wpml:droneInfo")
private DroneInfo droneInfo;
/**
* 负载机型信息
*/
@XStreamAlias("wpml:payloadInfo")
private PayloadInfo payloadInfo;
}
Folder对象:
package com.thcb.xml.bean.template;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import lombok.Data;
import java.util.List;
/**
* Folder
*
* @author nhx
* @date 2022-07-29
*/
@Data
@XStreamAlias("Folder")
public class Folder {
// 模板共用元素
/**
* 预定义模板类型
*/
@XStreamAlias("wpml:templateType")
private String templateType;
@XStreamAlias("wpml:useGlobalTransitionalSpeed")
private String useGlobalTransitionalSpeed;
/**
* 模板ID
*/
@XStreamAlias("wpml:templateId")
private String templateId;
/**
* 全局航线飞行速度
*/
@XStreamAlias("wpml:autoFlightSpeed")
private String autoFlightSpeed;
@XStreamAlias("wpml:transitionalSpeed")
private String transitionalSpeed;
/**
* 坐标系参数
*/
@XStreamAlias("wpml:waylineCoordinateSysParam")
private WaylineCoordinateSysParam waylineCoordinateSysParam;
/**
* 负载设置
*/
@XStreamAlias("wpml:payloadParam")
private PayloadParam payloadParam;
// 航点飞行模板元素
/**
* 全局航点类型(全局航点转弯模式)
*/
@XStreamAlias("wpml:globalWaypointTurnMode")
private String globalWaypointTurnMode;
/**
* 全局航段轨迹是否尽量贴合直线
*/
@XStreamAlias("wpml:globalUseStraightLine")
private String globalUseStraightLine;
/**
* 云台俯仰角控制模式
*/
@XStreamAlias("wpml:gimbalPitchMode")
private String gimbalPitchMode;
/**
* 全局航线高度(椭球高)
*/
@XStreamAlias("wpml:ellipsoidHeight")
private String ellipsoidHeight;
/**
* 全局航线高度(EGM96海拔高/相对起飞点高度/AGL相对地面高度)
*/
@XStreamAlias("wpml:height")
private String height;
/**
* 全局偏航角模式参数
*/
@XStreamAlias("wpml:globalWaypointHeadingParam")
private GlobalWaypointHeadingParam globalWaypointHeadingParam;
/**
* 航点信息(包括航点经纬度和高度等)
*/
@XStreamImplicit(itemFieldName = "Placemark")
private List placemarkList;
// 建图航拍模板元素
/**
* 是否开启标定飞行
* 注:仅适用于M300RTK与L1机型
*/
@XStreamAlias("wpml:caliFlightEnable")
private String caliFlightEnable;
/**
* 是否开启高程优化
*/
@XStreamAlias("wpml:elevationOpimizeEnable")
private String elevationOpimizeEnable;
/**
* 是否开启智能摆拍
* 注:仅适用于M300RTK与P1机型
*/
@XStreamAlias("wpml:elevationOpimizeEnable")
private String smartObliqueEnable;
/**
* 智能摆拍拍摄俯仰角
* 注:仅适用于M300RTK与P1机型。P1机型云台建议输入范围[-90, -45]
*/
@XStreamAlias("wpml:smartObliqueGimbalPitch")
private String smartObliqueGimbalPitch;
/**
* 拍照模式(定时或定距)
*/
@XStreamAlias("wpml:shootType")
private String shootType;
/**
* 航线方向
*/
@XStreamAlias("wpml:direction")
private String direction;
/**
* 测区外扩距离
*/
@XStreamAlias("wpml:margin")
private String margin;
/**
* 重叠率参数
*/
@XStreamAlias("wpml:overlap")
private String overlap;
/**
* 全局航线高度(椭球高):ellipsoidHeight
* 全局航线高度(EGM96海拔高/相对起飞点高度/AGL相对地面高度):height
*/
/**
* 测区多边形
*/
@XStreamAlias("Polygon")
private Polygon polygon;
// 倾斜摄影模板元素
/**
* 云台俯仰角度(倾斜)
*/
@XStreamAlias("wpml:inclinedGimbalPitch")
private String inclinedGimbalPitch;
/**
* 航线飞行速度(倾斜)
*/
@XStreamAlias("wpml:inclinedFlightSpeed")
private String inclinedFlightSpeed;
// 航带飞行模板元素
/**
* 是否开启单航线飞行
*/
@XStreamAlias("wpml:singleLineEnable")
private String singleLineEnable;
/**
* 每个子航带航线长度
*/
@XStreamAlias("wpml:cuttingDistance")
private String cuttingDistance;
/**
* 是否开启边缘优化
*/
@XStreamAlias("wpml:boundaryOptimEnable")
private String boundaryOptimEnable;
/**
* 航带左侧外扩距离
*/
@XStreamAlias("wpml:leftExtend")
private String leftExtend;
/**
* 航带右侧外扩距离
*/
@XStreamAlias("wpml:rightExtend")
private String rightExtend;
/**
* 是否包含中心线
*/
@XStreamAlias("wpml:includeCenterEnable")
private String includeCenterEnable;
/**
* 航点信息
*/
@XStreamAlias("LineString")
private LineString lineString;
/**
* 其他,参数无具体说明
*/
@XStreamAlias("wpml:globalHeight")
private String globalHeight;
}
这里就不把所有对象的代码都贴出来了,以上几个已经足够了,剩下的可以举一反三,自己创建出来。注意:如果想要解析xml,必须要把xml中的所有结构和标签都创建出来才可以,否则会报错。
创建xml工具类,主要就是将xstream进行一个简单的封装
package com.thcb.xml.util;
import com.thcb.xml.bean.template.Kml;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
/**
* FileUtils
*
* @author nhx
* @date 2022-08-01
*/
public class XmlUtils {
/**
* xstream初始化
*/
private static final XStream XSTREAM = new XStream(new DomDriver());
/**
* 添加合法的包名,否则无法解析xml,使用时需要改成自己工程的包名
*/
private static final String PACKET = "com.thcb.**";
/**
* 将xml字符串转为Kml对象
*
* @param xmlString xml字符串
*/
public static Kml xmlToKml(String xmlString) {
XSTREAM.allowTypesByWildcard(new String[]{PACKET});
XSTREAM.processAnnotations(Kml.class);
return (Kml) XSTREAM.fromXML(xmlString);
}
/**
* 将Kml对象转为xml字符串
*
* @param kml Kml对象
*/
public static String kmlToXml(Kml kml) {
// 设置包名
XSTREAM.allowTypesByWildcard(new String[]{PACKET});
// 设置kml中的xmlns标签
kml.setXmlns("http://www.opengis.net/kml/2.2");
// 设置kml中的wpml标签
kml.setWpml("http://www.dji.com/wpmz/1.0.0");
// 转换的字符串前面加上xml说明
return "\n" + XSTREAM.toXML(kml);
}
}
由于需要读取和写入文件,这里就创建一个读写文件的工具类,便于操作。
package com.thcb.xml.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
/**
* FileUtils
*
* @author nhx
* @date 2022-08-01
*/
public class FileUtils {
/**
* 将字符串写入指定路径的文件中
*
* @param encryptText 写入字符串
* @param fileNameDec 写入文件路径
* @param append 是否追加写入,true表示不覆盖原来的内容,而是加到文件的后面
*/
public static void writerFile(String encryptText, String fileNameDec, boolean append) {
FileWriter writer = null;
try {
writer = new FileWriter(fileNameDec, append);
writer.write(encryptText);
writer.flush();
writer.close();
} catch (IOException e) {
System.out.println("写入文件发生了异常");
e.printStackTrace();
}
}
/**
* 从指定路径的文件中读取字符串
*
* @param fileNameDec 读取文件路径
*/
public static String readFile(String fileNameDec) {
File file = new File(fileNameDec);
long fileLengthLong = file.length();
byte[] fileContent = new byte[(int) fileLengthLong];
try {
FileInputStream inputStream = new FileInputStream(file);
inputStream.read(fileContent);
inputStream.close();
} catch (Exception e) {
// TODO: handle exception
}
return new String(fileContent);
}
}
好了,上面把需要的都创建完了,这里就可以进行转换了,xstream使用起来非常方便,转换过程只需一步:
package com.thcb.test;
import com.thcb.xml.util.FileUtils;
import com.thcb.xml.util.XmlUtils;
import com.thcb.xml.util.ZipUtils;
import com.thcb.xml.bean.template.Kml;
/**
* XmlTest
*
* @author nhx
* @date 2022-07-28
*/
public class XmlTest {
public static void main(String[] args) {
// 读取文件流
String string = FileUtils.readFile("文件路径");
try {
// xml字符串转换成对象
Kml kml = XmlUtils.xmlToKml(string);
// log其中的一个属性值
String coordinates = kml.getDocument().getFolder().getPlacemarkList().get(0).getPoint().getCoordinates().trim();
System.out.println("coordinates:" + coordinates);
// 修改其中几个属性值
kml.getDocument().setUpdateTime(System.currentTimeMillis());
kml.getDocument().setAuthor("nhx");
// 对象转换成xml字符串
String xml = XmlUtils.kmlToXml(kml);
// log转换完的xml
System.out.println("xml:\n" + xml);
// 写入文件
FileUtils.writerFile(xml, "文件路径", false);
} catch (Exception e) {
System.out.println(e.toString());
}
System.out.println("over");
}
}
至此,xml和对象的互相转换工作就完成了,还是比较简单的,有兴趣的可以看一下xstream的官网,在本文开头就贴出来官网地址了,上面有一些其他用法的介绍。
注:旧版本的xstream有安全漏洞,建议使用最新版本。