Handling XML in Go
Daniel Hayes
Full-Stack Engineer · Leapcell

Key Takeaways
- The
encoding/xml
package in Go enables efficient XML parsing and generation. Unmarshal
andMarshal
functions simplify XML data processing with struct-based mapping.- Streaming with
xml.Decoder
is optimal for handling large XML files.
XML (eXtensible Markup Language) is a widely-used format for representing structured data. In Go, the standard library provides the encoding/xml
package, which offers comprehensive support for XML parsing and generation. This article explores how to work with XML in Go, covering both marshalling (encoding) and unmarshalling (decoding) processes.
Parsing XML with Unmarshal
To parse XML data into Go structures, we use the Unmarshal
function from the encoding/xml
package. This function decodes XML data into the specified struct, allowing for easy manipulation of the data within Go programs.
Here's an example:
package main import ( "encoding/xml" "fmt" "os" ) type Server struct { ServerName string `xml:"serverName"` ServerIP string `xml:"serverIP"` } type Servers struct { XMLName xml.Name `xml:"servers"` Version string `xml:"version,attr"` Svs []Server `xml:"server"` } func main() { file, err := os.Open("servers.xml") if err != nil { fmt.Printf("error: %v", err) return } defer file.Close() var servers Servers if err := xml.NewDecoder(file).Decode(&servers); err != nil { fmt.Printf("error: %v", err) return } fmt.Println(servers) }
In this example, the Servers
struct represents the root element of the XML, with an attribute version
and a slice of Server
structs. Each Server
contains serverName
and serverIP
elements. The xml
tags in the struct fields guide the unmarshalling process, mapping XML elements and attributes to struct fields.
Generating XML with Marshal
To generate XML from Go structures, the Marshal
or MarshalIndent
functions are used. These functions serialize Go structs into XML format.
Here's how to do it:
package main import ( "encoding/xml" "fmt" "os" ) type Server struct { ServerName string `xml:"serverName"` ServerIP string `xml:"serverIP"` } type Servers struct { XMLName xml.Name `xml:"servers"` Version string `xml:"version,attr"` Svs []Server `xml:"server"` } func main() { servers := &Servers{Version: "1"} servers.Svs = append(servers.Svs, Server{"Shanghai_VPN", "127.0.0.1"}) servers.Svs = append(servers.Svs, Server{"Beijing_VPN", "127.0.0.2"}) output, err := xml.MarshalIndent(servers, " ", " ") if err != nil { fmt.Printf("error: %v\n", err) return } os.Stdout.Write([]byte(xml.Header)) os.Stdout.Write(output) }
This code will produce the following XML:
<?xml version="1.0" encoding="UTF-8"?> <servers version="1"> <server> <serverName>Shanghai_VPN</serverName> <serverIP>127.0.0.1</serverIP> </server> <server> <serverName>Beijing_VPN</serverName> <serverIP>127.0.0.2</serverIP> </server> </servers>
The MarshalIndent
function is used here to produce indented (pretty-printed) XML output, making it more readable.
Handling Large XML Files
When dealing with large XML files, it's more efficient to use the xml.Decoder
for stream parsing. This approach allows for processing the XML data incrementally, reducing memory consumption.
Here's an example:
package main import ( "encoding/xml" "fmt" "os" ) type UserData struct { Name string `xml:"name"` Age int32 `xml:"age"` } func main() { file, err := os.Open("userdata.xml") if err != nil { fmt.Printf("error: %v\n", err) return } defer file.Close() decoder := xml.NewDecoder(file) for { token, err := decoder.Token() if err != nil { break } switch se := token.(type) { case xml.StartElement: if se.Name.Local == "user" { var user UserData if err := decoder.DecodeElement(&user, &se); err != nil { fmt.Printf("error: %v\n", err) continue } fmt.Printf("User: %+v\n", user) } } } }
In this example, the xml.Decoder
reads tokens from the XML file one at a time, allowing for efficient processing of large files without loading the entire content into memory.
Conclusion
Go's encoding/xml
package provides robust tools for both parsing and generating XML data. By leveraging struct tags and the package's functions, developers can effectively handle XML in their applications, whether dealing with small configurations or large datasets.
FAQs
Use xml.Unmarshal
or xml.NewDecoder().Decode()
with struct field tags.
MarshalIndent
formats XML with indentation for better readability.
Use xml.Decoder
for large files to process data efficiently in a stream.
We are Leapcell, your top choice for hosting Go projects.
Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:
Multi-Language Support
- Develop with Node.js, Python, Go, or Rust.
Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the Documentation!
Follow us on X: @LeapcellHQ