Тип xml.Decoder

Тип xml.Decoder представляет собой декодер XML-данных, который читает из заданного io.Reader. Он позволяет последовательно извлекать токены (элементы, символьные данные, комментарии) и декодировать их в структуры Go. Основной метод — Decode, который преобразует текущий XML-элемент в переданную структуру. Также доступен метод Token для низкоуровневого пошагового разбора.

Создание декодера

Декодер создается с помощью функции xml.NewDecoder, которая принимает io.Reader в качестве источника данных.

gopackage main

import (
  "encoding/xml"
  "fmt"
  "strings"
)

func main() {
  xmlData := strings.NewReader(`<person><name>John</name><age>30</age></person>`)
  decoder := xml.NewDecoder(xmlData)
  fmt.Printf("Decoder created: %T\n", decoder)
}

Результат выполнения кода:

go"Decoder created: *xml.Decoder"

Метод Decode

Метод Decode читает следующий XML-элемент и декодирует его в переданную структуру. Он возвращает ошибку, если декодирование невозможно. Если достигнут конец данных, возвращается io.EOF.

gopackage main

import (
  "encoding/xml"
  "fmt"
  "strings"
)

type Person struct {
  Name string `xml:"name"`
  Age  int  `xml:"age"`
}

func main() {
  xmlData := strings.NewReader(`<person><name>Alice</name><age>25</age></person>`)
  decoder := xml.NewDecoder(xmlData)

  var person Person
  err := decoder.Decode(&person)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  fmt.Printf("Name: %s, Age: %d\n", person.Name, person.Age)
}

Результат выполнения кода:

go"Name: Alice, Age: 25"

Метод Token

Метод Token возвращает следующий XML-токен (элемент, текст, комментарий и т.д.) в виде интерфейса xml.Token. Это позволяет выполнять пошаговый разбор и обрабатывать элементы вручную.

gopackage main

import (
  "encoding/xml"
  "fmt"
  "strings"
)

func main() {
  xmlData := strings.NewReader(`<root><item>one</item><item>two</item></root>`)
  decoder := xml.NewDecoder(xmlData)

  for {
    token, err := decoder.Token()
    if err != nil {
      break
    }

    switch elem := token.(type) {
    case xml.StartElement:
      fmt.Printf("Start element: %s\n", elem.Name.Local)
    case xml.EndElement:
      fmt.Printf("End element: %s\n", elem.Name.Local)
    case xml.CharData:
      content := strings.TrimSpace(string(elem))
      if content != "" {
        fmt.Printf("Char data: %s\n", content)
      }
    }
  }
}

Результат выполнения кода:

go"Start element: root"
"Start element: item"
"Char data: one"
"End element: item"
"Start element: item"
"Char data: two"
"End element: item"
"End element: root"

Метод DecodeElement

Метод DecodeElement декодирует XML-элемент, переданный как xml.StartElement, в структуру. Это полезно, когда вы уже получили начальный токен и хотите декодировать его отдельно.

gopackage main

import (
  "encoding/xml"
  "fmt"
  "strings"
)

type Item struct {
  ID   string `xml:"id,attr"`
  Data string `xml:",chardata"`
}

func main() {
  xmlData := strings.NewReader(`<items><item id="1">first</item><item id="2">second</item></items>`)
  decoder := xml.NewDecoder(xmlData)

  // Find the first item element
  for {
    token, err := decoder.Token()
    if err != nil {
      break
    }

    if start, ok := token.(xml.StartElement); ok && start.Name.Local == "item" {
      var item Item
      err := decoder.DecodeElement(&item, &start)
      if err != nil {
        fmt.Println("Error:", err)
        return
      }
      fmt.Printf("ID: %s, Data: %s\n", item.ID, item.Data)
      break
    }
  }
}

Результат выполнения кода:

go"ID: 1, Data: first"

Смотрите также

  • тип xml.Encoder,
    который используется для кодирования данных в XML
  • функцию xml.NewEncoder,
    которая создает новый кодировщик XML
  • функцию xml.NewDecoder,
    которая создает новый декодер XML из io.Reader
  • метод xml.Decoder.Decode,
    который декодирует следующий XML-элемент в структуру