Reading XML Documents in Go

Jun 17, 2013


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 (found here).

Here is the XML document we are going to read and de-serialize:

<straps>
    <strap key="CompanyName" value="NEWCO" />
    <strap key="UseEmail" value="true" />
</straps>

The first thing we need to do is define the structs we will use to map the document:

type XMLStrap struct {
    XMLName  xml.Name ̀ xml:"strap"̀
    Key      string   ̀ xml:"key,attr"̀
    Value    string   ̀ xml:"value,attr"̀
}

type XMLStraps struct {
    XMLName  xml.Name    ̀ xml:"straps"̀
    Straps   []XMLStrap ̀ xml:"strap"̀
}


There are two structs, one for the entire document (<straps>) and one for each individual child node (<strap>). 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.

These tag formats are specific to the decoding support inside the encoding/xml package. The tags map the nodes and attributes of the XML document to the struct.

The following code decodes the XML document and returns the array of strap nodes:

func ReadStraps(reader io.Reader) ([]XMLStrap, error) {
    var xmlStraps XMLStraps
    if err := xml.NewDecoder(reader).Decode(&xmlStraps); err != nil {
        return nil, err
    }

    return xmlStraps.Straps, nil
}

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.

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.

The following completes the sample code:

/*
straps.xml should be located in the default working directory

<straps>
    <strap key="CompanyName" value="NEWCO" />
    <strap key="UseEmail" value="true" />
</straps>
*/
package main

import (
    "encoding/xml"
    "fmt"
    "io"
    "os"
    "path/filepath"
)

type XMLStrap struct {
    XMLName  xml.Name ̀ xml:"strap"̀
    Key      string   ̀ xml:"key,attr"̀
    Value    string   ̀ xml:"value,attr"̀
}

type XMLStraps struct {
    XMLName  xml.Name    ̀ xml:"straps"̀
    Straps   []XMLStrap ̀ xml:"strap"̀
}

func ReadStraps(reader io.Reader) ([]XMLStrap, error) {
    var xmlStraps XMLStraps
    if err := xml.NewDecoder(reader).Decode(&xmlStraps); err != nil {
        return nil, err
    }

    return xmlStraps.Straps, nil
}

func main() {
    // Build the location of the straps.xml file
    // filepath.Abs appends the file name to the default working directly
    strapsFilePath, err := filepath.Abs("straps.xml")
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    // Open the straps.xml file
    file, err := os.Open(strapsFilePath)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    defer file.Close()

    // Read the straps file
    xmlStraps, err := ReadStraps(file)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    // Display The first strap
    fmt.Printf("Key: %s  Value: %s", xmlStraps[0].Key, xmlStraps[0].Value)
}

I hope this sample gets you started with reading XML documents for your Go applications.


Ultimate Go Programming LiveLessons

Ultimate Go Programming LiveLessons provides an intensive, comprehensive, and idiomatic view of the Go programming language. This course focuses on both the specification and implementation of the language, including topics ranging from language syntax, design, and guidelines to concurrency, testing, and profiling. This class is perfect for anyone who wants a jump-start in learning Go or wants a more thorough understanding of the language and its internals.

Learn more

Go Training

We have taught Go to thousands of developers all around the world since 2014. There is no other company that has been doing it longer and our material has proven to help jump start developers 6 to 12 months ahead of their knowledge of Go. We know what knowledge developers need in order to be productive and efficient when writing software in Go.

Our Go, Web and Data Science classes are perfect for both experienced and beginning engineers. We start every class from the beginning and get very detailed about the internals, mechanics, specification, guidelines, best practices and design philosophies. We cover a lot about "if performance matters" with a focus on mechanical sympathy, data oriented design, decoupling and writing production software.

Learn More

To learn about Corporate training events, options and special pricing please contact:

William Kennedy
ArdanLabs (www.ardanlabs.com)
bill@ardanlabs.com