Skip to main content
在 Go 语言中,encoding/xml 包提供了对 XML 数据进行编码和解码的功能。以下是一些常用的 encoding/xml 包的 API 及其详细说明:

1. XML 编码

xml.Marshal

将 Go 对象转换为 XML 格式的字节切片。
package main

import (
    "encoding/xml"
    "fmt"
)

type Person struct {
    XMLName xml.Name `xml:"person"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age"`
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    data, err := xml.Marshal(p)
    if err != nil {
        fmt.Println("Error marshalling:", err)
        return
    }
    fmt.Println(string(data))
}

xml.MarshalIndent

将 Go 对象转换为带缩进格式的 XML 字节切片。
package main

import (
    "encoding/xml"
    "fmt"
)

type Person struct {
    XMLName xml.Name `xml:"person"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age"`
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    data, err := xml.MarshalIndent(p, "", "  ")
    if err != nil {
        fmt.Println("Error marshalling:", err)
        return
    }
    fmt.Println(string(data))
}

2. XML 解码

xml.Unmarshal

将 XML 字节切片解码为 Go 对象。
package main

import (
    "encoding/xml"
    "fmt"
)

type Person struct {
    XMLName xml.Name `xml:"person"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age"`
}

func main() {
    data := []byte(`<person><name>Alice</name><age>30</age></person>`)
    var p Person
    err := xml.Unmarshal(data, &p)
    if err != nil {
        fmt.Println("Error unmarshalling:", err)
        return
    }
    fmt.Printf("%+v\n", p)
}

3. 使用 xml.Decoderxml.Encoder

xml.NewDecoder

创建一个 XML 解码器,可以逐步从 io.Reader 读取 XML 数据。
package main

import (
    "encoding/xml"
    "fmt"
    "strings"
)

type Person struct {
    XMLName xml.Name `xml:"person"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age"`
}

func main() {
    data := `<person><name>Alice</name><age>30</age></person>`
    reader := strings.NewReader(data)
    decoder := xml.NewDecoder(reader)

    var p Person
    err := decoder.Decode(&p)
    if err != nil {
        fmt.Println("Error decoding:", err)
        return
    }
    fmt.Printf("%+v\n", p)
}

xml.NewEncoder

创建一个 XML 编码器,可以逐步向 io.Writer 写入 XML 数据。
package main

import (
    "encoding/xml"
    "fmt"
    "os"
)

type Person struct {
    XMLName xml.Name `xml:"person"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age"`
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    encoder := xml.NewEncoder(os.Stdout)
    err := encoder.Encode(p)
    if err != nil {
        fmt.Println("Error encoding:", err)
    }
}

4. 自定义 XML 编码和解码

自定义标签名称

通过结构体标签自定义 XML 元素名称。
package main

import (
    "encoding/xml"
    "fmt"
)

type Person struct {
    XMLName xml.Name `xml:"person"`
    FullName string   `xml:"name"`
    Age      int      `xml:"age"`
}

func main() {
    p := Person{FullName: "Alice", Age: 30}
    data, err := xml.MarshalIndent(p, "", "  ")
    if err != nil {
        fmt.Println("Error marshalling:", err)
        return
    }
    fmt.Println(string(data))
}

嵌套结构的编码和解码

package main

import (
    "encoding/xml"
    "fmt"
)

type Address struct {
    Street string `xml:"street"`
    City   string `xml:"city"`
}

type Person struct {
    XMLName xml.Name `xml:"person"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age"`
    Address Address  `xml:"address"`
}

func main() {
    p := Person{
        Name: "Alice",
        Age:  30,
        Address: Address{
            Street: "123 Main St",
            City:   "Metropolis",
        },
    }

    data, err := xml.MarshalIndent(p, "", "  ")
    if err != nil {
        fmt.Println("Error marshalling:", err)
        return
    }
    fmt.Println(string(data))

    var p2 Person
    err = xml.Unmarshal(data, &p2)
    if err != nil {
        fmt.Println("Error unmarshalling:", err)
        return
    }
    fmt.Printf("%+v\n", p2)
}

5. 处理复杂结构

使用 xml.RawToken

逐步处理 XML 令牌。
package main

import (
    "encoding/xml"
    "fmt"
    "strings"
)

func main() {
    data := `<person><name>Alice</name><age>30</age></person>`
    reader := strings.NewReader(data)
    decoder := xml.NewDecoder(reader)

    for {
        token, err := decoder.RawToken()
        if err != nil {
            if err.Error() == "EOF" {
                break
            }
            fmt.Println("Error decoding:", err)
            return
        }
        fmt.Printf("%T: %v\n", token, token)
    }
}

使用 xml.StartElementxml.EndElement

处理嵌套的 XML 元素。
package main

import (
    "encoding/xml"
    "fmt"
    "strings"
)

type Person struct {
    Name string `xml:"name"`
    Age  int    `xml:"age"`
}

func main() {
    data := `<people><person><name>Alice</name><age>30</age></person><person><name>Bob</name><age>25</age></person></people>`
    reader := strings.NewReader(data)
    decoder := xml.NewDecoder(reader)

    var people []Person
    var person Person

    for {
        token, err := decoder.Token()
        if err != nil {
            if err.Error() == "EOF" {
                break
            }
            fmt.Println("Error decoding:", err)
            return
        }

        switch se := token.(type) {
        case xml.StartElement:
            if se.Name.Local == "person" {
                err := decoder.DecodeElement(&person, &se)
                if err != nil {
                    fmt.Println("Error decoding element:", err)
                    return
                }
                people = append(people, person)
            }
        }
    }

    for _, p := range people {
        fmt.Printf("%+v\n", p)
    }
}
通过以上这些 encoding/xml 包中的基本 API,你可以方便地在 Go 程序中处理 XML 数据。无论是简单的数据结构还是复杂的嵌套对象,都可以通过这些 API 进行高效的编码和解码操作。