java使用dom4j实现xml文件的解析

java使用dom4j实现xml文件和对象之间的相互转换

  • 整体描述
  • 两种方式的对比
  • 具体实现
    • 1. 引入dom4j的maven
    • 2.xml文件
    • 3. 创建节点名称的类
    • 4. 创建xml文件读写操作类
    • 5. 解析操作
  • 结语

整体描述

之前写过一篇文章,使用xstream将xml文件转成对象,文章链接:java使用xstream实现xml文件和对象之间的相互转换,使用起来很简单,但是有个问题,就是这种方法只能处理已知的xml中的字段,然后提前将对象创建处理,如果xml中有一些我们不能提前获知的字段,使用这种方法转成对象之后,在反转回xml,那些在对象中没有创建的字段就会丢失。
这里我们使用dom4j的方法,直接操作xml文件,就能避免这种问题。但是两种方法各有优劣,使用的时候可以根据情况进行选择。

两种方式的对比

在这对上面两种解析xml的方式做一个简单对比:

解析方式 xstream dom4j
优点 解析操作简单,代码复用性强 ,存入数据库操作方便 可以直接操作xml文件,不回造成字段丢失
缺点 对xml中未知字段无法处理 解析操作相对复杂,代码复用性低,同时操作文件问题

具体实现

1. 引入dom4j的maven

添加xstream的依赖

        
        
            org.dom4j
            dom4j
            2.1.3
        

2.xml文件

这里还是使用的是大疆无人机的地图文件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
          
        
      
    
  
 


3. 创建节点名称的类

/**
 * 航线文件常量
 *
 * @author nhx
 * @date 2022-08-22
 */
public interface WaylineConstant {

    /**
     * Document
     */
    String Document = "Document";

    /**
     * Folder
     */
    String Folder = "Folder";

    /**
     * Placemark
     */
    String Placemark = "Placemark";

    /**
     * actionGroup
     */
    String actionGroup = "actionGroup";

    /**
     * index
     */
    String index = "index";

    /**
     * action
     */
    String action = "action";

    /**
     * actionActuatorFunc
     */
    String actionActuatorFunc = "actionActuatorFunc";

    /**
     * actionActuatorFuncParam
     */
    String actionActuatorFuncParam = "actionActuatorFuncParam";

    /**
     * takePhoto
     */
    String takePhoto = "takePhoto";

    /**
     * wpml:fileSuffix
     */
    String addFileSuffix = "wpml:fileSuffix";

    /**
     * fileSuffix
     */
    String fileSuffix = "fileSuffix";

    /**
     * fileSuffix
     */
    String actionGroupStartIndex = "actionGroupStartIndex";

    /**
     * fileSuffix
     */
    String actionGroupEndIndex = "actionGroupEndIndex";

}

4. 创建xml文件读写操作类

此处对读写xml文件单独封装一个方法,在其中对xml文件修改保存时进行了一些格式设置,具体详见代码。

    /**
     * 将Document对象写入到xml文件
     *
     * @param document    写入的Document
     * @param fileNameDec 写入文件路径
     * @param append      是否追加写入,true表示不覆盖原来的内容,而是加到文件的后面
     */
    public static void documentToFile(Document document, String fileNameDec, boolean append) {
        try {
            OutputFormat outputFormat = OutputFormat.createPrettyPrint();
            // 设置XML编码方式,即是用指定的编码方式保存XML文档到字符串(String),这里也可以指定为GBK或是ISO8859-1
            outputFormat.setEncoding("UTF-8");
            //outputFormat.setSuppressDeclaration(true); //是否生产xml头
            // 设置是否缩进
            outputFormat.setIndent(true);
            // 以两个空格方式实现缩进
            outputFormat.setIndent("  ");
            // 设置是否换行
            outputFormat.setNewlines(true);
            // xml字符串
            StringWriter stringWriter = new StringWriter();
            // xmlWriter是用来把XML文档写入字符串
            XMLWriter xmlWriter = new XMLWriter(stringWriter, outputFormat);
            // 把创建好的XML文档写入字符串
            xmlWriter.write(document);
            //写入文件
            writerFile(stringWriter.toString(), fileNameDec, append);
        } catch (Exception e) {
            log.error("documentToFile:{}", e.toString());
            e.printStackTrace();
        }
    }


    /**
     * 将字符串写入指定路径的文件中
     *
     * @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) {
            log.error("writerFile:{}", e.toString());
            e.printStackTrace();
        }
    }

5. 解析操作

使用dom4j这种方式,就需要用代码进行逐层读取,这就是代码复用性差的原因,因为一旦xml结构变了,解析的代码需要重新写。

/**
     * xml解析测试方法
     *
     * @param filePath 文件路径
     */
    public static void testXml(String filePath) {
        try {
            SAXReader reader = new SAXReader();
            Document document = reader.read(filePath);
            if (Objects.isNull(document)) {
                return;
            }
            Element root = document.getRootElement();
            if (Objects.isNull(root)) {
                return;
            }
            Element doc = root.element(WaylineConstant.Document);
            if (Objects.isNull(doc)) {
                return;
            }
            Element folder = doc.element(WaylineConstant.Folder);
            if (Objects.isNull(folder)) {
                return;
            }
            List elementList = folder.elements(WaylineConstant.Placemark);
            if (Objects.isNull(elementList) || elementList.size() <= 0) {
                return;
            }
            for (Element placemark : elementList) {
                // 循环航点
                Element actionGroup = placemark.element(WaylineConstant.actionGroup);
                if (Objects.isNull(actionGroup)) {
                    continue;
                }
                String index = placemark.element(WaylineConstant.index).getText();
                List actionList = actionGroup.elements(WaylineConstant.action);
                if (Objects.isNull(actionList) || actionList.size() <= 0) {
                    continue;
                }
                for (Element action : actionList) {
                    // 循环航点动作
                }
            }
            // 写入文件
            FileUtils.documentToFile(document, filePath, false);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

结语

至此,解析和修改参数的工作就完成了,还需要注意的,由于直接对xml文件进行操作,如果有同时操作同一个航线文件的情况,会有问题,需要加一个线程锁或者文件锁之类的判断。

你可能感兴趣的:(java,后端,java,xml,开发语言)