Go语言的标准库encoding/xml提供了对XML数据的解析和生成支持,开发者可以通过该包快速完成XML格式数据的读写操作,无需引入第三方依赖。该包的核心能力围绕结构体标签映射展开,通过定义匹配XML结构的结构体,就能实现XML与Go数据类型的自动转换。

XML解析基础
解析XML数据最常用的方式是使用xml.Unmarshal函数,该函数可以将XML字节数据转换为对应的Go结构体实例。首先需要定义与XML结构匹配的结构体,通过struct tag指定每个字段对应的XML标签名称和属性。
以下是一个简单的XML解析示例,假设我们有如下XML数据:
<user>
<name>张三</name>
<age>25</age>
<email>test@ipipp.com</email>
</user>
对应的Go结构体定义和解析代码如下:
package main
import (
"encoding/xml"
"fmt"
)
// User 定义与XML结构匹配的结构体
type User struct {
XMLName xml.Name `xml:"user"` // 指定根节点名称
Name string `xml:"name"` // 映射name子标签
Age int `xml:"age"` // 映射age子标签
Email string `xml:"email"` // 映射email子标签
}
func main() {
xmlData := []byte(`<user><name>张三</name><age>25</age><email>test@ipipp.com</email></user>`)
var user User
// 解析XML数据到结构体
err := xml.Unmarshal(xmlData, &user)
if err != nil {
fmt.Println("解析XML失败:", err)
return
}
fmt.Printf("解析结果: 姓名=%s, 年龄=%d, 邮箱=%sn", user.Name, user.Age, user.Email)
}
解析XML属性
除了解析XML的标签内容,encoding/xml也支持解析XML标签的属性,只需要在struct tag中添加,attr后缀即可。例如下面的XML包含属性信息:
<user id="1001">
<name>李四</name>
<age>30</age>
</user>
对应的结构体定义和解析代码如下:
package main
import (
"encoding/xml"
"fmt"
)
type User struct {
XMLName xml.Name `xml:"user"`
ID int `xml:"id,attr"` // 解析id属性
Name string `xml:"name"`
Age int `xml:"age"`
}
func main() {
xmlData := []byte(`<user id="1001"><name>李四</name><age>30</age></user>`)
var user User
err := xml.Unmarshal(xmlData, &user)
if err != nil {
fmt.Println("解析失败:", err)
return
}
fmt.Printf("用户ID: %d, 姓名: %s, 年龄: %dn", user.ID, user.Name, user.Age)
}
生成XML数据
生成XML数据可以使用xml.Marshal或者xml.MarshalIndent函数,前者生成紧凑的XML,后者生成带缩进格式的XML,更适合阅读。生成XML时同样依赖结构体的struct tag定义。
以下是生成XML的示例代码:
package main
import (
"encoding/xml"
"fmt"
)
type User struct {
XMLName xml.Name `xml:"user"`
Name string `xml:"name"`
Age int `xml:"age"`
Email string `xml:"email"`
}
func main() {
user := User{
Name: "王五",
Age: 28,
Email: "wangwu@ipipp.com",
}
// 生成带缩进的XML
xmlData, err := xml.MarshalIndent(user, "", " ")
if err != nil {
fmt.Println("生成XML失败:", err)
return
}
// 添加XML头
xmlHeader := []byte(xml.Header)
fullXML := append(xmlHeader, xmlData...)
fmt.Println("生成的XML数据:")
fmt.Println(string(fullXML))
}
复杂XML结构处理
当XML结构包含嵌套或者重复的子元素时,可以通过在结构体中定义切片类型的字段来处理。例如下面的XML包含多个子元素:
<class>
<name>三年级一班</name>
<students>
<student>
<name>赵六</name>
<score>95</score>
</student>
<student>
<name>孙七</name>
<score>88</score>
</student>
</students>
</class>
对应的结构体定义和解析代码如下:
package main
import (
"encoding/xml"
"fmt"
)
// Student 学生结构体
type Student struct {
Name string `xml:"name"`
Score int `xml:"score"`
}
// Class 班级结构体
type Class struct {
XMLName xml.Name `xml:"class"`
Name string `xml:"name"`
Students []Student `xml:"students>student"` // 映射嵌套的student标签
}
func main() {
xmlData := []byte(`<class><name>三年级一班</name><students><student><name>赵六</name><score>95</score></student><student><name>孙七</name><score>88</score></student></students></class>`)
var class Class
err := xml.Unmarshal(xmlData, &class)
if err != nil {
fmt.Println("解析失败:", err)
return
}
fmt.Printf("班级名称: %sn", class.Name)
fmt.Println("学生列表:")
for _, stu := range class.Students {
fmt.Printf(" 姓名: %s, 分数: %dn", stu.Name, stu.Score)
}
}
常用struct tag说明
encoding/xml包的struct tag有多种配置项,常用的配置如下:
| tag配置 | 说明 |
|---|---|
| xml:"tagname" | 指定字段对应的XML标签名称 |
| xml:"tagname,attr" | 指定字段对应XML标签的属性 |
| xml:"tagname,omitempty" | 当字段为零值时,生成XML时忽略该字段 |
| xml:"tagname,innerxml" | 保留该标签下的原始XML内容,不做解析 |
| xml:"a>b" | 映射嵌套路径为a标签下的b标签 |
注意事项
- 结构体字段必须是可导出的(首字母大写),否则encoding/xml包无法访问该字段,会导致解析或生成失败。
- XML标签名称区分大小写,struct tag中指定的标签名需要和XML中的标签名完全一致。
- 解析XML时如果结构体定义和实际XML结构不匹配,不会报错,只会将匹配的字段赋值,不匹配的字段保持零值。
- 生成XML时如果需要自定义XML头,可以先调用
xml.Header获取默认头,再自行拼接修改。
Goxmlencoding/xmlstruct_tag修改时间:2026-07-09 14:21:43