前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Groovy】自定义 Xml 生成器 BuilderSupport ( 创建 XmlNode 节点 | 管理 XmlNode 节点并将根节点转为 Xml 信息 | 完整代码示例 )

【Groovy】自定义 Xml 生成器 BuilderSupport ( 创建 XmlNode 节点 | 管理 XmlNode 节点并将根节点转为 Xml 信息 | 完整代码示例 )

作者头像
韩曙亮
发布2023-03-30 11:15:42
6750
发布2023-03-30 11:15:42
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、创建 XmlNode 节点


class MyBuilderSupport extends BuilderSupport 类中维护一个 Map 集合 , 该 Map 集合用于存储 上一篇博客 【Groovy】自定义 Xml 生成器 BuilderSupport ( 构造 Xml 节点类 | 封装节点名称、节点值、节点属性、子节点 | 将封装的节点数据转为 Xml 字符串 ) 中封装的 XmlNode 节点 ;

该 Map 集合的 Key 是节点名称 , Value 是 XmlNode 节点的值 ;

代码语言:javascript
复制
    /**
     * Map 集合
     * Key 为 节点的 name 名称
     * Value 为 节点 XmlNode 对象
     */
    def xmlNodes = [:]

createNode 方法 , 是创建节点的方法 , 此处可以创建 XmlNode 节点 , 并放入 Map 集合中 ;

代码语言:javascript
复制
    @Override
    protected Object createNode(Object name, Map attributes, Object value) {
        println "创建节点 名称 : $name, 属性 : $attributes, 值 : $value"
        xmlNodes.put(name, new XmlNode(name, value, attributes))
        return name;
    }

二、管理 XmlNode 节点并将根节点转为 Xml 信息


BuilderSupport#nodeCompleted 方法是节点关闭的回调方法 ;

方法原型如下 :

代码语言:javascript
复制
    @Override
    protected void nodeCompleted(Object parent, Object node) {
        super.nodeCompleted(parent, node)
	}

其中 Object node 是被关闭的节点 , Object parent 是被关闭节点的父节点 ;

节点关闭时 , 可以根据 Object node 参数获取该被关闭的节点

代码语言:javascript
复制
def currentXmlNode = xmlNodes[node]

如果该被关闭的节点有父节点 , 即 Object parent 参数不为空 , 则将该节点放入父节点 XmlNode 的 children 子节点集合中 ;

代码语言:javascript
复制
        if (parent) {
            // 该节点有父节点, 将该节点放入父节点的 children 集合中
            xmlNodes[parent].children << currentXmlNode
        } 

如果该被关闭的节点没有父节点 , 说明该节点就是根节点 , 根节点关闭 意味着 Xml 数据生成完毕 , 此时可以将该根节点输出 ;

代码语言:javascript
复制
            // 如果该节点没有父节点, 说明该节点就是根节点, 则开始构建 Xml 文件
            currentXmlNode.build(writer)

三、完整代码示例


1、自定义 Xml 生成器 MyBuilderSupport

代码语言:javascript
复制
import groovy.util.BuilderSupport;

import java.util.Map;

public class MyBuilderSupport extends BuilderSupport {

    /**
     * Map 集合
     * Key 为 节点的 name 名称
     * Value 为 节点 XmlNode 对象
     */
    def xmlNodes = [:]

    /**
     * 写用于出 Xml 数据
     */
    Writer writer

    MyBuilderSupport(Writer writer) {
        this.writer = writer
    }

    /**
     * 设置节点之间的关系
     * @param parent Xml 中的父节点
     * @param child Xml 中的父节点下的子节点
     */
    @Override
    protected void setParent(Object parent, Object child) {
        println "setParent 设置子节点 ${child} 的父节点是 ${parent}"
    }

    @Override
    protected Object createNode(Object name) {
        /*
            所有的 createNode 方法都回调到 3 个参数的 createNode 方法
         */
        return createNode(name, null, null);
    }

    @Override
    protected Object createNode(Object name, Object value) {
        /*
            所有的 createNode 方法都回调到 3 个参数的 createNode 方法
         */
        return createNode(name, null, value);
    }

    @Override
    protected Object createNode(Object name, Map attributes) {
        /*
            所有的 createNode 方法都回调到 3 个参数的 createNode 方法
         */
        return createNode(name, attributes, null);
    }

    @Override
    protected Object createNode(Object name, Map attributes, Object value) {
        println "创建节点 名称 : $name, 属性 : $attributes, 值 : $value"
        xmlNodes.put(name, new XmlNode(name, value, attributes))
        return name;
    }

    /**
     * 闭合节点时, 回调该方法
     * @param parent
     * @param node
     */
    @Override
    protected void nodeCompleted(Object parent, Object node) {
        super.nodeCompleted(parent, node)
        println "nodeCompleted 完成了父节点为 parent : $parent  的节点 node : $node 的闭合操作"

        def currentXmlNode = xmlNodes[node]
        if (parent) {
            // 该节点有父节点, 将该节点放入父节点的 children 集合中
            xmlNodes[parent].children << currentXmlNode
        } else {
            // 如果该节点没有父节点, 说明该节点就是根节点, 则开始构建 Xml 文件
            currentXmlNode.build(writer)
        }
    }
}

2、Xml 节点封装了 XmlNode

代码语言:javascript
复制
class XmlNode {
    /**
     * 节点名称
     */
    String name

    /**
     * 节点值
     */
    String value

    /**
     * 节点属性
     */
    Map attributes

    /**
     * 子节点 ArrayList 类型
     */
    def children = []


    XmlNode(String name, String value, Map attributes) {
        this.name = name
        this.value = value
        this.attributes = attributes
    }


/*
<student>
    <name code="utf-8">Tom</name>
    <age>18</age>
</student>
*/

    /**
     * 写出该 XmlNode 节点数据
     * @param writer
     */
    def build(Writer writer) {
        /*
            写出 name 节点名称
            注意 : 此处有 2 种情况
            ① 带属性的节点 <name code="utf-8">Tom</name>
            ② 不带属性的节点 <age/>
            先写出 "<name"
         */
        writer.write("<${name}")

        /*
            假如该节点有节点属性信息
            循环写出节点属性
         */
        if (attributes != null) {
            attributes.each {
                writer.write(" ${it.key}='${it.value}'")
            }
        }

        /*
            可能有如下情况
            节点有值, 没有子节点
            节点没有值, 没有子节点
            节点有值, 有子节点
            节点没有值, 有子节点
            既没有值有没有子节点
            要兼顾处理上述 5 种情况
         */
        if (value != null || children != null) {
            // 处理前 4 种情况

            writer.write(">")

            if (value != null){
                writer.write("${value}")
            }

            if (children != null) {
                children.each {
                    it.build(writer)
                }
            }

            // 节点收尾
            writer.write("</${name}>")

        } else {
            // 既没有值有没有子节点的情况
            // <age/> , 之前写出了 "<age" , 现在写出 "/>"
            writer.write("/>")
        }
    }
}

3、在 Groovy 脚本中生成 Xml 信息

代码语言:javascript
复制
// 用于输出字符串
StringWriter stringWriter = new StringWriter()

// 创建自定义 Xml 构造器
def myBuilderSupport = new MyBuilderSupport(stringWriter)

// 构建 student 根节点
myBuilderSupport.student {
    // 构建 student 根节点下的 name 节点
    // 该节点有 code: "UTF-8" 属性
    // 节点元素为 "Tom" 字符串
    name("Tom", code: "UTF-8")

    age("18")
}

println ""
println(stringWriter)

执行结果 :

代码语言:javascript
复制
创建节点 名称 : student, 属性 : null, 值 : null
创建节点 名称 : name, 属性 : [code:UTF-8], 值 : Tom
setParent 设置子节点 name 的父节点是 student
nodeCompleted 完成了父节点为 parent : student  的节点 node : name 的闭合操作
创建节点 名称 : age, 属性 : null, 值 : 18
setParent 设置子节点 age 的父节点是 student
nodeCompleted 完成了父节点为 parent : student  的节点 node : age 的闭合操作
nodeCompleted 完成了父节点为 parent : null  的节点 node : student 的闭合操作

<student><name code='UTF-8'>Tom</name><age>18</age></student>

其中

代码语言:javascript
复制
<student><name code='UTF-8'>Tom</name><age>18</age></student>

就是生成的 Xml 数据 ;

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、创建 XmlNode 节点
  • 二、管理 XmlNode 节点并将根节点转为 Xml 信息
  • 三、完整代码示例
    • 1、自定义 Xml 生成器 MyBuilderSupport
      • 2、Xml 节点封装了 XmlNode
        • 3、在 Groovy 脚本中生成 Xml 信息
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档