Актуальность XML в 2022 году была бы под вопросом, но все еще остается много legacy систем, которые могут предоставлять данные в этом формате, поэтому нам приходится с ним работать.  XML популярен в travel индустрии. Например, GDS (международные системы бронирования, более подробно можно почитать о них в википедии) или информационная система Darwin ассоциации железнодорожных транспортных компаний Великобритании активно используют его. Поэтому, я надеюсь, что эта статья будет кому-то полезна. В ней рассмотрена пара подходов к парсингу xml в Golang: обычный и потоковый, пользовательский парсинг поля и работа с различными кодировками.  Мы будем использовать пакет encoding/xml из стандартной библиотеки. Если вы уже работали c encoding/json, то будет много похожего, но некоторые различия все же есть. Прежде всего нам понадобится описать go структуры, соответствующие xml файлам. Можно сделать это вручную c помощью структурных тегов (детальную информацию о том, как описывать теги для XML можно посмотреть в документации по методу Marshal). Но для скорости и простоты мы воспользуемся одним из многочисленных генераторов go структуры по xml, например https://github.com/miku/zek/ (обратите внимание, что есть онлайн версия этого генератора: https://www.onlinetool.io/xmltogo/). Если вы впервые сталкиваетесь с таким подходом, то рекомендую сначала ознакомиться, например, со статьей "Использование тегов структур в Go" Начнем с простого xml файла и обычного Unmarshal в golang структуру. Пример файла я взял с сайта w3schools. Напомню, что сначала нам понадобится описать go struct, соответствующую структуре xml. Чтобы сделать это мы будем использовать тэги структур (аналогично json, если ранее не работали с json в golang, то можете почитать об этом здесь и здесь, на русском здесь и здесь).  Давайте посмотрим на пример XML файла: И вот go структура, которая его описывает: Дальше все достаточно тривиально. Код для Unmarshal (парсинг из xml в golang структуру) будет выглядеть следующим образом: Соответственно Marshal (операция, обратная Unmarshal, из go структуры в xml): Полный текст программы вы можете посмотреть под катом и попробовать запустить по ссылке (обратите внимание, что мы используем MarshalIndent вместо Marshal – это функция позволяет вывести xml в более читаемом виде: добавить отступы и переносы строк.  Таким образом, здесь все просто, но есть пара проблем: в том случае, если xml файл большого размера, то нам понадобится большое количество оперативной памяти, и в том случае, если мы получаем файл по сети нам понадобится дождаться получения полного содержимого, прежде чем начать парсинг. Давайте рассмотрим второй подход, который нам позволит решить эти проблемы. Для потокового парсинга XML мы можем использовать тип Decoder, который позволяет парсить xml файл потоково и ожидает, что поток будет в кодировке UTF-8 (дословная цитата из документации: “A Decoder represents an XML parser reading a particular input stream. The parser assumes that its input is encoded in UTF-8.”) С полным текстом программы можно под катом и запустить по ссылке.   Давайте посмотрим на основные изменения в коде и разберем их подробнее: Сначала инстанцируется xml.Decoder с помощью функции xml.NewDecoder. Далее происходит итерация по токенам xml с помощью метода Token. Он возвращает тип Token или nil, если достигнут конец файла. Строго говоря, метод возвращает два значения: Token и ошибку, если она произошла. В случае достижения конца файла возвращается nil для Token и io.EOF в качестве ошибки. Тип xml.Token представляет собой интерфейс и объявлен как 'type Token any' (в свою очередь any объявлен как пустой интерфейс: 'type any = interface{}'). До введения дженериков в Golang xml.Token был объявлен как пустой интерфейс: 'type Token interface{}'. Таким образом, может содержать любой тип данных и, согласно документации, может быть одним из следующих типов: StartElement, EndElement, CharData, Comment, ProcInst или Directive. Нас будет интересовать только начало элемента, т.е. тип StartElement. Как только он нам встречается мы проверяем, что он является нодой “food”. Если это так, то декодируем в Go структуру с помощью метода Decode. Иногда требуется описать свой декодер для определенного поля. Часто такое бывает в случае парсинга даты, времени, либо enum-ов. Сделать это можно с помощью пользовательского типа данных, который должен реализовать интерфейс Unmarshaler пакета encoding/xml. Интерфейс содержит только один метод: UnmarshalXML, давайте посмотрим на пример его реализации: Коротко говоря, метод принимает на вход инстанс текущего xml.Decoder и xml элемент (мы уже использовали тип данных xml.StartElement в потоковом парсинге), которые используются для декодирования элемента в строку. После чего мы парсим строку в тип time.Time (используем свой шаблон формата даты: userDateFormat) и присваиваем значения ресиверу ud, предварительно преобразовав тип к userDate. Полный текст программы вы можете посмотреть под катом и попробовать запустить по ссылке.  Хотелось бы еще сказать несколько слов про кодировки в xml. Редко, но все же иногда вы можете столкнуться с кодировкой, отличной от UTF-8. На этот случай вы можете задать нужную кодировку с помощью поля CharsetReader у декодера, которое является функцией и ожидается, что будет конвертировать из кодировки xml файла в utf-8 (сигнатура: 'CharsetReader func(charset string, input io.Reader) (io.Reader, error)' ) Самый простой вариант задать CharsetEncoder – это использование NewReaderLabel из пакета x/net/html/charset. По переданному charset (он же label в сигнатуре NewReaderLabel) с помощью метода Lookup он находит соответствие кодировке из этой таблицы. Передаваемый параметр charset берется из encoding параметра xml файла. Код будет примерно такой: Полный код под катом, а запустить можно по ссылке. Обратите внимание, что задан 'encoding="windows-1251"' у XML и title в кодировке windows-1251.   В статье я постарался рассмотреть основные способы парсинга xml и некоторые  сопутствующие вопросы. Она не претендует на полноту и не является всеобъемлющей, но этого, обычно, оказывается вполне достаточно, чтобы решить большую часть типовых задач. Надеюсь, что данные примеры немного упростят кому-нибудь жизнь и ускорят вашу разработку. В следующем разделе оставлю некоторые полезные ссылки. https://pkg.go.dev/encoding/xml#Marshal - документация по методу Marshal, здесь можно почитать как описывать go структуры для xml https://www.digitalocean.com/community/tutorials/how-to-use-struct-tags-in-go-ru - про теги структур в Golang https://blog.kowalczyk.info/tools/xmltogo/ - онлайн генератор go структур по xml файлу https://habr.com/ru/company/vk/blog/463063/ - хорошая статья про интерфейсы в общем и про пустой интерфейс в частности