
本文介绍如何使用 Go 的 encoding/xml 包,灵活提取位于任意嵌套深度的 XML 节点(如 ),并正确反序列化为结构体字段,支持简单值与复杂嵌套结构。
本文介绍如何使用 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"
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 的最佳实践。











