欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang進行xml文件解析的操作方法

 更新時間:2024年11月09日 16:54:53   作者:辛巴克  
本文介紹了Go語言中解析XML文件的幾種方法:小文件解析、大文件流式解析和復(fù)雜結(jié)構(gòu)解析,對于小文件,使用標(biāo)準(zhǔn)庫中的encoding/xml包;對于大文件,采用流式解析以避免內(nèi)存溢出,對于復(fù)雜結(jié)構(gòu)的XML文件,推薦使用第三方庫github.com/beevik/etree

查閱了些資料自己記錄一下

一、小文件簡單解析

對于小文件的 XML 解析,我們可以使用 Go 標(biāo)準(zhǔn)庫中的encoding/xml包來實現(xiàn)。

假設(shè)我們有一個名為demo.xml的文件,內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<config>
   <smtpServer>smtp.163.com</smtpServer>
   <smtpPort>25</smtpPort>
   <sender>user@163.com</sender>
   <senderPasswd>123456</senderPasswd>
   <receivers flag="true">
     <age>16</age>
     <user>Mike_Zhang@live.com</user>
     <user>test1@qq.com</user>
     <script>
     <![CDATA[
        function matchwo(a,b) {
            if (a < b && a < 0) then {
                return 1;
            } else {
                return 0;
            }
        }
        ]]>
     </script>
  </receivers>
 </config>

對應(yīng)的main.go文件代碼如下:

package main
import (
	"fmt"
	"io/ioutil"
	"encoding/xml"
)
// 定義結(jié)構(gòu)體來映射 XML 結(jié)構(gòu)
type SConfig struct {
	XMLName    xml.Name `xml:"config"`
	SmtpServer string   `xml:"smtpServer"`
	SmtpPort   int      `xml:"smtpPort"`
	Sender     string   `xml:"sender"`
	SenderPasswd string   `xml:"senderPasswd"`
	Receivers  SReceivers `xml:"receivers"`
}
type SReceivers struct {
	Age    int      `xml:"age"`
	Flag   string   `xml:"flag,attr"`
	User   []string `xml:"user"`
	Script string   `xml:"script"`
}
func readXml(path string) {
	// 直接讀取文件內(nèi)容,ioutil 內(nèi)部處理打開和關(guān)閉操作
	data, err := ioutil.ReadFile(path)
	if err!= nil {
		fmt.Println("讀文件出錯!", err)
		return
	}
	// 初始化結(jié)構(gòu)體變量
	v := SConfig{}
	err = xml.Unmarshal(data, &v)
	if err!= nil {
		fmt.Printf("error: %v", err)
		return
	}
	// 打印解析后的結(jié)果
	fmt.Println("SmtpServer : ", v.SmtpServer)
	fmt.Println("SmtpPort : ", v.SmtpPort)
	fmt.Println("Sender : ", v.Sender)
	fmt.Println("SenderPasswd : ", v.SenderPasswd)
	fmt.Println("Receivers.Flag : ", v.Receivers.Flag)
	fmt.Println("Receivers.Age : ", v.Receivers.Age)
	fmt.Println("Receivers.Script : ", v.Receivers.Script)
	for i, element := range v.Receivers.User {
		fmt.Println(i, element)
	}
}
func main() {
	readXml("demo.xml")
}

運行這段代碼后,輸出如下:

SmtpServer :  smtp.163.com
SmtpPort :  25
Sender :  user@163.com
SenderPasswd :  123456
Receivers.Flag :  true
Receivers.Age :  16
Receivers.Script :

        function matchwo(a,b) {
            if (a < b && a < 0) then {
                return 1;
            } else {
                return 0;
            }
        }

0 Mike_Zhang@live.com
1 test1@qq.com

二、大文件解析

當(dāng)處理較大的 XML 文件時,我們可以采用流式解析的方式,以避免一次性將整個文件加載到內(nèi)存中。

同樣以demo.xml文件為例,內(nèi)容不變。

main.go文件代碼如下:

package main
import (
	"fmt"
	"encoding/xml"
	"bufio"
	"os"
	"io"
)
// 定義結(jié)構(gòu)體來映射 XML 結(jié)構(gòu)
type SConfig struct {
	XMLName    xml.Name `xml:"config"`
	SmtpServer string   `xml:"smtpServer"`
	SmtpPort   int      `xml:"smtpPort"`
	Sender     string   `xml:"sender"`
	SenderPasswd string   `xml:"senderPasswd"`
	Receivers  SReceivers `xml:"receivers"`
}
type SReceivers struct {
	Age    int      `xml:"age"`
	Flag   string   `xml:"flag,attr"`
	User   []string `xml:"user"`
	Script string   `xml:"script"`
}
func readXml(path string) {
	// 打開文件
	file, errOpen := os.Open(path)
	if errOpen!= nil {
		fmt.Println("打開文件異常!", errOpen)
		return
	}
	defer file.Close()
	// 創(chuàng)建帶緩存的 Reader
	reader := bufio.NewReader(file)
	decoder := xml.NewDecoder(reader)
	for t, err := decoder.Token(); err == nil || err == io.EOF; t, err = decoder.Token() {
		switch token := t.(type) {
		case xml.StartElement:
			name := token.Name.Local
			fmt.Println(name)
			if name == "config" {
				// 解析 config 
				var sConfig = SConfig{}
				configErr := decoder.DecodeElement(&sConfig, &token)
				if configErr!= nil {
					fmt.Println("解析錯誤:")
					fmt.Println(configErr)
				} else {
					fmt.Println(sConfig)
				}
				return
			}
		}
	}
}
func main() {
	readXml("demo.xml")
}

輸出結(jié)果為:

config
{{ config} smtp.163.com 25 user@163.com 123456 {16 true [Mike_Zhang@live.com test1@qq.com]

        function matchwo(a,b) {
            if (a < b && a < 0) then {
                return 1;
            } else {
                return 0;
            }
        }

     }}

三、復(fù)雜結(jié)構(gòu)解析

對于復(fù)雜結(jié)構(gòu)的 XML 文件,我們可以使用第三方庫github.com/beevik/etree來進行解析。

假設(shè)我們有一個名為bookstores.xml的文件,內(nèi)容如下:

<bookstore xmlns:p="urn:schemas-books-com:prices">
  <book category="COOKING">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <p:price>30.00</p:price>
  </book>
  <book category="CHILDREN">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <p:price>29.99</p:price>
  </book>
  <book category="WEB">
    <title lang="en">XQuery Kick Start</title>
    <author>James McGovern</author>
    <author>Per Bothner</author>
    <author>Kurt Cagle</author>
    <author>James Linn</author>
    <author>Vaidyanathan Nagarajan</author>
    <year>2003</year>
    <p:price>49.99</p:price>
  </book>
  <book category="WEB">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <p:price>39.95</p:price>
  </book>
</bookstore>

main.go文件代碼如下:

package main
import (
	"fmt"
	"github.com/beevik/etree"
)
func readXml(path string) {
	doc := etree.NewDocument()
	if err := doc.ReadFromFile(path); err!= nil {
		panic(err)
	}
	root := doc.SelectElement("bookstore")
	fmt.Println("ROOT element:", root.Tag)
	for _, book := range root.SelectElements("book") {
		fmt.Println("CHILD element:", book.Tag)
		if title := book.SelectElement("title"); title!= nil {
			lang := title.SelectAttrValue("lang", "unknown")
			fmt.Printf("  TITLE: %s (%s)\n", title.Text(), lang)
		}
		for _, attr := range book.Attr {
			fmt.Printf("  ATTR: %s=%s\n", attr.Key, attr.Value)
		}
	}
}
func main() {
	readXml("bookstores.xml")
}

輸出結(jié)果為:

ROOT element: bookstore
CHILD element: book
  TITLE: Everyday Italian (en)
  ATTR: category=COOKING
CHILD element: book
  TITLE: Harry Potter (en)
  ATTR: category=CHILDREN
CHILD element: book
  TITLE: XQuery Kick Start (en)
  ATTR: category=WEB
CHILD element: book
  TITLE: Learning XML (en)
  ATTR: category=WEB

使用流數(shù)據(jù)進行解析xml文件如果所包含標(biāo)簽存在會有字段讀取丟失清空這種情況進行如下編寫

package main
import (
    "encoding/xml"
    "fmt"
    "io"
    "os"
)
// 定義結(jié)構(gòu)體來映射HTML片段中的pre標(biāo)簽
type HTMLPre struct {
    XMLName xml.Name `xml:"htmlpre"`
    Text    string   `xml:",innerxml"`
}
// 定義結(jié)構(gòu)體來映射Rule元素
type XCCDFRule struct {
    XMLName    xml.Name `xml:"Rule"`
    ID         string   `xml:"id,attr"`
    Title      string   `xml:"title"`
    Description string   `xml:"description"`
    HTMLPre    []HTMLPre `xml:"htmlpre"`
}
func parseRule(reader io.Reader) (*XCCDFRule, error) {
    decoder := xml.NewDecoder(reader)
    decoder.Strict = false
    decoder.AutoClose = xml.HTMLAutoClose
    decoder.Entity = xml.HTMLEntity
    var rule XCCDFRule
    for {
        token, err := decoder.Token()
        if err == io.EOF {
            break
        } else if err!= nil {
            return nil, err
        }
        switch se := token.(type) {
        case xml.StartElement:
            if se.Name.Local == "Rule" {
                if err := decoder.DecodeElement(&rule, &se); err!= nil {
                    return nil, err
                }
                // 進一步解析description中的HTML內(nèi)容
                if err!= nil {
                    return nil, err
                }
                return &rule, nil
            }
        }
    }
    return nil, fmt.Errorf("Rule element not found")
}
func main() {
    file, err := os.Open("your_file.xml")
    if err!= nil {
        fmt.Println("打開文件錯誤:", err)
        return
    }
    defer file.Close()
    rule, err := parseRule(file)
    if err!= nil {
        fmt.Println("解析錯誤:", err)
        return
    }
    fmt.Printf("規(guī)則ID: %s\n", rule.ID)
    fmt.Printf("規(guī)則標(biāo)題: %s\n", rule.Title)
    fmt.Printf("規(guī)則描述: %s\n", rule.Description)
}

在這個改進后的代碼中:

  • 定義了HTMLPre結(jié)構(gòu)體來映射<htmlpre>標(biāo)簽的內(nèi)容,包括標(biāo)簽內(nèi)的文本(使用xml:",innerxml"來獲取標(biāo)簽內(nèi)的所有XML內(nèi)容作為字符串)。
  • XCCDFRule結(jié)構(gòu)體中添加了HTMLPre字段來存儲解析后的<htmlpre>標(biāo)簽內(nèi)容列表。
  • parseRule函數(shù)中,解碼Rule元素后,調(diào)用parseDescription函數(shù)來進一步解析description字段中的HTML內(nèi)容,提取<htmlpre>標(biāo)簽內(nèi)的文本并存儲到rule.HTMLPre列表中。
  • parseDescription函數(shù)創(chuàng)建了一個新的XML解析器來解析description字符串中的內(nèi)容,專門查找<html:pre>標(biāo)簽并解碼其內(nèi)容。

請注意,這只是一種處理方式,根據(jù)你的實際需求,可能需要進一步調(diào)整和擴展代碼來處理XML中更復(fù)雜的HTML嵌套結(jié)構(gòu)或其他類型的內(nèi)容。同時,將"your_file.xml"替換為實際的XML文件路徑。

到此這篇關(guān)于golang進行xml文件解析的文章就介紹到這了,更多相關(guān)golang xml文件解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • go嵌套匿名結(jié)構(gòu)體的初始化詳解

    go嵌套匿名結(jié)構(gòu)體的初始化詳解

    這篇文章主要介紹了go嵌套匿名結(jié)構(gòu)體的初始化詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • GO語言協(xié)程互斥鎖Mutex和讀寫鎖RWMutex用法實例詳解

    GO語言協(xié)程互斥鎖Mutex和讀寫鎖RWMutex用法實例詳解

    這篇文章主要介紹了GO語言協(xié)程互斥鎖Mutex和讀寫鎖RWMutex用法詳解,需要的朋友可以參考下
    2022-04-04
  • 玩轉(zhuǎn)Go命令行工具Cobra

    玩轉(zhuǎn)Go命令行工具Cobra

    這篇文章主要介紹了玩轉(zhuǎn)Go命令行工具Cobra,本文介紹了Cobra的最基本也是最常用的使用部分,但是Cobra仍然有很多優(yōu)秀的操作值得我們學(xué)習(xí),需要的朋友可以參考下
    2022-08-08
  • Go檢查結(jié)構(gòu)體中是否存在某個字段及創(chuàng)建結(jié)構(gòu)體切片或映射

    Go檢查結(jié)構(gòu)體中是否存在某個字段及創(chuàng)建結(jié)構(gòu)體切片或映射

    這篇文章主要為大家介紹了Go檢查結(jié)構(gòu)體中是否存在某個字段及創(chuàng)建結(jié)構(gòu)體切片或映射實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • 使用client-go工具調(diào)用kubernetes API接口的教程詳解(v1.17版本)

    使用client-go工具調(diào)用kubernetes API接口的教程詳解(v1.17版本)

    這篇文章主要介紹了使用client-go工具調(diào)kubernetes API接口(v1.17版本),本文通過圖文實例相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • GoLang橋接模式的實現(xiàn)示例

    GoLang橋接模式的實現(xiàn)示例

    橋接模式是一種結(jié)構(gòu)型設(shè)計模式,通過橋接模式可以將抽象部分和它的實現(xiàn)部分分離,本文主要介紹了GoLang橋接模式,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • GoLang?Time時間操作函數(shù)講解

    GoLang?Time時間操作函數(shù)講解

    在日常開發(fā)中,我們避免不了時間的使用,我們可能需要獲取當(dāng)前時間,然后格式化保存,也可能需要在時間類型與字符串類型之間相互轉(zhuǎn)換等。本文將會對?Go?time?包里面的常用函數(shù)和方法進行介紹,需要的可以參考一下
    2023-01-01
  • 使用Golang打印特定的日期時間的操作

    使用Golang打印特定的日期時間的操作

    這篇文章主要給大家詳細介紹了如何使用Golang打印特定的日期時間的操作,文中有詳細的代碼示例,具有一定的參考價值,需要的朋友可以參考下
    2023-07-07
  • 深入Golang的接口interface

    深入Golang的接口interface

    這篇文章主要介紹了深入Golang的接口interface,go不要求類型顯示地聲明實現(xiàn)了哪個接口,只要實現(xiàn)了相關(guān)的方法即可,編譯器就能檢測到,接下來關(guān)于接口interface的相關(guān)介紹需要的朋友可以參考下面文章內(nèi)容
    2022-06-06
  • go?zero微服務(wù)實戰(zhàn)處理每秒上萬次的下單請求

    go?zero微服務(wù)實戰(zhàn)處理每秒上萬次的下單請求

    這篇文章主要為大家介紹了go?zero微服務(wù)實戰(zhàn)處理每秒上萬次的下單請求示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07

最新評論