Golang如何将XML反序列化为结构体

Golang如何将XML反序列化为结构体 Go Playground - Go 编程语言

2 回复

我移除了所有 soap:xmlns:in: 前缀,然后它似乎可以工作了 → 似乎可以工作:Go Playground - The Go Programming Language

免责声明:我不熟悉 XML 解组,因此此解决方案可能仅在此特定上下文中偶然有效。

更多关于Golang如何将XML反序列化为结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,可以使用标准库的encoding/xml包将XML反序列化为结构体。以下是具体实现方法:

1. 基本反序列化

package main

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

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

func main() {
    xmlData := `
<person>
    <name>张三</name>
    <age>30</age>
    <email>zhangsan@example.com</email>
</person>`

    var person Person
    err := xml.Unmarshal([]byte(xmlData), &person)
    if err != nil {
        fmt.Println("解析错误:", err)
        return
    }
    
    fmt.Printf("姓名: %s\n", person.Name)
    fmt.Printf("年龄: %d\n", person.Age)
    fmt.Printf("邮箱: %s\n", person.Email)
}

2. 处理嵌套结构

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

type Employee struct {
    XMLName xml.Name `xml:"employee"`
    ID      int      `xml:"id,attr"`
    Name    string   `xml:"name"`
    Dept    string   `xml:"department"`
    Address Address  `xml:"address"`
}

func main() {
    xmlData := `
<employee id="1001">
    <name>李四</name>
    <department>技术部</department>
    <address>
        <city>北京</city>
        <street>中关村大街</street>
        <zipcode>100080</zipcode>
    </address>
</employee>`

    var emp Employee
    err := xml.Unmarshal([]byte(xmlData), &emp)
    if err != nil {
        fmt.Println("解析错误:", err)
        return
    }
    
    fmt.Printf("ID: %d\n", emp.ID)
    fmt.Printf("姓名: %s\n", emp.Name)
    fmt.Printf("地址: %s %s %s\n", emp.Address.City, emp.Address.Street, emp.Address.ZipCode)
}

3. 处理数组/切片

type Company struct {
    XMLName   xml.Name   `xml:"company"`
    Employees []Employee `xml:"employees>employee"`
}

func main() {
    xmlData := `
<company>
    <employees>
        <employee id="1001">
            <name>王五</name>
            <department>研发部</department>
        </employee>
        <employee id="1002">
            <name>赵六</name>
            <department>市场部</department>
        </employee>
    </employees>
</company>`

    var company Company
    err := xml.Unmarshal([]byte(xmlData), &company)
    if err != nil {
        fmt.Println("解析错误:", err)
        return
    }
    
    for _, emp := range company.Employees {
        fmt.Printf("员工ID: %d, 姓名: %s, 部门: %s\n", emp.ID, emp.Name, emp.Dept)
    }
}

4. 使用xml.Unmarshal的完整示例

package main

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

type Book struct {
    XMLName     xml.Name `xml:"book"`
    ISBN        string   `xml:"isbn,attr"`
    Title       string   `xml:"title"`
    Author      string   `xml:"author"`
    Price       float64  `xml:"price"`
    Description string   `xml:"description"`
    Categories  []string `xml:"categories>category"`
}

func main() {
    // 从字符串解析
    xmlStr := `
<book isbn="978-7-121-12345-6">
    <title>Go语言编程实战</title>
    <author>Go专家</author>
    <price>89.90</price>
    <description>深入讲解Go语言高级特性</description>
    <categories>
        <category>编程</category>
        <category>计算机</category>
        <category>Go语言</category>
    </categories>
</book>`
    
    var book Book
    err := xml.Unmarshal([]byte(xmlStr), &book)
    if err != nil {
        fmt.Println("解析错误:", err)
        return
    }
    
    fmt.Printf("ISBN: %s\n", book.ISBN)
    fmt.Printf("书名: %s\n", book.Title)
    fmt.Printf("价格: %.2f\n", book.Price)
    fmt.Printf("分类: %v\n", book.Categories)
    
    // 从文件解析
    file, err := os.Open("book.xml")
    if err != nil {
        fmt.Println("打开文件错误:", err)
        return
    }
    defer file.Close()
    
    data, err := io.ReadAll(file)
    if err != nil {
        fmt.Println("读取文件错误:", err)
        return
    }
    
    var bookFromFile Book
    err = xml.Unmarshal(data, &bookFromFile)
    if err != nil {
        fmt.Println("解析文件错误:", err)
        return
    }
}

5. 处理CDATA和命名空间

type Article struct {
    XMLName xml.Name `xml:"article"`
    ID      string   `xml:"id,attr"`
    Title   string   `xml:"title"`
    Content string   `xml:"content"`
}

func main() {
    xmlData := `
<article id="a001">
    <title>Go语言XML处理</title>
    <content><![CDATA[<p>这是包含HTML标签的内容</p>]]></content>
</article>`

    var article Article
    err := xml.Unmarshal([]byte(xmlData), &article)
    if err != nil {
        fmt.Println("解析错误:", err)
        return
    }
    
    fmt.Printf("文章ID: %s\n", article.ID)
    fmt.Printf("内容: %s\n", article.Content)
}

6. 使用xml.Decoder流式解析

func parseXMLStream(reader io.Reader) {
    decoder := xml.NewDecoder(reader)
    
    for {
        token, err := decoder.Token()
        if err == io.EOF {
            break
        }
        if err != nil {
            fmt.Println("解析错误:", err)
            return
        }
        
        switch se := token.(type) {
        case xml.StartElement:
            if se.Name.Local == "employee" {
                var emp Employee
                decoder.DecodeElement(&emp, &se)
                fmt.Printf("解析到员工: %s\n", emp.Name)
            }
        }
    }
}

这些示例展示了Go语言中将XML反序列化为结构体的各种场景。关键点是正确使用结构体标签定义XML映射关系,xml.Unmarshal函数会自动根据标签将XML数据填充到对应的结构体字段中。

回到顶部