Golang解析带windows-1251编码声明的XML返回空数组问题
问题根因
Go标准库encoding/xml默认仅支持UTF-8编码的XML内容解析。目标接口返回的内容编码为windows-1251,XML头部声明已明确标注该编码,但直接读取响应字节流调用xml.Unmarshal时,解析器无法自动完成该非UTF-8编码的识别与转码,最终导致解析结果为空。手动删除XML声明只是让解析器默认按UTF-8规则猜测编码,属于碰运气的错误方案,遇到windows-1251编码下的西里尔字母等特殊字符时必然出现乱码,不具备可用性。
修复方案
无需手动修改XML内容、删除头部声明,只需要在读取响应流时增加编码转换步骤,将windows-1251编码的内容转成UTF-8后再做XML解析即可。
- 先安装转码依赖:
go get golang.org/x/text/encoding/charmap go get golang.org/x/text/transform
- 调整后的完整可运行代码如下:
package main import ( "encoding/xml" "fmt" "io" "net/http" "golang.org/x/text/encoding/charmap" "golang.org/x/text/transform" ) type ValCurs struct { XMLName xml.Name `xml:"ValCurs"` Date string `xml:"Date,attr"` Name string `xml:"name,attr"` Valute []Valute `xml:"Valute"` } type Valute struct { XMLName xml.Name `xml:"Valute"` CharCode string `xml:"CharCode"` Nominal string `xml:"Nominal"` Name string `xml:"Name"` Value string `xml:"Value"` } func main() { resp, err := http.Get("http://www.cbr.ru/scripts/XML_daily.asp") if err != nil { panic(err) } defer resp.Body.Close() // 包装响应流,读取时自动将windows-1251编码转成UTF-8 decoder := charmap.Windows1251.NewDecoder() utf8Reader := transform.NewReader(resp.Body, decoder) req, err := io.ReadAll(utf8Reader) if err != nil { panic(err) } var val ValCurs err = xml.Unmarshal(req, &val) if err != nil { panic(err) } fmt.Printf("%+v\n", val) }
注意事项
- 该方案直接在IO读取层完成转码,不会修改原始XML结构,头部的encoding声明保留也不会干扰解析逻辑
- 原代码结构体标签中逗号后存在多余空格(比如
xml:"Date, attr"),该写法会导致xml包无法识别attr标记,无法正确解析节点属性,修复时已一并删除空格 - 原示例代码忽略了HTTP请求、流读取、XML解析全链路的错误返回,实际使用时必须处理对应错误,否则异常场景下无法定位问题
内容的提问来源于stack exchange,提问作者Remilay
相关产品推荐
相关产品推荐

