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ú.
También te puede interesar
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é & 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 &: 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é & 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 "
" ", 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.