)
" />
Go 的 encoding/xml 包不支持通配符式路径匹配(如 //FullName),但可通过定义灵活的嵌套结构体并利用 xml:",any" 和递归解析,实现在任意深度提取目标节点。
go 的 `encoding/xml` 包不支持通配符式路径匹配(如 `//fullname`),但可通过定义灵活的嵌套结构体并利用 `xml:",any"` 和递归解析,实现在任意深度提取目标节点。
在 Go 中处理 XML 时,标准库 encoding/xml 默认要求结构体字段与 XML 节点路径严格对应。当目标节点(如
✅ 正确方案:使用 xml:",any" + 递归解析
核心思路是:定义一个能接收任意子节点的通用结构体,再遍历其内容,递归提取目标节点。
package main
import (
"encoding/xml"
"fmt"
)
type XMLNode struct {
XMLName xml.Name `xml:"*"`
Children []XMLNode `xml:",any"`
Text string `xml:",chardata"`
}
// ExtractFullNames 递归提取所有 FullName 文本
func ExtractFullNames(node XMLNode) []string {
var names []string
if node.XMLName.Local == "FullName" && node.Text != "" {
names = append(names, node.Text)
}
for _, child := range node.Children {
names = append(names, ExtractFullNames(child)...)
}
return names
}
func main() {
data := `
<people><person><fullname>Jerome Anthony</fullname></person><a>
<person><fullname>Christina</fullname></person></a>
</people>`
var root XMLNode
err := xml.Unmarshal([]byte(data), &root)
if err != nil {
panic(err)
}
names := ExtractFullNames(root)
fmt.Printf("Names of people: %q\n", names) // 输出: ["Jerome Anthony" "Christina"]
}
? 关键要点说明
- xml:",any":让 Children 字段捕获当前节点下所有未显式声明的子元素,形成树状结构;
- xml.Name 和 xml:",chardata":分别获取节点名和文本内容,是递归判断与提取的基础;
- 无需预知 XML 层级结构,适用于动态、异构或第三方提供的 XML;
- 对于复杂结构(如需完整反序列化
),可扩展 XMLNode 或结合自定义 UnmarshalXML 方法实现混合解析。
⚠️ 注意事项
- 性能上:全树遍历比精准路径匹配开销略高,但对中等规模 XML(MB 级以下)影响极小;
- 安全性:若 XML 来源不可信,建议配合 xml.Decoder 设置 Strict(false) 和长度限制,防止恶意深层嵌套攻击;
- 替代方案:如需更强大的 XPath 表达式支持(如 //FullName),可引入第三方库如 github.com/jbowens/xmlpath,但会增加依赖。
通过结构化递归解析,你不仅能提取字符串值,还可进一步构建强类型对象(例如将每个匹配的











