【收藏】MyBatis 常用語法匯總
960
2025-04-01
解析 XML 文件的 Unmarshal 函數
解析 XML 到 struct 的規則
總結
解析 XML 文件的 Unmarshal 函數
解析 XML 到 struct 的規則
總結
解析 XML 文件的 Unmarshal 函數
我們來看一下 Unmarshal 的定義:
func Unmarshal(data []byte, v interface{}) error
我們看到函式定義了兩個參數,第一個是 XML 文件流,第二個是儲存的對應類型,目前支持:
結構體 struct
切片 slice
字符串 string
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} Guangzhou_node1 127.0.0.1} {{ server} Guangzhou_node2 127.0.0.2}]
上面的例子中,將 xml 文件解析成對應的 struct 結構體是通過 xml.Unmarshal 來完成的,
這個過程是如何實現的?可以看到我們的 struct 定義后面多了一些類似于 xml:"serverName" 這樣的內容,這個是 struct 的一個特性,它們被稱為 struct tag,它們是用來輔助反射的。
XML 套件內部采用了反射來進行文件的對映,所以 v 里面的位置必須是輸出的。Unmarshal 解析的時候 XML 元素和對應類型怎么對應起來的呢?
利用一個先后順序讀取:首先會讀取 struct tag,如果沒有,那么就會對應欄位名。必須注意一點的是解析的時候 tag、欄位名、XML 元素都是區分大小寫的的,所以必須一一對應。
解析 XML 到 struct 的規則
解析 XML 到 struct 的時候遵循如下的規則:
如果 struct 的第二個參數是 string 或者 []byte 型,并且它的 tag 含有 ",innerxml",Unmarshal 將會將此位置所對應的元素內所有內嵌的原始 xml 累加到此位置的元素,其余規則仍然適用。
如上面例子 Description 定義。最后的輸出是:
如果 struct 有一個名為 XMLName 的字段名稱,Unmarshal 在該字段中記錄元素名稱。
如果 XMLName 字段具有表單的關聯標記 "name" 或"namespace-URL name",XML元素必須具有
給定的名稱(以及可選的名稱空間)或 Unmarshal 返回錯誤。
如果 XML 元素具有名稱與 a 匹配的屬性 struct field name,其關聯標記包含 ",attr" 或
"name,attr" 形式的struct field標簽中的顯式名稱,Unmarshal 在該字段中記錄屬性值。
如果 XML 元素的屬性未由前一個處理規則和 struct 有一個字段,其中包含相關的標記",any,attr",Unmarshal在第一個中記錄屬性值這樣的領域。
如果 XML 元素包含字符數據,那么該數據就是累積在第一個具有標記 ",chardata" 的 struct 字段中。struct字段可以有 type [] byte 或 string。如果沒有這樣的字段,則丟棄字符數據。
如果 XML 元素包含注釋,則會累積它們第一個帶有標記 ",comment" 的 struct 字段。結構字段可以有 type [] byte 或 string 。如果沒有這樣的話字段,comment 會被丟棄。
如果 XML 元素包含名稱匹配的子元素格式化為 "a"或 "a> b> c"的標記的前綴,unmarshal 將下降到XML 結構中尋找帶有的元素給定名稱,并將最內層元素映射到該結構領域。以 ">" 開頭的標簽相當于一個開始字段名稱后跟 ">"。
如果 XML 元素包含名稱匹配的子元素 struct 字段的 XMLName 標記,struct字段沒有根據先前規則的顯式名稱標簽,unmarshal 映射該 struct 字段的子元素。
如果 XML 元素包含名稱與 a 匹配的子元素沒有任何模式標志的字段(",attr",",chardata" 等),Unmarshal 將子元素映射到該struct字段。
如果 XML 元素包含未匹配任何子元素以上規則和 struct 有一個標記為 ",any" 的字段,unmarshal 將子元素映射到該struct字段。
處理匿名結構字段,就像它的字段一樣 value 是外部結構的一部分。
帶有標記" - " 的結構字段永遠不會被 unmarshal。
總結
本文作為學習筆記,主要介紹了如何解析 XML 文件的 Unmarshal() 函數。之后再去探索更多的用法,比如在?Web?開發中讀取配置文件,或者接收?XML?文件格式的文件,或者看到 XML 格式和 JSON 格式做轉換。
推薦閱讀:
Go by Example: XML
Parse and generate XML easily in golang
Go XML
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。