The etree package is a lightweight, pure go package that expresses XML in the form of an element tree. Its design was inspired by the Python ElementTree module. Some of the package's features include:
- Represents XML documents as trees of elements for easy traversal.
- Imports, serializes, modifies or creates XML documents from scratch.
- Writes and reads XML to/from files, byte slices, strings and io interfaces.
- Performs simple or complex searches with lightweight XPath-like query APIs.
- Auto-indents XML using spaces or tabs for better readability.
- Implemented in pure go; depends only on standard go libraries.
- Built on top of the go encoding/xml package.
The following example creates an XML document from scratch using the etree package and outputs its indented contents to 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:
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="style.xsl"?> <People> <!--These are all known people--> <Person name="Jon"/> <Person name="Sally"/> </People>
Suppose you have a file on disk called bookstore.xml containing the
following data:
<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>
This code reads the file's contents into an etree document.
doc := etree.NewDocument() if err := doc.ReadFromFile("bookstore.xml"); err != nil { panic(err) }
You can also read XML from a string, a byte slice, or an io.Reader.
This example illustrates several ways to access elements and attributes using etree selection queries.
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
This example uses etree's path functions to select all book titles that fall into the category of 'WEB'. The double-slash prefix in the path causes the search for book elements to occur recursively; book elements may appear at any level of the XML hierarchy.
for _, t := range doc.FindElements("//book[@category='WEB']/title") { fmt.Println("Title:", t.Text()) }
Output:
Title: XQuery Kick Start
Title: Learning XML
This example finds the first book element under the root bookstore element and outputs the tag and text of each of its child elements.
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
This example finds all books with a price of 49.99 and outputs their titles.
path := etree.MustCompilePath("./bookstore/book[p:price='49.99']/title") for _, e := range doc.FindElementsPath(path) { fmt.Println(e.Text()) }
Output:
XQuery Kick Start
Note that this example uses the FindElementsPath function, which takes as an argument a pre-compiled path object. Use precompiled paths when you plan to search with the same path more than once.
###Other features
These are just a few examples of the things the etree package can do. See the documentation for a complete description of its capabilities.
###Contributing
This project accepts contributions. Just fork the repo and submit a pull request!