Working with XML in Go: encoding/xml, libraries and examples

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

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: Moscow


Generating 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                    

Recommendations