Go Gopher How to Go

XML (Extensible Markup Language) is a markup language for encoding documents in a format that is both human-readable and machine-readable. Go's encoding/xml package provides built-in support for encoding Go data structures to XML and decoding XML into Go structures using struct tags similar to JSON.

💡 Key Points

  • Use struct tags to control XML element names and attributes
  • XMLName field controls the root element name
  • Use xml.Marshal() to encode and xml.Unmarshal() to decode
  • The attr tag marks a field as an XML attribute
  • The chardata tag marks character data content
  • Use xml.Encoder and xml.Decoder for streaming
  • Support for namespaces, CDATA, comments, and processing instructions

Encoding to XML

Convert Go data structures to XML using xml.Marshal:

package main

import (
    "encoding/xml"
    "fmt"
)

type Person struct {
    XMLName xml.Name `xml:"person"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age"`
    Email   string   `xml:"email"`
}

func main() {
    p := Person{
        Name:   "Alice",
        Age:   30,
        Email: "alice@example.com",
    }
    
    xmlData, err := xml.MarshalIndent(p, "", "  ")
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    
    fmt. Println(xml.Header + string(xmlData))
}
Output:
<?xml version="1.0" encoding="UTF-8"?>
<person>
  <name>Alice</name>
  <age>30</age>
  <email>alice@example.com</email>
</person>

Decoding from XML

Parse XML into Go structures using xml.Unmarshal:

package main

import (
    "encoding/xml"
    "fmt"
)

type Person struct {
    XMLName xml.Name `xml:"person"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age"`
    Email   string   `xml:"email"`
}

func main() {
    xmlStr := `
    
        Bob
        25
        bob@example.com
    
    `
    
    var p Person
    err := xml.Unmarshal([]byte(xmlStr), &p)
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    
    fmt.Printf("Name: %s, Age:  %d, Email: %s\n", p.Name, p. Age, p.Email)
}
Output:
Name: Bob, Age: 25, Email: bob@example.com

XML Attributes and Nested Elements

XML supports attributes and nested structures:

package main

import (
    "encoding/xml"
    "fmt"
)

type Address struct {
    City    string `xml:"city"`
    Country string `xml:"country"`
}

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

func main() {
    p := Person{
        ID:   123,
        Name: "Charlie",
        Address: Address{
            City:    "New York",
            Country: "USA",
        },
    }
    
    xmlData, _ := xml.MarshalIndent(p, "", "  ")
    fmt.Println(xml. Header + string(xmlData))
}
Output:
<?xml version="1.0" encoding="UTF-8"?>
<person id="123">
  <name>Charlie</name>
  <address>
    <city>New York</city>
    <country>USA</country>
  </address>
</person>

Struct Tag Options

TagExampleDescription
Element Name` + "`xml:\"elementname\"`" + `Sets XML element name
Attribute` + "`xml:\"name,attr\"`" + `Field becomes an attribute
Character Data` + "`xml:\",chardata\"`" + `Field contains element content
CDATA` + "`xml:\",cdata\"`" + `Wrap content in CDATA section
Inner XML` + "`xml:\",innerxml\"`" + `Raw XML content
Comment` + "`xml:\",comment\"`" + `XML comment
Any Element` + "`xml:\",any\"`" + `Match any element
Omit Empty` + "`xml:\"name,omitempty\"`" + `Omit if zero value
Ignore Field` + "`xml:\"-\"`" + `Skip field entirely

XML Encoding Functions

FunctionSignatureUse Case
MarshalMarshal(v interface{}) ([]byte, error)Encode to compact XML
MarshalIndentMarshalIndent(v interface{}, prefix, indent string) ([]byte, error)Encode to formatted XML
UnmarshalUnmarshal(data []byte, v interface{}) errorDecode XML into struct
NewEncoderNewEncoder(w io.Writer) *EncoderCreate streaming encoder
NewDecoderNewDecoder(r io.Reader) *DecoderCreate streaming decoder

Type Mappings

Go TypeXML RepresentationNotes
booltrue/falseBoolean values
int, int8, int16, int32, int64Decimal numberInteger values
uint, uint8, uint16, uint32, uint64Decimal numberUnsigned integer values
float32, float64Decimal numberFloating-point values
stringCharacter dataText content
[]byteBase64-encodedBinary data
[]TMultiple elementsRepeated elements
structNested elementsComplex structures
*TElement or omittedOptional elements
xml.NameElement nameControls root element

Common XML Patterns

PatternCodeUse Case
With XML Headerxml. Header + string(xmlData)Include <? xml version=1.0?>
Stream Encodingxml.NewEncoder(w).Encode(v)Write directly to io.Writer
Stream Decodingxml.NewDecoder(r).Decode(&v)Read from io.Reader
Token-Based Parsingfor { token, _ := decoder.Token(); ... }Low-level XML parsing
Custom Marshalfunc (t T) MarshalXML(e *Encoder, start StartElement) errorCustom encoding logic
Custom Unmarshalfunc (t *T) UnmarshalXML(d *Decoder, start StartElement) errorCustom decoding logic
Namespace HandlingXMLName xml. Name `xml:\"http://example.com/ns elementname\"`Work with XML namespaces

XML Features

FeatureExampleDescription
AttributesID int `xml:\"id,attr\"`Add attributes to elements
Namespacesxml.Name{Space: \"http://...\", Local: \"name\"}XML namespace support
CDATA Sections` + "`xml:\",cdata\"`" + `Preserve special characters
Comments` + "`xml:\",comment\"`" + `XML comments
Processing Instructionsxml.ProcInstProcessing directives
Character EntitiesAutomatic escaping<, >, &, etc.
Directivesxml.DirectiveDOCTYPE and other directives