Working with XML in Go (Golang): encoding/xml package and alternatives

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction to XML Processing in Go



The Go language (Golang) provides a powerful and elegant way to work with XML through the standard encoding/xml package. This package implements a simple interface for reading (parsing) and writing (serializing) XML documents using struct annotations (struct tags). Unlike many other languages, Go does not require creating separate DOM or SAX parsers — you just need to describe the data structure, and the package will map XML tags to fields automatically.



In this article, we will thoroughly explore the main features of the encoding/xml package, starting from basic parsing and moving to advanced techniques: handling attributes, namespaces, streaming large files, and generating XML. We will also look at popular third-party libraries that can be useful in specific scenarios.



Basics: Parsing XML into Go Structures



The most common way to work with XML in Go is to deserialize (unmarshal) XML data into struct instances. This is done using the xml.Unmarshal() function. The key feature is the use of xml:"..." tags in the struct field declarations.



Simple Example: Parsing an RSS Feed



package main

import ( "encoding/xml" "fmt")

// Structure for an RSS itemtype RSS struct { XMLName xml.Name `xml:"rss"` Channel Channel `xml:"channel"`}

type Channel struct { Title string `xml:"title"` Description string `xml:"description"` Items []Item `xml:"item"`}

type Item struct { Title string `xml:"title"` Link string `xml:"link"` Description string `xml:"description"`}

func main() { data := `<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"> <channel> <title>Example Feed</title> <description>A sample RSS feed</description> <item> <title>First Post</title> <link>https://example.com/1</link> <description>This is the first post.</description> </item> </channel> </rss>`

var rss RSS err := xml.Unmarshal([]byte(data), &rss) if err != nil { panic(err) }

fmt.Printf("Channel: %s", rss.Channel.Title) fmt.Printf("Description: %s", rss.Channel.Description) for _, item := range rss.Channel.Items { fmt.Printf("- %s (%s)", item.Title, item.Link) }}


In this example, the xml:"rss" tag links the structure to the root element, and xml:"channel", xml:"item" link to nested elements. The XMLName field is optional but allows you to get the name of the root element.



Working with XML Attributes



XML attributes are handled using a special syntax in the tag: xml:"tag_name,attr". If the attribute is directly in the root element, xml:",attr" is used.



type Person struct {    XMLName xml.Name `xml:"person"`    ID      int      `xml:"id,attr"`    Name    string   `xml:"name"`    Age     int      `xml:"age,attr"`}

func main() { xmlData := `<person id="123" age="30"><name>Alice</name></person>` var p Person xml.Unmarshal([]byte(xmlData), &p) fmt.Printf("ID: %d, Name: %s, Age: %d", p.ID, p.Name, p.Age) // Output: ID: 123, Name: Alice, Age: 30}


Generating (Serializing) XML



To create XML from a structure, use the xml.Marshal() function or xml.MarshalIndent() for formatted output. The package automatically uses struct tags to generate correct element names and attributes.



type Book struct {    XMLName xml.Name `xml:"book"`    Title   string                    

Recommendations