Go 语言标准库中encoding/xml模块详细功能介绍与示例

Go语言的 encoding/xml 模块提供了 XML 的编码和解码功能,支持结构体与 XML 之间的转换、处理命名空间、属性等。以下是核心方法及示例说明:


1. XML 编码(序列化)

xml.Marshal

将 Go 结构体转换为 XML 字节切片。

go 复制代码
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))
}

输出

xml 复制代码
<person age="30">
  <name>Alice</name>
  <city>Beijing</city>
</person>

2. XML 解码(反序列化)

xml.Unmarshal

将 XML 字节切片解析到 Go 结构体。

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.NewEncoderEncoder.Encode

将 XML 写入 io.Writer(如文件或 HTTP 响应)。

go 复制代码
file, _ := os.Create("person.xml")
encoder := xml.NewEncoder(file)
encoder.Indent("", "  ") // 设置缩进格式
err := encoder.Encode(p)
if err != nil {
    panic(err)
}
// 文件内容与上述 MarshalIndent 输出相同
xml.NewDecoderDecoder.Decode

io.Reader(如文件或 HTTP 请求)读取并解析 XML。

go 复制代码
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. 处理嵌套结构与集合

嵌套结构体
go 复制代码
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))
}

输出

xml 复制代码
<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:空值字段省略。
go 复制代码
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))
}

输出

xml 复制代码
<book id="101">
  <title>Go Programming</title>
  <![CDATA[Hello, <world>!]]>
  <!--示例书籍-->
  <chapters>
    <chapter>Intro</chapter>
    <chapter>Basics</chapter>
  </chapters>
</book>

6. 处理命名空间

go 复制代码
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))
}

输出

xml 复制代码
<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="200px"></svg>

7. 自定义编解码行为

实现 xml.Marshalerxml.Unmarshaler 接口

自定义字段的序列化逻辑。

go 复制代码
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:"-" 忽略字段。

go 复制代码
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" 删除即可。

相关推荐
liu****4 小时前
11.字符函数和字符串函数(一)
linux·运维·c语言·开发语言·数据结构·算法
hmbbcsm4 小时前
练习python题目小记(七)
开发语言·python
aini_lovee4 小时前
基于UERD算法的JPEG图像隐写MATLAB实现
开发语言·算法·matlab
繁华似锦respect4 小时前
HTTPS 中 TLS 协议详细过程 + 数字证书/签名深度解析
开发语言·c++·网络协议·http·单例模式·设计模式·https
坐吃山猪4 小时前
Electron03-桌面文件夹
开发语言·javascript·ecmascript
我命由我123454 小时前
微信小程序 - 内容弹出框实现(Vant Weapp 实现、原生实现)
开发语言·前端·javascript·微信小程序·小程序·前端框架·js
豐儀麟阁贵4 小时前
8.6运行时异常
java·开发语言
小年糕是糕手4 小时前
【C++】类和对象(四) -- 取地址运算符重载、构造函数plus
c语言·开发语言·数据结构·c++·算法·leetcode·蓝桥杯
橘子编程4 小时前
仓颉语言变量与表达式解析
java·linux·服务器·开发语言·数据库·python·mysql
LXS_3574 小时前
Day 15 C++之文件操作
开发语言·c++·学习方法·改行学it