Go 语言标准库中encoding/xml模块详细功能介绍与示例
Go语言的 encoding/xml
模块提供了 XML 的编码和解码功能,支持结构体与 XML 之间的转换、处理命名空间、属性等。以下是核心方法及示例说明:
1. XML 编码(序列化)
xml.Marshal
将 Go 结构体转换为 XML 字节切片。
package main
import (
"encoding/xml"
"fmt"
)
type Person struct {
XMLName xml.Name `xml:"person"` // 定义 XML 根节点名称
Name string `xml:"name"` // 元素标签
Age int `xml:"age,attr"` // 作为属性
City string `xml:"city"` // 元素标签
}
func main() {
p := Person{Name: "Alice", Age: 30, City: "Beijing"}
data, _ := xml.MarshalIndent(p, "", " ") // 格式化输出
fmt.Println(string(data))
}
输出:
<person age="30">
<name>Alice</name>
<city>Beijing</city>
</person>
2. XML 解码(反序列化)
xml.Unmarshal
将 XML 字节切片解析到 Go 结构体。
xmlData := []byte(`
<person age="30">
<name>Bob</name>
<city>Shanghai</city>
</person>
`)
var p Person
err := xml.Unmarshal(xmlData, &p)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", p) // 输出: {XMLName:{Space: Local:person} Name:Bob Age:30 City:Shanghai}
3. 流式处理(编码器/解码器)
xml.NewEncoder
与 Encoder.Encode
将 XML 写入 io.Writer
(如文件或 HTTP 响应)。
file, _ := os.Create("person.xml")
encoder := xml.NewEncoder(file)
encoder.Indent("", " ") // 设置缩进格式
err := encoder.Encode(p)
if err != nil {
panic(err)
}
// 文件内容与上述 MarshalIndent 输出相同
xml.NewDecoder
与 Decoder.Decode
从 io.Reader
(如文件或 HTTP 请求)读取并解析 XML。
file, _ := os.Open("person.xml")
var p Person
decoder := xml.NewDecoder(file)
err := decoder.Decode(&p)
if err != nil {
panic(err)
}
fmt.Println(p.Name) // 输出: Bob
4. 处理嵌套结构与集合
嵌套结构体
type Address struct {
Street string `xml:"street"`
Zip string `xml:"zip"`
}
type Company struct {
XMLName xml.Name `xml:"company"`
Name string `xml:"name"`
Address Address `xml:"address"`
Employees []Person `xml:"employees>person"` // 嵌套集合
}
func main() {
company := Company{
Name: "Tech Corp",
Address: Address{Street: "Main St", Zip: "100001"},
Employees: []Person{
{Name: "Alice", Age: 30},
{Name: "Bob", Age: 25},
},
}
data, _ := xml.MarshalIndent(company, "", " ")
fmt.Println(string(data))
}
输出:
<company>
<name>Tech Corp</name>
<address>
<street>Main St</street>
<zip>100001</zip>
</address>
<employees>
<person age="30">
<name>Alice</name>
</person>
<person age="25">
<name>Bob</name>
</person>
</employees>
</company>
5. 处理 XML 属性与特殊标签
标签选项
attr
:字段作为 XML 属性。chardata
:字段作为字符数据(无标签包裹)。innerxml
:字段作为原始 XML 内容插入。omitempty
:空值字段省略。
type Book struct {
XMLName xml.Name `xml:"book"`
ID string `xml:"id,attr"` // 作为属性
Title string `xml:"title"`
Content string `xml:",innerxml"` // 直接嵌入原始 XML
Comment string `xml:",comment"` // 作为注释
Chapters []string `xml:"chapters>chapter,omitempty"` // 嵌套集合,空则省略
}
func main() {
book := Book{
ID: "101",
Title: "Go Programming",
Content: "<![CDATA[Hello, <world>!]]>", // CDATA 内容
Comment: "示例书籍",
Chapters: []string{"Intro", "Basics"},
}
data, _ := xml.MarshalIndent(book, "", " ")
fmt.Println(string(data))
}
输出:
<book id="101">
<title>Go Programming</title>
<![CDATA[Hello, <world>!]]>
<!--示例书籍-->
<chapters>
<chapter>Intro</chapter>
<chapter>Basics</chapter>
</chapters>
</book>
6. 处理命名空间
type SVG struct {
XMLName xml.Name `xml:"http://www.w3.org/2000/svg svg"`
Width string `xml:"width,attr"`
Height string `xml:"height,attr"`
}
func main() {
svg := SVG{Width: "100px", Height: "200px"}
data, _ := xml.MarshalIndent(svg, "", " ")
fmt.Println(string(data))
}
输出:
<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="200px"></svg>
7. 自定义编解码行为
实现 xml.Marshaler
或 xml.Unmarshaler
接口
自定义字段的序列化逻辑。
type CustomDate struct {
time.Time
}
func (d CustomDate) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
dateStr := d.Time.Format("2006-01-02")
return e.EncodeElement(dateStr, start)
}
type Event struct {
Date CustomDate `xml:"date"`
}
func main() {
event := Event{Date: CustomDate{time.Now()}}
data, _ := xml.MarshalIndent(event, "", " ")
fmt.Println(string(data)) // 输出: <Event><date>2023-10-01</date></Event>
}
8. 忽略字段
使用 xml:"-"
忽略字段。
type User struct {
Name string `xml:"name"`
Password string `xml:"-"` // 不序列化此字段
}
func main() {
u := User{Name: "Alice", Password: "secret"}
data, _ := xml.Marshal(u)
fmt.Println(string(data)) // 输出: <User><name>Alice</name></User>
}
总结
- 核心方法:
- 序列化:
Marshal
,MarshalIndent
,NewEncoder
- 反序列化:
Unmarshal
,NewDecoder
- 序列化:
- 结构体标签:
attr
:字段作为属性。chardata
:直接写入字符数据。innerxml
:嵌入原始 XML。omitempty
:空值省略。
- 高级功能:
- 命名空间:通过 XML 根节点定义。
- 自定义编解码:实现
Marshaler
/Unmarshaler
接口。 - 流式处理:适用于大文件或网络传输。
- 常见场景:
- 配置文件解析。
- Web 服务的 XML 请求/响应处理。
- 与遗留系统交互时处理复杂 XML 结构。
由于 go 并不支持 xml 1.1 的序列化、反序列化,如果我们操作 xml 1.1 版本就会出现以下问题
解决方法也很简单,我们只需要在 xml 字符中将 version=‘1.1’ 替换成version='1.0’或 version=“1.1” 删除即可。