Интерфейс xml.Marshaler
Интерфейс xml.Marshaler из пакета encoding/xml позволяет
типам данных управлять своим преобразованием в XML.
Он содержит единственный метод MarshalXML, который
принимает указатель на xml.Encoder и начальный
элемент xml.StartElement, а возвращает ошибку.
Реализация этого метода дает полный контроль над
тем, как структура будет представлена в XML-формате.
Синтаксис
type Marshaler interface {
MarshalXML(e *Encoder, start StartElement) error
}
Базовый пример
Рассмотрим простую структуру, реализующую интерфейс
xml.Marshaler. В этом примере мы вручную
конструируем XML-элемент с атрибутами:
package main
import (
"encoding/xml"
"fmt"
"os"
)
type User struct {
ID int
Name string
}
func (u User) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name = xml.Name{Local: "user"}
start.Attr = []xml.Attr{
{Name: xml.Name{Local: "id"}, Value: fmt.Sprintf("%d", u.ID)},
}
err := e.EncodeToken(start)
if err != nil {
return err
}
err = e.EncodeElement(u.Name, xml.StartElement{Name: xml.Name{Local: "name"}})
if err != nil {
return err
}
return e.EncodeToken(start.End())
}
func main() {
user := User{ID: 1, Name: "Alice"}
output, err := xml.MarshalIndent(user, "", " ")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(output))
}
Результат выполнения кода:
<user id="1">
<name>Alice</name>
</user>
Пример со вложенными элементами
В этом примере мы создаем более сложную XML-структуру
с несколькими уровнями вложенности, используя методы
EncodeToken и EncodeElement для
построения иерархии:
package main
import (
"encoding/xml"
"fmt"
"os"
)
type Address struct {
City string
Country string
}
type Person struct {
FullName string
Location Address
}
func (p Person) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name = xml.Name{Local: "person"}
err := e.EncodeToken(start)
if err != nil {
return err
}
err = e.EncodeElement(p.FullName, xml.StartElement{Name: xml.Name{Local: "full_name"}})
if err != nil {
return err
}
err = e.EncodeElement(p.Location, xml.StartElement{Name: xml.Name{Local: "address"}})
if err != nil {
return err
}
return e.EncodeToken(start.End())
}
func main() {
person := Person{
FullName: "John Doe",
Location: Address{City: "New York", Country: "USA"},
}
output, err := xml.MarshalIndent(person, "", " ")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(output))
}
Результат выполнения кода:
<person>
<full_name>John Doe</full_name>
<address>
<City>New York</City>
<Country>USA</Country>
</address>
</person>
Пример с изменением имен полей
Реализация интерфейса позволяет изменить имена полей в XML, используя пользовательские теги или динамическое формирование имен:
package main
import (
"encoding/xml"
"fmt"
"os"
)
type Product struct {
ID int
Title string
Price float64
InStock bool
}
func (p Product) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name = xml.Name{Local: "product"}
err := e.EncodeToken(start)
if err != nil {
return err
}
err = e.EncodeElement(p.ID, xml.StartElement{Name: xml.Name{Local: "product_id"}})
if err != nil {
return err
}
err = e.EncodeElement(p.Title, xml.StartElement{Name: xml.Name{Local: "product_title"}})
if err != nil {
return err
}
err = e.EncodeElement(p.Price, xml.StartElement{Name: xml.Name{Local: "product_price"}})
if err != nil {
return err
}
stockStatus := "no"
if p.InStock {
stockStatus = "yes"
}
err = e.EncodeElement(stockStatus, xml.StartElement{Name: xml.Name{Local: "in_stock"}})
if err != nil {
return err
}
return e.EncodeToken(start.End())
}
func main() {
product := Product{ID: 101, Title: "Laptop", Price: 999.99, InStock: true}
output, err := xml.MarshalIndent(product, "", " ")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(output))
}
Результат выполнения кода:
<product>
<product_id>101</product_id>
<product_title>Laptop</product_title>
<product_price>999.99</product_price>
<in_stock>yes</in_stock>
</product>
Смотрите также
-
интерфейс
xml.Unmarshaler,
который позволяет управлять парсингом XML -
интерфейс
json.Marshaler,
который аналогичен для JSON -
функцию
xml.Marshal,
которая преобразует данные в XML без отступов -
функцию
xml.MarshalIndent,
которая создает XML с форматированием