Go语言实现对XML的读取和修改

 更新时间:2023年12月19日 15:43:04   作者:畱䶒  
这篇文章主要为大家详细介绍了Go语言实现对XML的读取和修改的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

前言

很久没有更新了,来水篇文章。这篇文章给大家介绍一下如何用Go来读取XML和修改XML。XML我就不多介绍了,相信大家都使用过,不了解的可以看下百度百科。

处理XML我们暂时不需要借助第三方库,使用Go标准库encoding包下的xml即可完成,“encoding/xml”。

读取XML

首先我们需要创建一个XML文件,模拟一个web平台的信息,需要协议、IP、端口号、用户名和密码、页面路径等信息。命名为web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<Web>
	<Protocol>https</Protocol>
	<Host>192.168.100.169</Host>
	<Port>8080</Port>
	<Account>
		<Username>admin</Username>
		<Password>123456</Password>
	</Account>
	<Link>
		<Login>/api/login</Login>
		<Index>/api/index/page</Index>
		<Setting>/api/self/setting</Setting>
	</Link>
</Web>

紧接着根据这个XML文件来编写对应的结构体树,需要注意的是我们需要在最上层的结构体中使用xml.Name字段来声明最外围标签的名称。

type WebContent struct {
	XML xml.Name `json:"Web" xml:"Web"`
	Protocol string `json:"protocol"`
	Host string `json:"host"`
	Port string `json:"port"`
	Account *Account `json:"account"`
	Link *Link `json:"link"`
}

type Account struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type Link struct {
	Login string `json:"login"`
	Index string `json:"index"`
	Setting string `json:"setting"`
}

声明号XML文件对应的结构体之后,我们对文件进行解析读取。首先读取整个文件,获取到文件的字节数组,再通过xml包提供的Unmarshal方法进行反序列化。

由于是示例代码,错误都没有进行处理,选择直接panic。需要注意的是文件路径的问题,如果提示找不到文件,可以使用文件的绝对路径,或者使用os.Getwd()获取程序运行的当前目录,再将文件拷贝到当前目录中。以下是完整示例代码。

package main

import (
	"encoding/xml"
	"fmt"
	"log"
	"os"
)

// 这里我使用的是绝对路径
const (
	XMLFilePath = "/Users/mac/Library/Application Support/JetBrains/GoLand2023.3/scratches/web.xml"
)

type WebContent struct {
	XMLName xml.Name `json:"Web" xml:"Web"`
	Protocol string `json:"protocol"`
	Host string `json:"host"`
	Port string `json:"port"`
	Account *Account `json:"account"`
	Link *Link `json:"link"`
}

type Account struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type Link struct {
	Login string `json:"login"`
	Index string `json:"index"`
	Setting string `json:"setting"`
}

func main() {
	readXMl()
}

func readXMl() {
	data, err := os.ReadFile(XMLFilePath)
	if err != nil {
		log.Fatalf("读取文件%v失败: %v\n", XMLFilePath, err)
	}

	w := new(WebContent)
	if err = xml.Unmarshal(data, &w); err != nil {
		log.Fatal("XML数据解析失败", err)
	}

	fmt.Println("------------------------------")
	fmt.Printf("Protocol: %v\nHost: %v\nPort: %v\nAccount:\n --Username: %v\n --Password: %v\nLink:\n --Login: %v\n --Index: %v\n --Setting: %v\n",
		w.Protocol, w.Host, w.Port, w.Account.Username, w.Account.Password, w.Link.Login, w.Link.Index,w.Link.Setting)
	fmt.Println("------------------------------")
}


/* 输出信息:
------------------------------
Protocol: http
Host: 192.168.100.169
Port: 80
Account:
 --Username: sysadmin
 --Password: sysadmin
Link:
 --Login: /api/login
 --Index: /api/index/page
 --Setting: /api/self/setting
------------------------------
*/

修改XML

修改XML文件中的某几个字段,首先需要使用os.Open方法打开文件,拿到实现了i o.Reader接口的文件流,然后调用Decode方法反序列化数据。

使用赋值方法修改数据,完成后通过xml.MarshalIndent方法来序列化XML数据,并控制前缀和缩进。

最后再覆写文件,完成修改操作。以下是示例代码。

func amendXML() {
	file, err := os.Open(XMLFilePath)
	if err != nil {
		log.Fatalf("打开文件%v失败: %v\n", XMLFilePath, err)
	}

	// 解析文件
	w := new(WebContent)
	if err = xml.NewDecoder(file).Decode(&w); err != nil {
		log.Fatal("解析文件失败:", err)
	}

	// 修改数据
	w.Protocol= "http"
	w.Account.Password = "123456"

	// 序列化XML数据,MarshalIndent后两个参数用来控制前缀和缩进
	xmlData, err := xml.MarshalIndent(w, "", "     ")
	if err != nil {
		log.Fatal(err)
	}

	// 覆写文件
	xmlData = append([]byte(xml.Header), xmlData...)
	if err = os.WriteFile(XMLFilePath, xmlData, 0777); err != nil {
		log.Fatal("覆写文件失败:",err)
	}
}

完整代码

以下是完整的代码,复制粘贴后,添加一个xml文件,修改文件路径后可直接运行

package main

import (
	"encoding/xml"
	"fmt"
	"log"
	"os"
)

const (
	XMLFilePath = "/Users/mac/Library/Application Support/JetBrains/GoLand2023.3/scratches/web.xml"
)

type WebContent struct {
	XMLName xml.Name `json:"Web" xml:"Web"`
	Protocol string `json:"protocol"`
	Host string `json:"host"`
	Port string `json:"port"`
	Account *Account `json:"account"`
	Link *Link `json:"link"`
}

type Account struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type Link struct {
	Login string `json:"login"`
	Index string `json:"index"`
	Setting string `json:"setting"`
}

func main() {
	readXML()
	amendXML()
	readXML()
}

func readXML() {
	data, err := os.ReadFile(XMLFilePath)
	if err != nil {
		log.Fatalf("读取文件%v失败: %v\n", XMLFilePath, err)
	}

	w := new(WebContent)
	if err = xml.Unmarshal(data, &w); err != nil {
		log.Fatal("XML数据解析失败", err)
	}

	fmt.Println("------------------------------")
	fmt.Printf("Protocol: %v\nHost: %v\nPort: %v\nAccount:\n --Username: %v\n --Password: %v\nLink:\n --Login: %v\n --Index: %v\n --Setting: %v\n",
		w.Protocol, w.Host, w.Port, w.Account.Username, w.Account.Password, w.Link.Login, w.Link.Index,w.Link.Setting)
	fmt.Println("------------------------------")
}

func amendXML() {
	file, err := os.Open(XMLFilePath)
	if err != nil {
		log.Fatalf("打开文件%v失败: %v\n", XMLFilePath, err)
	}

	// 解析文件
	w := new(WebContent)
	if err = xml.NewDecoder(file).Decode(&w); err != nil {
		log.Fatal("解析文件失败:", err)
	}

	// 修改数据
	w.Protocol= "http"
	w.Account.Password = "654321"

	// 序列化XML数据,MarshalIndent后两个参数用来控制前缀和缩进
	xmlData, err := xml.MarshalIndent(w, "", "     ")
	if err != nil {
		log.Fatal(err)
	}

	// 覆写文件
	xmlData = append([]byte(xml.Header), xmlData...)
	if err = os.WriteFile(XMLFilePath, xmlData, 0777); err != nil {
		log.Fatal("覆写文件失败:",err)
	}
}

执行输出

------------------------------
Protocol: https
Host: 192.168.100.169
Port: 80
Account:
 --Username: admin
 --Password: 123456
Link:
 --Login: /api/login
 --Index: /api/index/page
 --Setting: /api/self/setting
------------------------------
------------------------------
Protocol: http
Host: 192.168.100.169
Port: 80
Account:
 --Username: admin
 --Password: 654321
Link:
 --Login: /api/login
 --Index: /api/index/page
 --Setting: /api/self/setting
------------------------------

到此这篇关于Go语言实现对XML的读取和修改的文章就介绍到这了,更多相关Go读取和修改XML内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 用golang实现一个定时器任务队列实例

    用golang实现一个定时器任务队列实例

    golang中提供了2种定时器timer和ticker,分别是一次性定时器和重复任务定时器。这篇文章主要介绍了用golang实现一个定时器任务队列实例,非常具有实用价值,需要的朋友可以参考下
    2018-05-05
  • 解决GO编译时避免引入外部动态库的问题

    解决GO编译时避免引入外部动态库的问题

    最近碰到一个问题,有一个流量采集的组件中使用到了github.com/google/gopacket 这个库,这个库使用一切正常,但是唯独有一个缺点,编译后的二进制文件依赖于libpcap.so的动态库,这篇文章主要介绍了GO编译时避免引入外部动态库的解决方法,需要的朋友可以参考下
    2022-10-10
  • GO常见的错误99%程序员会遇到(解决方法)

    GO常见的错误99%程序员会遇到(解决方法)

    这篇文章主要介绍了GO常见的错误99%程序员会遇到,本文给出了解决方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-01-01
  • Go语言中如何进行数据库查询操作

    Go语言中如何进行数据库查询操作

    在Go语言中,与数据库交互通常通过使用数据库驱动来实现,Go语言支持多种数据库,如MySQL、PostgreSQL、SQLite等,每种数据库都有其对应的官方或第三方驱动,接下来通过本文给大家介绍Go语言中进行数据库查询操作方法,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • Go语言单元测试超详细解析

    Go语言单元测试超详细解析

    本文介绍了了Go语言单元测试超详细解析,测试函数分为函数的基本测试、函数的组测试、函数的子测试,进行基准测试时往往是对函数的算法进行测验,有时后一个算法在测试数据的基量不同时测试出的效果会不同我们需要对不同数量级的样本进行测试,下文需要的朋友可以参考下
    2022-02-02
  • golang模板template自定义函数用法示例

    golang模板template自定义函数用法示例

    这篇文章主要介绍了golang模板template自定义函数用法,结合实例形式分析了Go语言模板自定义函数的基本定义与使用方法,需要的朋友可以参考下
    2016-07-07
  • 使用go连接clickhouse方式

    使用go连接clickhouse方式

    这篇文章主要介绍了使用go连接clickhouse方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Go语言中普通函数与方法的区别分析

    Go语言中普通函数与方法的区别分析

    这篇文章主要介绍了Go语言中普通函数与方法的区别,以实例形式对比分析了普通函数与方法使用时的区别与相关技巧,需要的朋友可以参考下
    2015-02-02
  • Golang超全面讲解并发

    Golang超全面讲解并发

    goroutine 不是os线程、不是绿色线程(由语言运行时管理的线程),是协程。协程是一种非抢占式的简单并发子goroutine(函数、闭包或方法),也就是说,它们不能被中断。取而代之的是,协程有多个点,允许暂停或重新进入 —Go语言并发之道
    2022-06-06
  • Golang性能优化的技巧分享

    Golang性能优化的技巧分享

    性能优化的前提是满足正确可靠、简洁清晰等质量因素,针对 Go语言特性,本文为大家整理了一些Go语言相关的性能优化建议,感兴趣的可以了解一下
    2023-07-07

最新评论