How Go encoding/xml Maps Struct Tags to XML

Go’s standard encoding/xml package relies on struct field tags using the xml key to define how struct fields marshal into XML data and unmarshal back into Go types. By specifying XML element names, directive flags such as attr or chardata, path traversal using the > operator, and exclusion rules, developers have fine-grained control over the generated XML structure without altering their Go data models.

Tag Syntax and Element Names

By default, an untagged exported field in a struct is encoded as an XML element using the struct field’s exact name. Adding an xml tag overrides this behavior:

type User struct {
    Name string `xml:"full_name"`
}

This struct encodes to <full_name>...</full_name>.

Mapping to Attributes

To map a field to an XML attribute rather than a child element, append ,attr to the tag definition:

type Item struct {
    ID    string `xml:"id,attr"`
    Value string `xml:"value"`
}

This generates:

<Item id="123">
    <value>Sample</value>
</Item>

Special Directives

The encoding/xml package supports several specific directives placed after the element name or standalone:

Nesting with the Path Operator (>)

You can create or unpack nested XML elements without declaring intermediary structs by using the > operator in the tag:

type Document struct {
    Author string `xml:"info>metadata>author"`
}

This automatically marshals and unmarshals the structure:

<Document>
    <info>
        <metadata>
            <author>Jane Doe</author>
        </metadata>
    </info>
</Document>

Controlling the Root Element with XMLName

To explicitly name the enclosing XML element for a struct, add a field named XMLName of type xml.Name:

type Response struct {
    XMLName xml.Name `xml:"api_response"`
    Status  string   `xml:"status"`
}

You can also specify a namespace URL before a space in the tag: xml:"http://example.com/ns api_response".

Anonymous and Embedded Structs

Fields of an embedded anonymous struct are handled as if they were declared directly in the outer struct, unless the embedded field is explicitly given an XML name tag, in which case it is wrapped in an element of that name.