GO输出 XML

简介: GO输出 XML

输出 XML
假若我们不是要解析如上所示的 XML 文件,而是生成它,那么在 go 语言中又该如何实现
呢? xml 包中提供了 Marshal 和 MarshalIndent 两个函数,来满足我们的需求。这两个函数
主要的区别是第二个函数会增加前缀和缩进,函数的定义如下所示:
func Marshal(v interface{}) ([]byte, error)
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
两个函数第一个参数是用来生成 XML 的结构定义类型数据,都是返回生成的 XML 数据流。
下面我们来看一下如何输出如上的 XML:
package main
import (
"encoding/xml"
"fmt"
"os"
)
type Servers struct {
XMLName xml.Name xml:"servers"
Version string xml:"version,attr"
Svs []server xml:"server"
}
type server struct {
ServerName string xml:"serverName"
ServerIP string xml:"serverIP"
}
func main() {
v := &Servers{Version: "1"}
v.Svs = append(v.Svs, server{"Shanghai_VPN", "127.0.0.1"})
v.Svs = append(v.Svs, server{"Beijing_VPN", "127.0.0.2"})
output, err := xml.MarshalIndent(v, " ", " ")
if err != nil {
fmt.Printf("error: %v\n", err)
}
os.Stdout.Write([]byte(xml.Header))
os.Stdout.Write(output)
}
上面的代码输出如下信息:
<?xml version="1.0" encoding="UTF-8"?>


Shanghai_VPN
127.0.0.1


Beijing_VPN
127.0.0.2


和我们之前定义的文件的格式一模一样,之所以会有 os.Stdout.Write([]byte(xml.Header))
这句代码的出现,是因为 xml.MarshalIndent 或者 xml.Marshal 输出的信息都是不带 XML 头
的,为了生成正确的 xml 文件,我们使用了 xml 包预定义的 Header 变量。
我们看到 Marshal 函数接收的参数 v 是 interface{}类型的,即它可以接受任意类型的参数,
那么 xml 包,根据什么规则来生成相应的 XML 文件呢?
• 如果 v 是 array 或者 slice,那么输出每一个元素,类似 value
• 如果 v 是指针,那么会 Marshal 指针指向的内容,如果指针为空,什么都不输出
• 如果 v 是 interface,那么就处理 interface 所包含的数据
• 如果 v 是其他数据类型,就会输出这个数据类型所拥有的字段信息
生成的 XML 文件中的 element 的名字又是根据什么决定的呢?元素名按照如下优先级从
struct 中获取:
• 如果 v 是 struct,XMLName 的 tag 中定义的名称
• 类型为 xml.Name 的名叫 XMLName 的字段的值
• 通过 strcut 中字段的 tag 来获取
• 通过 strcut 的字段名用来获取
• marshall 的类型名称
我们应如何设置 struct 中字段的 tag 信息以控制最终 xml 文件的生成呢?
• XMLName 不会被输出
• tag 中含有"-"的字段不会输出
• tag 中含有"name,attr",会以 name 作为属性名,字段值作为值输出为这个 XML 元
素的属性,如上 version 字段所描述
• tag 中含有",attr",会以这个 struct 的字段名作为属性名输出为 XML 元素的属性,
类似上一条,只是这个 name 默认是字段名了。
• tag 中含有",chardata",输出为 xml 的 character data 而非 element。
• tag 中含有",innerxml",将会被原样输出,而不会进行常规的编码过程
• tag 中含有",comment",将被当作 xml 注释来输出,而不会进行常规的编码过程,
字段值中不能含有"--"字符串
• tag 中含有"omitempty",如果该字段的值为空值那么该字段就不会被输出到 XML,
空值包括:false、0、nil 指针或 nil 接口,任何长度为 0 的 array, slice, map 或者 string
• tag 中含有"a>b>c",那么就会循环输出三个元素 a 包含 b,b 包含 c,例如如下代
码就会输出
• FirstName string xml:"name>first"
• LastName string xml:"name>last"


• Asta
• Xie

上面我们介绍了如何使用 Go 语言的 xml 包来编/解码 XML 文件,重要的一点是对 XML 的
所有操作都是通过 struct tag 来实现的,所以学会对 struct tag 的运用变得非常重要,在文
章中我们简要的列举了如何定义 tag。更多内容或 tag 定义请参看相应的官方资料。

目录
相关文章
|
消息中间件 NoSQL Kafka
如何保证消息不被重复消费~~~~~(如何保证消息队列的幂等性)
如何保证消息不被重复消费~~~~~(如何保证消息队列的幂等性)
229 0
|
9月前
|
存储 算法 Java
面试必备!一文搞懂HashMap如何优雅处理哈希冲突
大家好,我是小米,一个积极的程序员。今天聊聊Java面试中的常见问题——“HashMap是怎么解决哈希冲突的?”。通过一个小故事,我们了解到HashMap使用链地址法(JDK 1.8前)和红黑树(JDK 1.8后)来处理哈希冲突。链地址法用链表存储冲突的元素,而红黑树在链表长度超过8时启用,提升查找效率。希望这个讲解能帮助你更好地理解HashMap的工作原理。欢迎留言讨论,关注我的公众号“软件求生”,获取更多技术干货!
299 3
|
人工智能 数据可视化 搜索推荐
Todolist 任务管理:企业发展的核心驱动力与未来展望
任务管理对企业至关重要,能够提高工作效率、优化资源配置、增强团队协作、提升决策质量和确保项目按时交付,未来,任务管理将与人工智能、移动化和大数据等技术深度融合,助力企业实现更高效、便捷和智能化的管理。
|
前端开发 Java 编译器
【前端学java】java基础练习缺少项目?看这篇文章就够了!(完结)
【8月更文挑战第11天】java基础练习缺少项目?看这篇文章就够了!(完结)
89 0
|
传感器 编解码 物联网
STC89C52+DHT20设计的环境温湿度检测仪
本项目基于STC89C52单片机和DHT20温湿度传感器,实现了一款环境温湿度检测仪。通过传感器采集环境的温度和湿度数据,利用IIC接口的OLED显示屏显示出来,便于用户实时监测环境温湿度状态。
316 1
|
Java 开发者 JavaScript
Struts 2 开发者的秘籍:隐藏的表单标签库功能,能否成为你下个项目的大杀器?
【8月更文挑战第31天】Struts 2表单标签库是提升Web页面交互体验的神器。它提供丰富的标签,如`&lt;s:textfield&gt;`和`&lt;s:select&gt;`,简化表单元素创建与管理,支持数据验证和动态选项展示。结合示例代码,如创建文本输入框并与Action类属性绑定,显著提升开发效率和用户体验。通过自定义按钮样式等功能,Struts 2表单标签库让开发者更专注于业务逻辑实现。
121 0
|
机器学习/深度学习 Android开发 开发者
探索移动应用开发的未来:跨平台框架与原生开发的融合
随着移动技术的不断进步,移动应用开发领域正经历着前所未有的变革。跨平台框架的兴起为开发者提供了一种高效、灵活的开发方式,而原生开发则因其卓越的性能和用户体验而备受青睐。本文将深入探讨跨平台框架与原生开发的优势与局限,分析它们如何相互补充,并预测未来移动应用开发的趋势。
|
网络协议 算法 网络性能优化
CCNA 200-301系列:TCP 窗口
【4月更文挑战第21天】
180 7
|
监控 搜索推荐 关系型数据库
盘点73个Python各行各业管理系统源码Python爱好者不容错过
盘点73个Python各行各业管理系统源码Python爱好者不容错过
211 0
|
存储 SQL 机器学习/深度学习
数据仓库与数据湖的联系与区别
数据仓库与数据湖的联系与区别
数据仓库与数据湖的联系与区别