通過Go來分析和建立XML
一、分析 XML
下面有一個 xml 檔案讓你分析。
<?xml version="1.0" encoding="utf-8"?>
<post id="1">
<content>Hello World!</content>
<author id="2">Sau She</author>
<comments>
<comment id="1">
<content>Have a great day!</content>
<author id="3">Adam</author>
</comment>
<comment id="2">
<content>How are you today?</content>
<author id="4">Betty</author>
</comment>
</comments>
</post>
怎麼樣去分析呢?我們要遵循一下原則。
(1)通過建立一個名為 XMLName、型別為 xml.Name 的欄位,可以將 XML 元素的名字儲存在這個欄位裡面。
(2)通過建立一個與 XML 元素屬性同名的欄位,並使用 xml:"<name>,attr"作為該欄位的結構標籤,可以將元素的屬性的值儲存到這個欄位裡面。
(3)通過建立一個與 XML 元素相同的欄位,並使用 xml:",chardata"作為該欄位的結構標籤,可以將 XML 元素的字元資料儲存到這個欄位裡面。
(4)通過定義一個任意名字欄位,並使用 XML:",innerxml"作為該欄位的結構標籤,可以將 XML 元素中的原始 XML 儲存到這個欄位裡面。
(5)沒有模式標籤(如,attr、,chardata 或者,innerxml)的結構欄位將與同名的 XML 元素匹配。
(6)使用 xml:"a>b>c"這樣的結構標籤可以在不指定樹樁結構的情況下直接獲取指定的 XML 元素,其中 a 和 b 為中間元素,而 c 則是想要獲取的節點元素。
*解析程式碼 *
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
"log"
"os"
)
type Post struct {
XMLName xml.Name `xml:"post"`
Id string `xml:"id,attr"`
Author Author `xml:"author"`
Xml string `xml:",innerxml"`
Comments []Comment `xml:"comments>comment"`
}
type Author struct {
Id string `xml:"id,attr"`
Name string `xml:",chardata"`
}
type Comment struct {
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
}
func main() {
file, err := os.Open("src/text/xml/post.xml")
if err != nil {
log.Fatalf("Error opening XML file %v",err)
return
}
defer file.Close()
bytes, err := ioutil.ReadAll(file)
if err != nil {
log.Fatalf("Error reading XML file %v",err)
return
}
var post Post
xml.Unmarshal(bytes,&post)
fmt.Println(post)
}
上面的這種方法可以很好的處理體積較小的 XML 檔案,但是卻無法高效地處理以流方式傳輸的 XML 檔案以及體積較大的 XML 檔案。為了解決這個問題,我們需要使用 Decoder 結構來替代 Unmarshal 函式,通過手動解碼 XML 元素的方式來解封 XML 資料。
package main
import (
"encoding/xml"
"fmt"
"io"
"log"
"os"
)
type Post struct {
XMLName xml.Name `xml:"post"`
Id string `xml:"id,attr"`
Author Author `xml:"author"`
Xml string `xml:",innerxml"`
Comments []Comment `xml:"comments>comment"`
}
type Author struct {
Id string `xml:"id,attr"`
Name string `xml:",chardata"`
}
type Comment struct {
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
}
func main() {
file, err := os.Open("src/text/xml/post.xml")
if err != nil {
log.Fatalf("Error opening XML file %v",err)
return
}
defer file.Close()
decoder := xml.NewDecoder(file) //根據給定的XML資料生成相應的解碼器
for {
t, err := decoder.Token() //每進行一次迭代,就從解碼器獲取一個token
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("Error decoding XML into tokens %v",err)
}
switch se := t.(type) { //檢查token的型別
case xml.StartElement:
if se.Name.Local == "comment" {
var comment Comment
decoder.DecodeElement(&comment,&se) //將XML資料解析至結構
fmt.Println(comment)
}
}
}
}
二、建立 XML
package main
import (
"encoding/xml"
"io/ioutil"
"log"
)
type Post struct {
XMLName xml.Name `xml:"post"`
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
Xml string `xml:",innerxml"`
Comments []Comment `xml:"comments>comment"`
}
type Author struct {
Id string `xml:"id,attr"`
Name string `xml:",chardata"`
}
type Comment struct {
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
}
func main() {
post := Post{
Id:"1",
Content:"Hello World!",
Author:Author{
Id:"2",
Name:"Sau Sheong",
},
Comments: []Comment{{
Id:"1",
Content:"i love sz",
Author:Author{
Id:"3",
Name:"zhu",
},
}},
}
output, err := xml.MarshalIndent(&post,"","\t") //生成段落式的XML
if err != nil {
log.Fatalf("Error marshalling to XML %v",err)
return
}
err = ioutil.WriteFile("post2.xml", []byte(xml.Header+string(output)), 0644) //新增XML宣告
if err != nil {
log.Fatalf("Error writing XML to file %v",err)
return
}
}
我們可以看一下生成的 post2.xml 檔案中的 xml 資料
<?xml version="1.0" encoding="UTF-8"?>
<post id="1">
<content>Hello World!</content>
<author id="2">Sau Sheong</author>
<comments>
<comment id="1">
<content>i love sz</content>
<author id="3">zhu</author>
</comment>
</comments>
</post>
正如我們可以手動將 XML 解碼到 Go 結構裡面一樣,我們同樣也可以手動將 Go 結構編碼到 XML 裡面。
package main
import (
"encoding/xml"
"log"
"os"
)
type Post struct {
XMLName xml.Name `xml:"post"`
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
Xml string `xml:",innerxml"`
Comments []Comment `xml:"comments>comment"`
}
type Author struct {
Id string `xml:"id,attr"`
Name string `xml:",chardata"`
}
type Comment struct {
Id string `xml:"id,attr"`
Content string `xml:"content"`
Author Author `xml:"author"`
}
func main() {
post := Post{
Id:"1",
Content:"Hello World!",
Author:Author{
Id:"2",
Name:"Sau Sheong",
},
Comments: []Comment{{
Id:"1",
Content:"i love sz",
Author:Author{
Id:"3",
Name:"zhu",
},
}},
}
xmlFile, err := os.Create("post3.xml")
if err != nil {
log.Fatalf("Error creating XML File %v",err)
return
}
encoder := xml.NewEncoder(xmlFile)
encoder.Indent("","\t")
err = encoder.Encode(&post)
if err != nil {
log.Fatalf("Error encoding XML to file %v",err)
return
}
}
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 通過Go來分析和建立JSONGoJSON
- 通過MySQL儲存原理來分析排序和鎖MySql排序
- 在Go和Python之間通過ActiveMQ通訊GoPythonMQ
- 通過Go語言建立CA與簽發證書Go
- 通過了解RejectedExecutionException來分析ThreadPoolExecutor原始碼Exceptionthread原始碼
- SpringBoot通過yml和xml檔案配置日誌輸出Spring BootXML
- php建立XMLPHPXML
- go 解析xmlGoXML
- GO語言————6.12 通過記憶體快取來提升效能Go記憶體快取
- Mybatis原始碼分析(三)通過例項來看typeHandlersMyBatis原始碼
- 3、Spring Cloud Rest工程建立(通過IDEA建立)SpringCloudRESTIdea
- myeclipse下通過maven建立springbootEclipseMavenSpring Boot
- XML基本操作-建立(DOM和LOINQ)和LINQ查詢和儲存XML
- 建立mapper.xml方法APPXML
- 2.3 通過DBCA建立資料庫資料庫
- 1.3.2.1.2.1. 通過快照方式建立PDB
- 1.3.2.3. 通過Relocating方式建立PDB
- 通過抓包分析 HTTPSHTTP
- 1.3.2.1.1. 通過種子Seed建立PDB
- 1.3.2.1. 通過克隆Cloning方式建立PDB
- Go xml檔案處理GoXML
- Netty NioEventLoop 建立過程原始碼分析NettyOOP原始碼
- 通過分析LinkedHashMap瞭解LRUHashMap
- jmeter通過cookies來登入JMeterCookie
- 把list集合的內容寫入到Xml中,通過XmlDocument方式寫入Xml檔案中XML
- 深入理解 c# 第十四章 一個通過 ExpandoObject實現簡單XML DOM 變換 建立DOM樹C#ObjectXML
- 【譯】Flutter PlatformView: 如何通過原生view建立widgetFlutterPlatformView
- 通過驅動建立與MySQL的連線MySql
- 通過Go實現AES加密和解密工具Go加密解密
- 通過原始碼分析Mybatis的功能原始碼MyBatis
- 通過外來鍵找主鍵
- 通過信鴿來解釋 HTTPSHTTP
- 通過IO模型帶來的思考模型
- 通過編寫指令碼和程式來擴充套件SSIS包NZ指令碼套件
- 通過貝葉斯公式來評估功能難度和返工率公式
- SAP RETAIL 通過分配表建立UB STO單據AI
- Laravel 通過遷移指令碼建立MySQL檢視Laravel指令碼MySql
- 圖解Flutter建立Isolate的過程及通訊圖解Flutter