Leer un archivo XML en Golang

Para leer XML en Go se describe su forma con structs y xml.Unmarshal los rellena. Es igual que con JSON: las etiquetas de cada campo dicen qué elemento o qué atributo le corresponde.

El archivo

usuarios.xml<usuarios>
    <usuario tipo="admin">
        <nombre>Juan</nombre>
        <correo>juan@ejemplo.com</correo>
    </usuario>
    <usuario tipo="consulta">
        <nombre>Pedro</nombre>
        <correo>pedro@ejemplo.com</correo>
    </usuario>
</usuarios>

Los structs y la lectura

type Usuarios struct {
	Lista []Usuario `xml:"usuario"`
}

type Usuario struct {
	Tipo     string `xml:"tipo,attr"`
	Nombre   string `xml:"nombre"`
	Correo   string `xml:"correo"`
	Telefono string `xml:"telefono"`
}

func main() {
	datos, err := os.ReadFile("usuarios.xml")
	if err != nil {
		log.Fatal(err)
	}
	var u Usuarios
	if err := xml.Unmarshal(datos, &u); err != nil {
		log.Fatal(err)
	}
	fmt.Println("usuarios:", len(u.Lista))
	for _, x := range u.Lista {
		fmt.Printf("  %-8s %-6s %s | teléfono: %q\n", x.Tipo, x.Nombre, x.Correo, x.Telefono)
	}
}
salidausuarios: 2
  admin    Juan   juan@ejemplo.com | teléfono: ""
  consulta Pedro  pedro@ejemplo.com | teléfono: ""

Las etiquetas

EtiquetaCorresponde a
xml:"nombre"el elemento hijo <nombre>
xml:"tipo,attr"el atributo tipo="…"
xml:"usuario" en un []Usuariotodos los <usuario>, en orden
xml:",chardata"el texto de dentro del propio elemento
xml:"datos>ciudad"un elemento anidado, saltándose el de en medio

Lo que falta no da error. El struct tiene un campo Telefono que el XML no trae, y se queda vacío sin aviso. Lo mismo pasa con un elemento que se llama distinto de la etiqueta por una errata. Si un campo es obligatorio, compruébalo tú después de leer.

XML mal formado

salidaXML mal formado: XML syntax error on line 1: element <nombre> closed by </usuarios>

Esto sí da error, con la línea y el motivo. La versión anterior de esta página leía el archivo con datos, _ := ioutil.ReadFile(…): ese guion bajo descarta el error, y si el archivo no existía, el programa seguía con unos datos vacíos y no decía nada. En Go, cada err se mira.

El XML de ejemplo anterior guardaba contraseñas en claro. Como ejemplo no hacía daño, pero no conviene acostumbrarse: las contraseñas no se guardan, se guarda su hash.

Más información en inglés: Read 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.