XML DOM 獲取節點值
1142
2025-04-01
讀取 XML 文件
先來看一看如何讀取本地 XML 文件,同 JSON 數據類似,Go 同樣需要一個結構體來接收 XML 的數據。
我們定義一個 test.xml 文件,存取的是員工信息:
然后我們看到該 XML 有一條記錄,所以我們需要兩個結構體: Record 和 Telphone :
type Record struct { Name string Surname string Tel []Telephone } type Telephone struct { Mobile bool Number string }
然后定義一個 readFromXML() 函數,先讀取文件,然后解析該文件:
func readFromXMl(filename string, key interface{}) error { in, err := os.Open(filename) if err != nil { return err } decodeXML := xml.NewDecoder(in) err = decodeXML.Decode(key) if err != nil { return err } in.Close() return nil }
最后我們代碼的完整部分如下:
package main import ( "encoding/xml" "fmt" "os" ) // Users結構體:所有用戶組成的數組 type Record struct { Name string Surname string Tel []Telephone } type Telephone struct { Mobile bool Number string } func readFromXMl(filename string, key interface{}) error { in, err := os.Open(filename) if err != nil { return err } decodeXML := xml.NewDecoder(in) err = decodeXML.Decode(key) if err != nil { return err } in.Close() return nil } func main() { arguments := os.Args if len(arguments) == 1 { fmt.Println("Please provide a filename!") return } filename := arguments[1] var myRecord Record err := readFromXMl(filename, &myRecord) if err == nil { fmt.Println("XML:", myRecord) } else { fmt.Println(err) } }
在終端執行該代碼,得到如下結果:
$ go run main.go test.xml XML: {Yuzhou [{true 12345678} {true 0755-12345}]}
解析 XML 文件
Go 有一個使用 NewParser() 創建的 XML 解析器。 這需要一個 io.Reader() 作為參數并返回一個指向 Parser 的指針。 如果 XML 文件在用戶標簽、嵌套元素上設置了屬性,如果您能夠解析這些屬性,那么通過擴展,您應該能夠解析任何大小的 XML 文件。
現在新建另一個 test.xml 文件:
如何解析如上這個 XML 文檔呢?我們可以透過 xml 模塊的 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 本質上是一種樹狀結構,而我們可以定義與之匹配的 go 語言的結構體類型,然后通過 xml.Unmarshal 來將?XML?中的文件解析成對應的 struct 結構體。如上例子輸出如下結果:
{{ servers} 1 [{{ server} Shanghai_VPN 127.0.0.1} {{ server} Beijing_VPN 127.0.0.2}]
上面的例子中,將 xml 文件解析成對應的 struct 結構體是通過 xml.Unmarshal 來完成的,
這個過程是如何實現的?可以看到我們的 struct 定義后面多了一些類似于 xml:"serverName" 這樣的內容,這個是 struct 的一個特性,它們被稱為 struct tag,它們是用來輔助反射的。我們來看一下 Unmarshal 的定義:
func Unmarshal(data []byte, v interface{}) error
我們看到函式定義了兩個參數,第一個是 XML 文件流,第二個是儲存的對應類型,目前支持:
結構體 struct
切片 slice
字符串 string
XML 套件內部采用了反射來進行文件的對映,所以 v 里面的位置必須是輸出的。 Unmarshal 解析的時候 XML 元素和對應類型怎么對應起來的呢?
利用一個先后順序讀取:首先會讀取 struct tag,如果沒有,那么就會對應欄位名。必須注意一點的是解析的時候 tag、欄位名、XML 元素都是區分大小寫的的,所以必須一一對應。
解析 XML 到 struct 的時候遵循如下的規則:
如果 struct 的第二個參數是 string 或者 []byte 型,并且它的 tag 含有 ",innerxml" , Unmarshal 將會將此位置所對應的元素內所有內嵌的原始 xml 累加到此位置上,如上面例子 Description 定義。最后的輸出是:
總結
本文主要介紹了如何讀取本地 XML 文件和解析 XML 文件,分別使用 Go 的 encoding/ XML 包中的 NewDecoder() 和 Unmarshal() 函數。之后再去探索更多的用法,比如在?Web?開發中讀取配置文件,或者接收?XML?文件格式的文件。下一篇文章將會介紹如何將?Go?數據轉化為 XML?文件。
Go XML
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。