Working with XML in Go (Golang): complete guide with examples
Go (Golang) offers built-in support for working with XML through the encoding/xml package. This package provides powerful tools for parsing (reading), generating (writing), and serializing data in XML format. Unlike JSON, XML requires a more strict structure and support for namespaces, which makes encoding/xml especially flexible.
In this article, we will thoroughly examine how to work with XML in Go: from basic unmarshalling (converting XML to Go structures) to creating complex XML documents with attributes and namespaces.
Basics: structures and XML tags
Special xml tags are used to map XML elements to Go structure fields. They define the element name, attributes, and behavior during serialization.
type Person struct { XMLName xml.Name `xml:"person"` ID int `xml:"id,attr"` Name string `xml:"name"` Age int `xml:"age"` Email string `xml:"email,omitempty"` Addresses []Address `xml:"address"`}
type Address struct { City string `xml:"city"` Street string `xml:"street"` ZipCode string `xml:"zip"`}xml:"person"— the name of the root element.xml:"id,attr"— the field becomes an element attribute.xml:"email,omitempty"— the field is omitted if empty.xml:"address"— the array will be serialized as multiple nested elements.
Parsing XML: Unmarshalling
The xml.Unmarshal function converts XML bytes into a Go structure. Let's look at an example with our Person type:
package main
import ( "encoding/xml" "fmt")
func main() { xmlData := `<person id="123"> <name>Ivan Petrov</name> <age>30</age> <email>ivan@example.com</email> <address> <city>Moscow</city> <street>Tverskaya, 1</street> <zip>101000</zip> </address></person>`
var p Person err := xml.Unmarshal([]byte(xmlData), &p) if err != nil { fmt.Printf("Parsing error: %v", err) return }
fmt.Printf("ID: %d", p.ID) fmt.Printf("Name: %s", p.Name) fmt.Printf("Age: %d", p.Age) fmt.Printf("City: %s", p.Addresses[0].City)}Program output:
ID: 123Name: Ivan PetrovAge: 30City: MoscowGenerating XML: Marshalling
To create XML from a structure, xml.Marshal or xml.MarshalIndent (with indentation) is used.
func main() { p := Person{ ID: 456, Name: "Anna Smirnova", Age: 25, Email: "anna@example.com", Addresses: []Address{ {City: "Saint Petersburg", Street: "Nevsky, 10", ZipCode: "191186"}, }, }
output, err := xml.MarshalIndent(p, "", " ") if err != nil { fmt.Printf("Serialization error: %v", err) return }
fmt.Println(string(output))}Result:
<person id="456"> <name>Anna Smirnova</name> <age>25</age> <email>anna@example.com</email> <address> <city>Saint Petersburg</city> <street>Nevsky, 10</street> <zip>191186</zip> </address></person>Working with Namespaces
XML namespaces are handled through the XMLName field with the xmlns attribute.
type Document struct { XMLName xml.Name `xml Also in library
Data Validation in C++: Libraries and Methods (libvalidate, nlohmann/json, Boost)
Clap — Powerful CLI Framework for Rust
PDF Generation in Go: Library Overview and Practical Guide
Machine Learning in Swift: Core ML, Create ML, TensorFlow Swift, and Turi Create