Работа с XML в Go (Golang): пакет encoding/xml и альтернативы

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в обработку XML на языке Go

Язык Go (Golang) предоставляет мощный и элегантный способ работы с XML через стандартный пакет encoding/xml. Этот пакет реализует простой интерфейс для чтения (парсинга) и записи (сериализации) XML-документов, используя аннотации к структурам (struct tags). В отличие от многих других языков, Go не требует создания отдельных DOM- или SAX-парсеров — достаточно описать структуру данных, и пакет сам сопоставит XML-теги с полями.

В этой статье мы подробно разберём основные возможности пакета encoding/xml, начиная с базового парсинга и заканчивая продвинутыми техниками: обработкой атрибутов, пространств имён, потоковым чтением больших файлов и генерацией XML. Также рассмотрим популярные сторонние библиотеки, которые могут быть полезны в специфических сценариях.

Основы: парсинг XML в структуры Go

Самый распространённый способ работы с XML в Go — это десериализация (unmarshal) XML-данных в экземпляры структур. Для этого используется функция xml.Unmarshal(). Ключевая особенность — использование тегов xml:"..." в объявлении полей структуры.

Простой пример: парсинг RSS-ленты

package main

import (
    "encoding/xml"
    "fmt"
)

// Структура для элемента RSS
type RSS struct {
    XMLName xml.Name `xml:"rss"`
    Channel Channel  `xml:"channel"`
}

type Channel struct {
    Title       string    `xml:"title"`
    Description string    `xml:"description"`
    Items       []Item    `xml:"item"`
}

type Item struct {
    Title       string `xml:"title"`
    Link        string `xml:"link"`
    Description string `xml:"description"`
}

func main() {
    data := `<?xml version="1.0" encoding="UTF-8"?>
    <rss version="2.0">
        <channel>
            <title>Example Feed</title>
            <description>A sample RSS feed</description>
            <item>
                <title>First Post</title>
                <link>https://example.com/1</link>
                <description>This is the first post.</description>
            </item>
        </channel>
    </rss>`

    var rss RSS
    err := xml.Unmarshal([]byte(data), &rss)
    if err != nil {
        panic(err)
    }

    fmt.Printf("Канал: %s\n", rss.Channel.Title)
    fmt.Printf("Описание: %s\n", rss.Channel.Description)
    for _, item := range rss.Channel.Items {
        fmt.Printf("- %s (%s)\n", item.Title, item.Link)
    }
}

В этом примере тег xml:"rss" связывает структуру с корневым элементом, а xml:"channel", xml:"item" — с вложенными. Поле XMLName необязательно, но позволяет получить имя корневого элемента.

Работа с атрибутами XML

Атрибуты XML обрабатываются через специальный синтаксис в теге: xml:"имя_тега,attr". Если атрибут находится прямо в корневом элементе, используется xml:",attr".

type Person struct {
    XMLName xml.Name `xml:"person"`
    ID      int      `xml:"id,attr"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age,attr"`
}

func main() {
    xmlData := `<person id="123" age="30"><name>Alice</name></person>`
    var p Person
    xml.Unmarshal([]byte(xmlData), &p)
    fmt.Printf("ID: %d, Name: %s, Age: %d\n", p.ID, p.Name, p.Age)
    // Вывод: ID: 123, Name: Alice, Age: 30
}

Генерация (сериализация) XML

Для создания XML из структуры используется функция xml.Marshal() или xml.MarshalIndent() для форматированного вывода. Пакет автоматически использует теги структур для генерации правильных имён элементов и атрибутов.

type Book struct {
    XMLName xml.Name `xml:"book"`
    Title   string   `xml:"title"`
    Author  string   `xml:"author"`
    Year    int      `xml:"year,attr"`
}

func main() {
    book := Book{
        Title:  "The Go Programming Language",
        Author: "Donovan & Kernighan",
        Year:   2015,
    }

    output, _ := xml.MarshalIndent(book, "", "  ")
    fmt.Println(string(output))
}

Вывод:

<book year="2015">
  <title>The Go Programming Language</title>
  <author>                    

Рекомендаций