groovy XmlParser 递归遍历 xml 文件,修改并保存

发布时间:2024年01月10日

在这里插入图片描述
使用 groovy.util.XmlParser 解析 xml 文件,对文件进行修改(新增标签),然后保存。

是不是 XmlParser 没有提供方法遍历每个节点,难道要自己写?

什么是递归?

不用说,想必都懂得~

import ***.XmlNodeCallback;
import ***.PluginLog;

import org.xml.sax.SAXException;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import groovy.util.Node;
import groovy.util.XmlParser;
import groovy.xml.XmlUtil;

/**
 * 创建者:村长
 * 时间:2024/1/10 10:20
 */
public class PluginXmlUtil {
	 /**
     * 
     * @param xmlFile   需要解析的 xml 文件
     * @param callback  回调每一个标签 node,可以对 node 进行 CURD
     * @return
     */
    public static Node parseXml(File xmlFile, XmlNodeCallback callback) {
        if (CommUtils.isEmptyOrNoExists(xmlFile)) {
            return null;
        }

        try {
            Node rootNode = new XmlParser().parse(xmlFile);
            traverseNode(rootNode, callback);
            return rootNode;
        } catch (IOException e) {
        } catch (SAXException e) {
        } catch (ParserConfigurationException e) {
        }

        return null;
    }

    /**
     * 
     * @param node          需要保存的往往是根节点 node(当然保存你想要的任意节点也是可以)
     * @param targetFile    保存文件
     * @return
     */
    public static boolean saveNodeToFile(Node node, File targetFile) {
        if (node == null || targetFile == null) {
            return false;
        }

        try {
        	// 使用 groovy 提供的 xml 序列化工具获得原始字符串
            String finalContent = XmlUtil.serialize(node);
            if (CommUtils.isEmptyOrNoExists(finalContent)) {
                return false;
            }
            // 使用 TRUNCATE_EXISTING,如果文件存在,那么截取长度为0(也就是覆盖文件内容),然后写入新内容
            Files.write(targetFile.toPath(), finalContent.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
            return true;
        } catch (IOException e) {
        }
        return false;
    }


    /**
     * 递归会写吧~
     * 
     * @param rootNode      根节点
     * @param callback      把每个 node 回调返回给外部,在回调中可操作 node 等
     */
    private static void traverseNode(Node node, XmlNodeCallback callback) {
        if (node == null) {
            return;
        }

        if (callback != null) {
            callback.onNode(node);
        }

        List<Object> children = node.children();
        boolean hasChildren = children != null && !children.isEmpty();
        if (hasChildren) {
            for (Object child : children) {
            	// 仅遍历 node 类型,因为 children 可存在 String 等,调用递归就不合适了
            	// 比如存在 <name>lf</name>,其中值 lf 也是作为 children 的一个元素,
            	// 目前不对他进行递归(如果需要回调给外部,也可以在 XmlNodeCallback 新增一个接口,通过 callback 回调数据) 
                if (child instanceof Node) {
                    traverseNode((Node) child, callback);
                } else {
                    PluginLog.d("traverseNode: " + child.getClass() + "  val:" + child);
                }
            }
        }
    }
}

使用接口,回调每一个递归遍历到的 node,在回调中处理逻辑

/**
 * 创建者:村长
 * 时间:2024/1/10 10:38
 */
public interface XmlNodeCallback {
    void onNode(Node node);
}

直接使用

  File xmlFile = new File(****)
  def rootNode = PluginXmlUtil.parseXml(xmlFile, new XmlNodeCallback() {
     @Override
     void onNode(Node node) {
         if (node == null) {
             return
         }

         String nodeName = node.name()
         String[] nodeAttr = node.attributes()
         if (CommUtils.isEmptyOrNoExists(nodeName)) {
             return
         }
         PluginLog.d("nodeName:" + nodeName + "  nodeAttr:  " + nodeAttr + " value: " + node.value)
		
		// TODO: 2024/1/10  处理你的逻辑

     }
 })

  // 比如,我要在跟节点下面添加一个标签
 rootNode.append(ArgUtil.genDefaultBaseConfigNode())
 //然后保存修改
 def saveSuccess = PluginXmlUtil.saveNodeToFile(rootNode, xmlFile)

默认配置

package ***.utils;

import org.xml.sax.SAXException;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;

import groovy.util.Node;
import groovy.util.XmlParser;

/**
 * 创建者:村长
 * 时间:2024/1/10 11:08
 */
public class ArgUtil {
    public static Node genDefaultBaseConfigNode() throws ParserConfigurationException, SAXException, IOException {
        return new XmlParser().parseText("<base-config cleartextTrafficPermitted=\"true\">\n" +
                "        <trust-anchors>\n" +
                "            <certificates src=\"user\" />\n" +
                "            <certificates src=\"system\" />\n" +
                "        </trust-anchors>\n" +
                "    </base-config>");
    }

    public static Node genDefaultTrustAnchorsNode() throws ParserConfigurationException, SAXException, IOException {
        return new XmlParser().parseText("<trust-anchors>\n" +
                "            <certificates src=\"user\" />\n" +
                "            <certificates src=\"system\" />\n" +
                "        </trust-anchors>");
    }

    public static Node genDefaultCertificatesNode(String value) throws ParserConfigurationException, SAXException, IOException {
        return new XmlParser().parseText("<certificates src=" + value + " />");
    }
}

学会了新增,删除、修改都不是问题吧~

文章来源:https://blog.csdn.net/printf123scanf/article/details/135501166
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。