解析 XML 文件的 Unmarshal 函数

我们来看一下 Unmarshal 的定义:

func Unmarshal(data []byte, v interface{}) error

我们看到函式定义了两个参数,第一个是 XML 文件流,第二个是储存的对应类型,目前支持:

  • 结构体 struct
  • 切片 slice
  • 字符串 string
NewParser()io.Reader()Parser
test.xml
<?xml version="1.0" encoding="utf-8"?>
<servers version="1">
    <server>
        <serverName>Guangzhou_node1</serverName>
        <serverIP>127.0.0.1</serverIP>
    </server>
    <server>
        <serverName>Guangzhou_node2</serverName>
        <serverIP>127.0.0.2</serverIP>
    </server>
</servers>
Unmarshal()
func Unmarshal(data []byte, v interface{}) error

data 接收的是 XML 文件流,v 是需要输出的结构,定义为 interface,也就是可以把 XML 转换为任意的格式。我们这里主要介绍 struct 的转换,因为 struct 和 XML 都有类似树状结构的特征。

定义我们的结构体:

type Recurlyservers struct {
  XMLName     xml.Name `xml:"servers"`
  Version     string   `xml:"version,attr"`
  Svs         []server `xml:"server"`
  Description string   `xml:",innerxml"`
}

type server struct {
  XMLName    xml.Name `xml:"server"`
  ServerName string   `xml:"serverName"`
  ServerIP   string   `xml:"serverIP"`
}

完整代码:

package main

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

type Recurlyservers struct {
	XMLName     xml.Name `xml:"servers"`
	Version     string   `xml:"version,attr"`
	Svs         []server `xml:"server"`
	Description string   `xml:",innerxml"`
}

type server struct {
	XMLName    xml.Name `xml:"server"`
	ServerName string   `xml:"serverName"`
	ServerIP   string   `xml:"serverIP"`
}

func main() {
	file, err := os.Open("test.xml") // For read access.
	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}
	defer file.Close()
	data, err := ioutil.ReadAll(file)
	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}
	v := Recurlyservers{}
	err = xml.Unmarshal(data, &v)
	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}

	fmt.Println(v)
}
xml.Unmarshal
{{ servers} 1 [{{ server} Guangzhou_node1 127.0.0.1} {{ server} Guangzhou_node2 127.0.0.2}]
<server>
    <serverName>Guangzhou_node1</serverName>
    <serverIP>127.0.0.1</serverIP>
</server>
<server>
    <serverName>Guangzhou_node2</serverName>
    <serverIP>127.0.0.2</serverIP>
</server>
}
xml.Unmarshal
xml:"serverName"
Unmarshal

利用一个先后顺序读取:首先会读取 struct tag,如果没有,那么就会对应栏位名。必须注意一点的是解析的时候 tag、栏位名、XML 元素都是区分大小写的的,所以必须一一对应。

解析 XML 到 struct 的规则

解析 XML 到 struct 的时候遵循如下的规则:

string[]byte",innerxml"Unmarshal

如上面例子 Description 定义。最后的输出是:

    <server>
        <serverName>Shanghai_VPN</serverName>
        <serverIP>127.0.0.1</serverIP>
    </server>
    <server>
        <serverName>Beijing_VPN</serverName>
        <serverIP>127.0.0.2</serverIP>
    </server>
Unmarshal"name""namespace-URL name"Unmarshal",attr""name,attr"Unmarshal",any,attr"",chardata"type [] bytestring",comment"type [] bytestring"a""a> b> c"">"">"XMLName",attr",",chardata"",any"" - "

总结

Unmarshal()

推荐阅读: