在 Go (Golang) 中处理 XML:完整指南与示例
Go (Golang) 通过 encoding/xml 包提供了对 XML 处理的内置支持。该包提供了强大的工具,用于解析(读取)、生成(写入)和序列化 XML 格式的数据。与 JSON 不同,XML 需要更严格的结构并支持命名空间,这使得 encoding/xml 特别灵活。
在本文中,我们将详细讲解如何在 Go 中处理 XML:从基本的解组(将 XML 转换为 Go 结构体)到创建包含属性和命名空间的复杂 XML 文档。
基础:结构体和 XML 标签
为了将 XML 元素与 Go 结构体的字段进行映射,需要使用特殊的 xml 标签。这些标签定义了元素名称、属性以及序列化时的行为。
type Person struct { XMLName xml.Name `xml:"person"` ID int `xml:"id,attr"` Name string `xml:"name"` Age int `xml:"age"` Email string `xml:"email,omitempty"` Addresses []Address `xml:"address"`}
type Address struct { City string `xml:"city"` Street string `xml:"street"` ZipCode string `xml:"zip"`}xml:"person"— 根元素的名称。xml:"id,attr"— 该字段成为元素的属性。xml:"email,omitempty"— 如果字段为空,则跳过。xml:"address"— 数组将被序列化为多个嵌套元素。
解析 XML:解组 (Unmarshal)
xml.Unmarshal 函数将 XML 字节数据转换为 Go 结构体。以下是我们 Person 类型的示例:
package main
import ( "encoding/xml" "fmt")
func main() { xmlData := `<person id="123"> <name>伊万·彼得罗夫</name> <age>30</age> <email>ivan@example.com</email> <address> <city>莫斯科</city> <street>特维尔大街, 1</street> <zip>101000</zip> </address></person>`
var p Person err := xml.Unmarshal([]byte(xmlData), &p) if err != nil { fmt.Printf("解析错误: %v", err) return }
fmt.Printf("ID: %d", p.ID) fmt.Printf("姓名: %s", p.Name) fmt.Printf("年龄: %d", p.Age) fmt.Printf("城市: %s", p.Addresses[0].City)}程序输出:
ID: 123姓名: 伊万·彼得罗夫年龄: 30城市: 莫斯科生成 XML:编组 (Marshal)
要从结构体创建 XML,使用 xml.Marshal 或 xml.MarshalIndent(带缩进)。
func main() { p := Person{ ID: 456, Name: "安娜·斯米尔诺娃", Age: 25, Email: "anna@example.com", Addresses: []Address{ {City: "圣彼得堡", Street: "涅瓦大街, 10", ZipCode: "191186"}, }, }
output, err := xml.MarshalIndent(p, "", " ") if err != nil { fmt.Printf("序列化错误: %v", err) return }
fmt.Println(string(output))}结果:
<person id="456"> <name>安娜·斯米尔诺娃</name> <age>25</age> <email>anna@example.com</email> <address> <city>圣彼得堡</city> <street>涅瓦大街, 10</street> <zip>191186</zip> </address></person>处理命名空间 (Namespaces)
XML 命名空间通过带有 xmlns 属性的 XMLName 字段进行处理。
type Document struct { XMLName xml.Name `xml