如何用Go标准库解析XML获取指定令牌的已知属性值?
Go标准库解析XML获取指定属性值的惯用方法
嘿,我来给你详细说说Go标准库怎么处理这个需求,刚好这两种常用方式我都用过,给你拆解清楚:
一、用xml.Decoder循环令牌的实现方式
完全可以通过解码器循环令牌来实现,这也是处理大型XML或者只需要提取部分内容时常用的方式,步骤和代码示例如下:
核心思路就是逐枚读取XML令牌,判断遇到的是不是<foo>的起始标签,再从中提取bar属性:
package main import ( "encoding/xml" "fmt" "strings" ) func main() { // 模拟你的HTTP请求体XML内容 xmlContent := `<something> ... <inner_something> ... <foo bar='VALUE_I_WANT'> ... </foo> ... </inner_something> ... </something>` decoder := xml.NewDecoder(strings.NewReader(xmlContent)) for { token, err := decoder.Token() // 遇到错误或者到XML结尾就退出循环 if err != nil { break } // 判断当前令牌是否是起始标签元素 startElem, ok := token.(xml.StartElement) if !ok { continue } // 检查标签名是否是我们要找的`foo`(注意XML标签名大小写敏感哦) if startElem.Name.Local == "foo" { // 遍历该标签的所有属性,找到`bar`属性 for _, attr := range startElem.Attr { if attr.Name.Local == "bar" { fmt.Printf("拿到目标值啦:%s\n", attr.Value) // 找到后直接退出程序就行,不用继续解析了 return } } } } fmt.Println("没找到目标属性哦") }
具体判断逻辑:
- 每次读取令牌后,先断言是不是
xml.StartElement类型(也就是标签的起始部分,比如<foo bar="xxx">) - 对比
startElem.Name.Local是否等于"foo",确认是目标标签 - 遍历
startElem.Attr这个属性切片,找到Name.Local为"bar"的属性,它的Value就是你要的VALUE_I_WANT
二、更简洁的结构体映射方式
这可不是标准库的唯一实现方式哦,对于结构固定的XML,用结构体映射+xml.Unmarshal会更简洁,代码量更少:
你只需要定义和XML结构对应的结构体,给字段加上xml标签指定映射关系,就能直接解析出目标属性:
package main import ( "encoding/xml" "fmt" "strings" ) // 定义和XML层级对应的结构体 type Something struct { InnerSomething struct { Foo struct { Bar string `xml:"bar,attr"` // 用`,attr`标记这是标签的属性 } `xml:"foo"` // 指定映射到<foo>标签 } `xml:"inner_something"` // 指定映射到<inner_something>标签 } func main() { xmlContent := `<something> ... <inner_something> ... <foo bar='VALUE_I_WANT'> ... </foo> ... </inner_something> ... </something>` var data Something err := xml.Unmarshal([]byte(xmlContent), &data) if err != nil { panic(err) } fmt.Printf("拿到目标值啦:%s\n", data.InnerSomething.Foo.Bar) }
关于“直接查找令牌”的疑问
Go标准库本身没有提供类似XPath的直接查询API,没法直接写个路径就取出目标属性,要么自己循环令牌筛选,要么用结构体映射。如果需要更强大的查询能力,可能得借助第三方库,但仅用标准库的话,就是这两种方式啦。
内容的提问来源于stack exchange,提问作者Bren
相关产品推荐
相关产品推荐

