[![Build Status](https://travis-ci.org/beevik/etree.svg?branch=master)](https://travis-ci.org/beevik/etree) [![GoDoc](https://godoc.org/github.com/beevik/etree?status.svg)](https://godoc.org/github.com/beevik/etree) etree ===== 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](http://docs.python.org/2/library/xml.etree.elementtree.html) module. Some of the package's capabilities and features: * 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](http://golang.org/pkg/encoding/xml) package. ### Creating an XML document The following example creates an XML document from scratch using the etree package and outputs its indented contents to stdout. ```go 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 ``` ### Reading an XML file Suppose you have a file on disk called `bookstore.xml` containing the following data: ```xml Everyday Italian Giada De Laurentiis 2005 30.00 Harry Potter J K. Rowling 2005 29.99 XQuery Kick Start James McGovern Per Bothner Kurt Cagle James Linn Vaidyanathan Nagarajan 2003 49.99 Learning XML Erik T. Ray 2003 39.95 ``` This code reads the file's contents into an etree document. ```go 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`. ### Processing elements and attributes This example illustrates several ways to access elements and attributes using etree selection queries. ```go 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 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. ```go 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. ```go 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. ```go 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](http://godoc.org/github.com/beevik/etree) for a complete description of its capabilities. ### Contributing This project accepts contributions. Just fork the repo and submit a pull request!