官网地址:​https://github.com/beevik/etree​etree包是一个轻量级的纯go包,它以元素树的形式表示XML。它可以查找节点,轮询、生成XML文件。

一、创建XML文件

利用​etree.NewDocument()​​方法创建xml文件对象,示例代码如下:

//创建xml文件模版
func CreateXml(){
//创建xml文件对象
doc := etree.NewDocument()
//创建层级元素
rules := doc.CreateElement("rules")
bannedDependencies := rules.CreateElement("bannedDependencies")
excludes := bannedDependencies.CreateElement("excludes")
rule := excludes.CreateElement("exclude")
//元素内写入具体内容
rule.CreateText(config.GroupId + ":" + config.ArtifactId + ":" + reversalResult)

//设置文件缩进字符数
doc.Indent(2)
//写入文件流
fileBytes, err := doc.WriteToBytes()
if err != nil {
return nil, tracerr.Wrap(err)
}
fileReader := bytes.NewReader(fileBytes)

return fileReader, nil
}

输出结果

<rules>
<bannedDependencies>
<excludes>
<exclude>com.xxx:xxx:(, 2.0.0]</exclude>
<exclude>com.c2f.boot:c2f-boot-starter-rpc:(,3.0.0]</exclude>
</excludes>
</bannedDependencies>
</rules>

在使用​​CreateElement​​​创建层级元素A时,会返回这个元素A对应的对象a,用这个对象a再调用​​CreateElement​​创建层级元素B时,相当于创建了层级元素A的子元素B,这个规则在解析xml文件时也同样如此

二、读取XML文件

假设磁盘上有一个名为​​bookstore.xml​​的文件,其中包含以下数据:

<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>

此代码将文件内容读入etree文档。

doc := etree.NewDocument()
if err := doc.ReadFromFile("bookstore.xml"); err != nil {
panic(err)
}

还可以从字符串、字节片或​​io.Reader​​读取XML。

三、处理元素和属性

此示例说明了使用etree选择查询访问元素和属性的几种方法。

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)
}
}

Output:

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

四、路径查找

此示例使用etree的path函数选择属于“WEB”类别的所有图书标题。路径中的double-slash前缀导致递归地搜索book元素;book元素可能出现在XML层次结构的任何级别。

for _, t := range doc.FindElements("//book[@category='WEB']/title") {
fmt.Println("Title:", t.Text())
}

Output:

Title: XQuery Kick Start
Title: Learning XML

此示例在根bookstore元素下找到第一个book元素,并输出其每个子元素的标记和文本。

for _, e := range doc.FindElements("./bookstore/book[1]/*") {
fmt.Printf("%s: %s\n", e.Tag, e.Text())
}

Output:

title: Everyday Italian
author: Giada De Laurentiis
year: 2005
price: 30.00

此示例查找价格为49.99的所有书籍并输出其标题。

path := etree.MustCompilePath("./bookstore/book[p:price='49.99']/title")
for _, e := range doc.FindElementsPath(path) {
fmt.Println(e.Text())
}

Output:

XQuery Kick Start

注意,这个例子使用了FindElementsPath函数,它以pre-compiled路径对象作为参数。如果计划使用同一路径多次搜索,请使用预编译路径。