XML
encoding/xml Marshal and Unmarshal, struct tags for element and attribute mapping, streaming with Encoder/Decoder, and handling namespaces.
The encoding/xml package encodes Go values to XML and decodes XML into Go values. Struct tags (xml:"name") control how Go fields map to XML elements and attributes.
Encode a struct to XML with xml.Marshal. The xml.Header constant provides the standard XML declaration. Use xml:",attr" to map a field to an XML attribute instead of a child element.
package main
import (
"encoding/xml"
"fmt"
)
type Book struct {
XMLName xml.Name `xml:"book"`
ID int `xml:"id,attr"`
Title string `xml:"title"`
Author string `xml:"author"`
}
func main() {
b := Book{ID: 1, Title: "The Go Programming Language", Author: "Donovan"}
out, err := xml.MarshalIndent(b, "", " ")
if err != nil {
panic(err)
}
fmt.Println(xml.Header + string(out))
}Decode XML into a struct with xml.Unmarshal. Fields without a tag use their lowercased name. Unknown elements are silently ignored by default.
package main
import (
"encoding/xml"
"fmt"
)
type Book struct {
XMLName xml.Name `xml:"book"`
ID int `xml:"id,attr"`
Title string `xml:"title"`
Author string `xml:"author"`
}
func main() {
data := []byte(`<book id="42"><title>The Go Programming Language</title><author>Donovan</author></book>`)
var b Book
if err := xml.Unmarshal(data, &b); err != nil {
panic(err)
}
fmt.Printf("ID:%d Title:%s Author:%s\n", b.ID, b.Title, b.Author)
}Use xml.Decoder for streaming. It reads tokens one at a time and avoids loading the full document into memory - essential for large XML files or feeds.
package main
import (
"encoding/xml"
"fmt"
"strings"
)
type Item struct {
Title string `xml:"title"`
}
func main() {
feed := `<feed><item><title>First</title></item><item><title>Second</title></item></feed>`
dec := xml.NewDecoder(strings.NewReader(feed))
for {
tok, err := dec.Token()
if err != nil {
break // io.EOF
}
if se, ok := tok.(xml.StartElement); ok && se.Name.Local == "item" {
var item Item
dec.DecodeElement(&item, &se)
fmt.Println(item.Title)
}
}
}In production
XML is common in enterprise integrations, SOAP services, and RSS/Atom feeds. encoding/xml handles straightforward cases well, but for large XML streams use xml.Decoder token-by-token to avoid loading the entire document into memory - a 500 MB XML export will OOM your service if passed to xml.Unmarshal. For namespace-heavy XML (SOAP envelopes, XHTML), embed xml.Name with the Space field to match qualified names precisely. When generating XML for third-party consumers, always test the output against their schema validator - whitespace, attribute ordering, and namespace prefixes can all cause rejections even when the data is structurally correct.
Enjoyed this? Get more essays on software craft delivered to your inbox.
Subscribe free