РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
1157 of 1593 menu

Интерфейс xml.Unmarshaler

Интерфейс xml.Unmarshaler позволяет определить собственный способ распаковки XML-данных в структуру. Он содержит единственный метод UnmarshalXML, который получает на вход указатель на декодер *xml.Decoder и начальный элемент xml.StartElement. Реализация этого метода полностью контролирует процесс чтения и парсинга XML-данных для конкретного типа.

Синтаксис

type Unmarshaler interface { UnmarshalXML(d *xml.Decoder, start xml.StartElement) error }

Пример

Давайте реализуем кастомную распаковку для структуры, которая содержит цену товара в виде строки:

package main import ( "encoding/xml" "fmt" "strings" ) type Price string func (p *Price) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { var value string if err := d.DecodeElement(&value, &start); err != nil { return err } // Убираем символ валюты и пробелы cleaned := strings.TrimSpace(strings.TrimSuffix(value, "$")) *p = Price(cleaned) return nil } type Product struct { XMLName xml.Name `xml:"product"` Name string `xml:"name"` Price Price `xml:"price"` } func main() { xmlData := `<product><name>Laptop</name><price>999$</price></product>` var product Product if err := xml.Unmarshal([]byte(xmlData), &product); err != nil { fmt.Println(err) return } fmt.Printf("Name: %s, Price: %s", product.Name, product.Price) }

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

"Name: Laptop, Price: 999"

Пример

Реализуем кастомную распаковку для структуры, которая обрабатывает атрибуты и вложенные элементы:

package main import ( "encoding/xml" "fmt" ) type User struct { ID int Name string IsAdmin bool } func (u *User) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { // Считываем атрибут id var id int for _, attr := range start.Attr { if attr.Name.Local == "id" { fmt.Sscanf(attr.Value, "%d", &id) u.ID = id } } // Считываем вложенные элементы var name, role string for { token, err := d.Token() if err != nil { return err } switch elem := token.(type) { case xml.StartElement: if elem.Name.Local == "name" { if err := d.DecodeElement(&name, &elem); err != nil { return err } u.Name = name } if elem.Name.Local == "role" { if err := d.DecodeElement(&role, &elem); err != nil { return err } u.IsAdmin = (role == "admin") } case xml.EndElement: if elem.Name == start.Name { return nil } } } } func main() { xmlData := `<user id="42"><name>John</name><role>admin</role></user>` var user User if err := xml.Unmarshal([]byte(xmlData), &user); err != nil { fmt.Println(err) return } fmt.Printf("ID: %d, Name: %s, IsAdmin: %t", user.ID, user.Name, user.IsAdmin) }

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

"ID: 42, Name: John, IsAdmin: true"

Пример

Используем кастомную распаковку для обработки списка элементов с возможностью пропуска некорректных данных:

package main import ( "encoding/xml" "fmt" "strconv" ) type PositiveInt int func (pi *PositiveInt) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { var value string if err := d.DecodeElement(&value, &start); err != nil { return err } num, err := strconv.Atoi(value) if err != nil || num <= 0 { // Устанавливаем значение по умолчанию для некорректных данных *pi = 1 return nil } *pi = PositiveInt(num) return nil } type Data struct { XMLName xml.Name `xml:"data"` Numbers []PositiveInt `xml:"number"` } func main() { xmlData := `<data><number>10</number><number>-5</number><number>abc</number><number>7</number></data>` var data Data if err := xml.Unmarshal([]byte(xmlData), &data); err != nil { fmt.Println(err) return } fmt.Println(data.Numbers) }

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

[10 1 1 7]
  • интерфейс xml.Marshaler,
    который определяет кастомную упаковку в XML
  • интерфейс json.Unmarshaler,
    который реализует кастомную распаковку JSON
  • функцию xml.Unmarshal,
    которая выполняет распаковку XML-данных
  • тип xml.Decoder,
    который используется для потокового чтения XML
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить