В настоящее время я работаю над дополнительным проектом, который позволит энтузиастам активного отдыха найти кемпинги на определенном расстоянии от места своего проживания. Чтобы собрать данные для кемпингов, мне нужно запросить веб-API XML и проанализировать результаты. Предположим, что ответ выглядит так:

В приведенном выше XML-коде нашим внешним элементом является палаточный лагерь, у которого есть имя, адрес и список удобств. По умолчанию пакет XML Go будет демаршалировать элементы в экспортированные поля структуры с одинаковыми именами, но в большинстве случаев имена элементов XML записываются в нижнем регистре. Чтобы обойти это, нам нужно добавить дополнительную информацию к нашим структурам данных, чтобы дать синтаксическому анализатору сопоставление элементов XML с полями структуры.

Теги XML

В пакете XML есть специальный набор тегов, которые можно использовать для определения того, как XML будет анализироваться в наших структурах. Структуры в Go могут иметь метаданные, прикрепленные к каждому определению поля в виде тегов. Тег - это строковый литерал, содержащий определение значения ключа, доступ к которому можно получить с помощью отражения. Здесь - хорошая статья на Stack Overflow, в которой теги обсуждаются более подробно.

Ниже приводится таблица большинства тегов XML, типов полей, в которые они могут быть демаршалированы, и их описания:

Преобразование в структуры данных

Чтобы получить доступ к данным в XML, давайте определим несколько структур с правильными тегами, которые мы можем передать синтаксическому анализатору:

В приведенных выше структурах мы использовали несколько типов тегов XML, которые будут определять, как данные неупорядочиваются в самой структуре. Многие из них просто сопоставляют имя элемента в нижнем регистре с именем экспортируемой структуры, но есть еще пара более интересных примеров, которые я хочу указать.

Первое - это поле Type в структуре Campground. Обратите внимание, что это атрибут элемента кемпинга в XML, поэтому для его анализа нам нужно было использовать тег xml:"type,attr" вместо простого тега xml:"type".

Второе, на что я хочу обратить внимание, - это поле Amenities. Здесь мы разворачиваем фрагмент Amenity структур, углубляясь в XML-элемент «Удобства» и находя все подэлементы «Удобства». Затем каждый из этих подэлементов сопоставляется со структурой Amenity, которая затем добавляется к слайсу. Это сопоставление подэлементов обрабатывается тегом xml:"amenities>amenity".

Поддержание чистоты

Эти структуры данных будут делать то, что нам нужно, но действительно ли нам нужна отдельная структура для каждого внутреннего элемента? Мы могли бы разместить поля Address на самом Campground, но мне нравится, как в настоящее время все поля привязаны к структуре Address. Что касается удобств, мы не можем быть уверены в том, сколько их будет для конкретного кемпинга, поэтому это исключает возможность размещения полей непосредственно на структуре Campground.

Наилучшим вариантом здесь было бы использование анонимных структур для устранения дополнительных структур, необходимых для Address и Amenity:

Это дает нам возможность анализировать результат XML без необходимости указывать множество структур.

Теперь, когда наши структуры реализованы, давайте проанализируем данные с помощью функции Unmarshal в пакете XML Go.

Здесь мы создаем пустую структуру и вызываем xml.Unmarshal с байтовым фрагментом XML и указателем на значение Campground, в которое мы хотим поместить данные.

Собираем все вместе

Давайте объединим все вместе в рабочем состоянии с помощью функции main, которая демаршалирует данные и выводит результат.

Также попробуйте запустить его в Go Playground!

Кредиты изображений:
- XML
- Gopher