# Reading XML Documents in Go

- Published: June 17, 2013
- Author: William Kennedy
- URL: https://www.ardanlabs.com/blog/2013/06/reading-xml-documents-in-go.html

I was really surprised how easy it was to read an XML document using the encoding/xml package that comes with the standard library. The package works by defining structs that map the XML document. If you need more flexibility then use Gustavo Niemeyer's xmlpath package (<a href="http://godoc.org/launchpad.net/xmlpath" target="_blank">found here)</a>.<br />
<br />

Here is the XML document we are going to read and de-serialize:<br />
<br />
<div style="background-color: #efefef; font-family: 'Courier New', Courier, monospace; font-size: small; overflow-x: scroll; padding: 10px; white-space: nowrap;">
&lt;straps&gt;<br />
&nbsp; &nbsp; &lt;strap key=&quot;CompanyName&quot; value=&quot;NEWCO&quot; /&gt;<br />
&nbsp; &nbsp; &lt;strap key=&quot;UseEmail&quot; value=&quot;true&quot; /&gt;<br />
&lt;/straps&gt;</div>
<br />
The first thing we need to do is define the structs we will use to map the document:<br />
<br />
<div style="background-color: #efefef; font-family: 'Courier New', Courier, monospace; font-size: small; overflow-x: scroll; padding: 10px; white-space: nowrap;">
type XMLStrap struct {<br />
&nbsp; &nbsp; XMLName &nbsp;xml.Name &#768; xml:&quot;strap&quot;&#768; <br />
&nbsp; &nbsp; Key &nbsp; &nbsp; &nbsp;string &nbsp; &#768; xml:&quot;key,attr&quot;&#768; <br />
&nbsp; &nbsp; Value &nbsp; &nbsp;string &nbsp; &#768; xml:&quot;value,attr&quot;&#768; <br />
}<br />
<br />
type XMLStraps struct {<br />
&nbsp; &nbsp; XMLName &nbsp;xml.Name &nbsp; &nbsp;&#768; xml:&quot;straps&quot;&#768; <br />
&nbsp; &nbsp; Straps &nbsp; []XMLStrap &#768; xml:&quot;strap&quot;&#768; <br />
}<br />
</div>

<br />
There are two structs, one for the entire document (&lt;straps&gt;) and one for each individual child node (&lt;strap&gt;). If you look closely at the structs you may see something new. Each field has a tag associated with it. These tags are bound to each individual field. Go's reflect package allows you to access these tags.<br />
<br />
These tag formats are specific to the decoding support inside the encoding/xml&nbsp;package. The tags map the nodes and attributes of the XML document to the struct.<br />
<br />
The following code decodes the XML document and returns the array of strap nodes:<br />
<br />
<div style="background-color: #efefef; font-family: 'Courier New', Courier, monospace; font-size: small; overflow-x: scroll; padding: 10px; white-space: nowrap;">
func ReadStraps(reader io.Reader) ([]XMLStrap, error) {<br />
&nbsp; &nbsp; var xmlStraps XMLStraps<br />
&nbsp; &nbsp; if err :=&nbsp;xml.NewDecoder(reader).Decode(&amp;xmlStraps); err != nil {<br />
&nbsp; &nbsp; &nbsp; &nbsp; return nil, err<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; return xmlStraps.Straps, nil<br />
}
</div>
<br />
The function takes an io.Reader. We will be passing a os.File variable into this method. The function returns an array of pointers for each strap we read from the file.<br />
<br />
First we create a XMLStraps variable and get its address. Next we create a decoder using the xml.NewDecoder method passing the io.Reader object. Then we call Decode which reads the file and de-serializes the file into the XMLStraps variable. Then we just return the array of strap values.<br />
<br />
The following completes the sample code:<br />
<br />
<div style="background-color: #efefef; font-family: 'Courier New', Courier, monospace; font-size: small; overflow-x: scroll; padding: 10px; white-space: nowrap;">
/&#42;<br />
straps.xml should be located in the default working directory<br />
<br />
&lt;straps&gt;<br />
&nbsp; &nbsp; &lt;strap key=&quot;CompanyName&quot; value=&quot;NEWCO&quot; /&gt;<br />
&nbsp; &nbsp; &lt;strap key=&quot;UseEmail&quot; value=&quot;true&quot; /&gt;<br />
&lt;/straps&gt;<br />
&#42;/<br />
package main<br />
<br />
import (<br />
&nbsp; &nbsp; &quot;encoding/xml&quot;<br />
&nbsp; &nbsp; &quot;fmt&quot;<br />
&nbsp; &nbsp; &quot;io&quot;<br />
&nbsp; &nbsp; &quot;os&quot;<br />
&nbsp; &nbsp; &quot;path/filepath&quot;<br />
)<br />
<br />
type XMLStrap struct {<br />
&nbsp; &nbsp; XMLName &nbsp;xml.Name &#768; xml:&quot;strap&quot;&#768; <br />
&nbsp; &nbsp; Key &nbsp; &nbsp; &nbsp;string &nbsp; &#768; xml:&quot;key,attr&quot;&#768; <br />
&nbsp; &nbsp; Value &nbsp; &nbsp;string &nbsp; &#768; xml:&quot;value,attr&quot;&#768; <br />
}<br />
<br />
type XMLStraps struct {<br />
&nbsp; &nbsp; XMLName &nbsp;xml.Name &nbsp; &nbsp;&#768; xml:&quot;straps&quot;&#768; <br />
&nbsp; &nbsp; Straps &nbsp; []XMLStrap &#768; xml:&quot;strap&quot;&#768; <br />
}<br />
<br />
func ReadStraps(reader io.Reader) ([]XMLStrap, error) {<br />
&nbsp; &nbsp; var xmlStraps XMLStraps<br />
&nbsp; &nbsp; if err :=&nbsp;xml.NewDecoder(reader).Decode(&amp;xmlStraps); err != nil {<br />
&nbsp; &nbsp; &nbsp; &nbsp; return nil, err<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; return xmlStraps.Straps, nil<br />
}<br />
<br />
func main() {<br />
&nbsp; &nbsp; // Build the location of the straps.xml file<br />
&nbsp; &nbsp; // filepath.Abs appends the file name to the default working directly<br />
&nbsp; &nbsp; strapsFilePath, err := filepath.Abs(&quot;straps.xml&quot;)<br />
&nbsp; &nbsp; if err != nil {<br />
&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(err)<br />
&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; // Open the straps.xml file<br />
&nbsp; &nbsp; file, err := os.Open(strapsFilePath)<br />
&nbsp; &nbsp; if err != nil {<br />
&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(err)<br />
&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; defer file.Close()<br />
<br />
&nbsp; &nbsp; // Read the straps file<br />
&nbsp; &nbsp; xmlStraps, err := ReadStraps(file)<br />
&nbsp; &nbsp; if err != nil {<br />
&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(err)<br />
&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; // Display The first strap<br />
&nbsp; &nbsp; fmt.Printf(&quot;Key: %s &nbsp;Value: %s&quot;,&nbsp;xmlStraps[0].Key,&nbsp;xmlStraps[0].Value)<br />
}</div>
<br />
I hope this sample gets you started with reading XML documents for your Go applications.<br />
<br />
