go解析和生成XML
etree
etree包是一个轻量级的纯go包,它以元素树的形式表示XML。它的设计灵感来自Python ElementTree模块。
软件包的一些功能和特性:
将XML文档表示为便于遍历的元素树。
从头导入、序列化、修改或创建XML文档。
在文件、字节片、字符串和io接口之间写入和读取XML。
使用轻量级XPath-like查询API执行简单或复杂的搜索。
Auto-indentsXML使用空格或制表符以提高可读性。
在纯go中实现;仅依赖于标准go库。
基于xml编码构建。
安装方式
go get github.com/beevik/etree
创建XML文档
下面的示例使用etree包从头创建一个XML文档,并将其缩进的内容输出到stdout。
doc := etree.NewDocument() doc.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`) doc.CreateProcInst("xml-stylesheet", `type="text/xsl" href="style.xsl"`) people := doc.CreateElement("People") people.CreateComment("These are all known people") jon := people.CreateElement("Person") jon.CreateAttr("name", "Jon") sally := people.CreateElement("Person") sally.CreateAttr("name", "Sally") doc.Indent(2) doc.WriteTo(os.Stdout) Output: <?xmlversion="1.0"encoding="UTF-8"?> <?xml-stylesheettype="text/xsl"href="style.xsl"?> <People> <!--These are all known people--> <Person name="Jon"/> <Person name="Sally"/> </People>
读取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
Path queries
此示例使用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路径对象作为参数。如果计划使用同一路径多次搜索,请使用预编译路径。
Other features
这些只是etree包可以做的一些事情的例子。有关其功能的完整描述,请参阅文档。