Go 的 encoding/xml
包提供了 xml.Attr
类型来表示 XML 属性。你可以通过添加一个字段来接收这些“多余的”或未指定的属性。
示例 XML:
<Person name="Tom" age="30" country="USA"></Person>
方法 1:使用 ,attr
显式字段接收属性
如果你已知属性名,可以这样写:
type Person struct {
Name string `xml:"name,attr"`
Age string `xml:"age,attr"`
Country string `xml:"country,attr"`
}
方法 2:接收所有未定义的额外属性
如果你只定义了部分属性,其余的属性可以使用 []xml.Attr
来接收:
type Person struct {
Name string `xml:"name,attr"` // 显式字段
ExtraAttrs []xml.Attr `xml:",any,attr"` // 接收所有额外属性
}
但实际上
xml:",any,attr"
并不直接支持。Go 的标准encoding/xml
不支持自动捕获未定义的属性进[]xml.Attr
。你必须用xml.Unmarshal
自定义解析器或嵌入结构体 来实现更灵活的处理。
推荐方式:嵌入一个辅助结构体并实现自定义 UnmarshalXML
type Person struct {
Name string `xml:"name,attr"`
ExtraAttrs []xml.Attr
}
func (p *Person) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// 提取已知属性
for _, attr := range start.Attr {
switch attr.Name.Local {
case "name":
p.Name = attr.Value
default:
p.ExtraAttrs = append(p.ExtraAttrs, attr)
}
}
// 跳过子元素(如果有)
return d.Skip()
}
输出示例:
xmlData := `<Person name="Tom" age="30" country="USA"></Person>`
var p Person
xml.Unmarshal([]byte(xmlData), &p)
fmt.Println(p.Name) // Tom
fmt.Println(p.ExtraAttrs) // [age="30", country="USA"]
总结:
- 如果你已知属性名,可直接使用 struct tag
xml:"name,attr"
。 - 如果你想获取所有额外属性,需要自定义
UnmarshalXML
方法。 - Go 的
encoding/xml
包功能强大但略显简陋,处理动态字段需要动手实现。
完整示例
下面是一个完整可运行的 Go 示例,展示如何在解析 XML 时获取已知属性和额外未定义的属性。
✅ 示例 XML:
<Person name="Tom" age="30" country="USA"></Person>
✅ Go 代码(可以直接运行):
package main
import (
"encoding/xml"
"fmt"
"strings"
)
type Person struct {
Name string // 已知属性
ExtraAttrs []xml.Attr // 未定义的额外属性
}
// 自定义 XML 解码器
func (p *Person) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "name":
p.Name = attr.Value
default:
p.ExtraAttrs = append(p.ExtraAttrs, attr)
}
}
// 跳过内部内容
return d.Skip()
}
func main() {
data := `<Person name="Tom" age="30" country="USA"></Person>`
var p Person
if err := xml.Unmarshal([]byte(data), &p); err != nil {
fmt.Println("解析失败:", err)
return
}
fmt.Println("姓名:", p.Name)
fmt.Println("额外属性:")
for _, attr := range p.ExtraAttrs {
fmt.Printf("- %s = %s\n", attr.Name.Local, attr.Value)
}
}
✅ 输出结果:
姓名: Tom
额外属性:
- age = 30
- country = USA