Crear un archivo XML en Golang

Para escribir XML en Go se hace lo mismo que para leerlo, al revés: se define un struct con etiquetas y se convierte. El escape de caracteres especiales lo hace solo, y la cabecera <?xml …?> hay que ponerla tú.

El struct

type Usuario struct {
	XMLName xml.Name `xml:"usuario"`
	ID      int      `xml:"id,attr"`
	Nombre  string   `xml:"nombre"`
	Correo  string   `xml:"correo"`
	Notas   string   `xml:"notas,omitempty"`
}

u := Usuario{ID: 1, Nombre: "José & Cía", Correo: "jose@ejemplo.com"}
b, _ := xml.Marshal(u)
fmt.Println(string(b))
salida<usuario id="1"><nombre>José &amp; Cía</nombre><correo>jose@ejemplo.com</correo></usuario>

XMLName fija el nombre del elemento raíz; sin él, sería el del tipo, Usuario. Notas no aparece porque está vacío y tiene omitempty. Y el & sale escapado como &amp;: es lo que hace que el archivo sea válido aunque los datos traigan caracteres especiales.

A un archivo, con cabecera y sangría

f, err := os.Create("usuario.xml")
if err != nil {
	log.Fatal(err)
}
defer f.Close()

f.WriteString(xml.Header)
enc := xml.NewEncoder(f)
enc.Indent("", "  ")
if err := enc.Encode(u); err != nil {
	log.Fatal(err)
}
if err := enc.Close(); err != nil {
	log.Fatal(err)
}
usuario.xml<?xml version="1.0" encoding="UTF-8"?>
<usuario id="1">
  <nombre>José &amp; Cía</nombre>
  <correo>jose@ejemplo.com</correo>
</usuario>

xml.Header es la línea de la declaración, ya escrita como constante. El Encoder escribe directamente en el archivo, sin pasar por una cadena intermedia. Y la versión anterior de esta página escribía en /home/decodigo/Documentos/go/archivos/archivo.xml, una ruta que solo existía en un ordenador.

El prefijo de MarshalIndent

b, _ := xml.MarshalIndent(u, " ", "  ")
fmt.Printf("%q\n", string(b)[:20])
salida" <usuario id=\"1\">\n  "
El primer argumento de sangría no es la sangría: es un prefijo que se pone delante de cada línea. El ejemplo anterior pasaba " ", y el archivo resultante empezaba cada línea con un espacio de más, incluida la primera, delante de <usuario>. Lo normal es MarshalIndent(u, "", " "): prefijo vacío y dos espacios de sangría.

Más información en inglés: Create an XML file in Golang.

Todo el código se compiló y se ejecutó con Go 1.27 en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.