当前位置: 代码网 > it编程>前端脚本>Golang > golang进行xml文件解析的操作方法

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

2024年11月25日 Golang 我要评论
查阅了些资料自己记录一下一、小文件简单解析对于小文件的 xml 解析,我们可以使用 go 标准库中的encoding/xml包来实现。假设我们有一个名为demo.xml的文件,内容如下:<?xm

查阅了些资料自己记录一下

一、小文件简单解析

对于小文件的 xml 解析,我们可以使用 go 标准库中的encoding/xml包来实现。

假设我们有一个名为demo.xml的文件,内容如下:

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

对应的main.go文件代码如下:

package main
import (
	"fmt"
	"io/ioutil"
	"encoding/xml"
)
// 定义结构体来映射 xml 结构
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) {
	// 直接读取文件内容,ioutil 内部处理打开和关闭操作
	data, err := ioutil.readfile(path)
	if err!= nil {
		fmt.println("读文件出错!", err)
		return
	}
	// 初始化结构体变量
	v := sconfig{}
	err = xml.unmarshal(data, &v)
	if err!= nil {
		fmt.printf("error: %v", err)
		return
	}
	// 打印解析后的结果
	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

二、大文件解析

当处理较大的 xml 文件时,我们可以采用流式解析的方式,以避免一次性将整个文件加载到内存中。

同样以demo.xml文件为例,内容不变。

main.go文件代码如下:

package main
import (
	"fmt"
	"encoding/xml"
	"bufio"
	"os"
	"io"
)
// 定义结构体来映射 xml 结构
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()
	// 创建带缓存的 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")
}

输出结果为:

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

     }}

三、复杂结构解析

对于复杂结构的 xml 文件,我们可以使用第三方库github.com/beevik/etree来进行解析。

假设我们有一个名为bookstores.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>

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

输出结果为:

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

使用流数据进行解析xml文件如果所包含标签存在会有字段读取丢失清空这种情况进行如下编写

package main
import (
    "encoding/xml"
    "fmt"
    "io"
    "os"
)
// 定义结构体来映射html片段中的pre标签
type htmlpre struct {
    xmlname xml.name `xml:"htmlpre"`
    text    string   `xml:",innerxml"`
}
// 定义结构体来映射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内容
                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("规则id: %s\n", rule.id)
    fmt.printf("规则标题: %s\n", rule.title)
    fmt.printf("规则描述: %s\n", rule.description)
}

在这个改进后的代码中:

  • 定义了htmlpre结构体来映射<htmlpre>标签的内容,包括标签内的文本(使用xml:",innerxml"来获取标签内的所有xml内容作为字符串)。
  • xccdfrule结构体中添加了htmlpre字段来存储解析后的<htmlpre>标签内容列表。
  • parserule函数中,解码rule元素后,调用parsedescription函数来进一步解析description字段中的html内容,提取<htmlpre>标签内的文本并存储到rule.htmlpre列表中。
  • parsedescription函数创建了一个新的xml解析器来解析description字符串中的内容,专门查找<html:pre>标签并解码其内容。

请注意,这只是一种处理方式,根据你的实际需求,可能需要进一步调整和扩展代码来处理xml中更复杂的html嵌套结构或其他类型的内容。同时,将"your_file.xml"替换为实际的xml文件路径。

到此这篇关于golang进行xml文件解析的文章就介绍到这了,更多相关golang xml文件解析内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com