
本文介绍如何使用 Go 的 encoding/xml 包,灵活提取位于任意嵌套深度的 XML 节点(如 <FullName>),并正确反序列化为结构体字段,支持简单值与复杂嵌套结构。
本文介绍如何使用 go 的 `encoding/xml` 包,灵活提取位于任意嵌套深度的 xml 节点(如 `
在 Go 中,xml.Unmarshal 默认采用严格路径匹配:结构体字段的 XML 标签(如 xml:"FullName")仅匹配直接子元素,无法跨层级搜索。因此,面对如下 XML:
<People>
<Person>
<FullName>Jerome Anthony</FullName>
</Person>
<a>
<Person>
<FullName>Christina</FullName>
</Person>
</a>
</People>若定义 type People struct { Names []stringxml:"FullName"},将无法捕获任何 <FullName> —— 因为 <FullName> 并非 <People> 的直接子元素,而是嵌套在 <Person> 下(可能多层)。
✅ 正确方案:使用通配符路径 ".//FullName"
Go 的 encoding/xml 支持 XPath 风格的简化语法。".//FullName" 表示“从当前节点开始,递归查找所有名为 FullName 的后代元素”,无论嵌套几层:
type People struct {
Names []string `xml:".//FullName"`
}
data := `<People>
<Person><FullName>Jerome Anthony</FullName></Person>
<a><Person><FullName>Christina</FullName></Person></a>
</People>`
v := People{}
err := xml.Unmarshal([]byte(data), &v)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Names: %q\n", v.Names) // 输出: ["Jerome Anthony" "Christina"]? 处理复杂结构(如完整 Person 对象)
当需提取完整嵌套结构(不止字符串)时,可定义对应结构体,并同样使用 ".//Person":
type Person struct {
FullName string `xml:"FullName"`
Age int `xml:"Age"`
}
type People struct {
Persons []Person `xml:".//Person"`
}
// 示例 XML(含 Age)
data := `<People>
<Person><FullName>Alice</FullName><Age>30</Age></Person>
<group><Person><FullName>Bob</FullName><Age>25</Age></Person></group>
</People>`
var p People
xml.Unmarshal([]byte(data), &p)
fmt.Printf("Found %d persons: %+v\n", len(p.Persons), p.Persons)
// 输出: Found 2 persons: [{FullName:"Alice" Age:30} {FullName:"Bob" Age:25}]⚠️ 注意事项
- ".//X" 是 Go XML 解析器特有语法(非标准 XPath),仅支持 .(当前节点)、//(任意后代)和元素名,不支持属性筛选(如 //X[@attr="val"]);
- 若 XML 存在命名空间,需显式处理前缀(如 xml:"ns:FullName"),通配符路径仍有效;
- 为避免空切片 panic,建议初始化结构体字段或使用指针字段(如 *[]string);
- 如需更强大查询能力(如条件过滤、属性提取),推荐结合 github.com/huandu/xstrings 或解析为 xml.Node 后手动遍历。
✅ 总结
无需手动遍历 DOM 或正则解析,Go 原生 encoding/xml 通过 ".//ElementName" 语法即可实现任意层级节点提取,兼顾简洁性与类型安全性。这是处理不规则、松散嵌套 XML 的最佳实践。

















