如何在 Go 中正确反序列化 XML 多节点数组(解决仅解析首个元素的问题)
技术百科
碧海醫心
发布时间:2026-01-01
浏览: 次 go 的 `xml.unmarshal` 默认只处理单个 xml 元素;当输入是多个并列的顶层 `
在 Go 中处理 VMware vSphere 等系统返回的 XML 数据时,一个常见陷阱是:XML 响应中包含多个同名、并列的顶层元素(如多个
xml.Unmarshal 设计上期望输入为「单个完整 XML 文档或元素」,它无法自动识别并跳转到下一个同级标签。要正确解析这种“多根节点”格式(严格来说不符合标准 XML 文档结构,但常见于 SOAP 或某些 API 响应),必须改用流式解析器 xml.Decoder:
import (
"bytes"
"encoding/xml"
"io"
)
type HostSystemIdentificationInfo struct { // 注意:此处改为单个结构体,更清晰且便于解码
IdentifierValue string `xml:"identifierValue"`
IdentifierType struct {
Label string `xml:"label"`
Summary string `xml:"summary"`
Key string `xml:"key"`
} `xml:"identifierType"`
}
// 解析多个并列的 HostSystemIdentificationInfo 节点
func parseMultipleXML(xmlData string) ([]HostSystemIdentificationInfo, error) {
var results []HostSystemIdentificationInfo
decoder := xml.NewDecoder(bytes.NewBufferString(xmlData))
for {
var item HostSystemIdentificationInfo
err := decoder.Decode(&item)
if err == io.EOF {
break // 所有节点已读取完毕
}
if err != nil {
return nil, err // 如遇格式错误(如标签不闭合),立即返回
}
results = append(results, item)
}
return results, nil
}✅ 关键要点说明:
- 结构体定义优化:将类型从 []struct{...} 改为单个 struct,再手动切片收集,语义更清晰,避免嵌套切片带来的反序列化歧义;
- Decoder 是核心:xml.NewDecoder 创建可复用的流式解析器,Decode(&v) 每次读取并解析下一个完整的起始-结束标签对;
- EOF 判定终止:循环以 io.EOF 为正常退出条件,其他 err(如语法错误)需显式处理;
-
无需预包装根节点:不推荐手动拼接
... 包裹原始 XML(易引入转义/命名空间问题),Decoder 方式更健壮、零侵入。
⚠️ 注意事项:
- 确保原始 XML 字符串中各节点格式合法(标签闭合、属性引号匹配),否则 Dec
ode 可能提前失败; - 若 XML 含有 xmlns 或 xsi:type 等命名空间属性,而结构体未声明对应字段,Decode 通常会静默跳过——如需保留,可在结构体中添加 XMLName xml.Namexml:"HostSystemIdentificationInfo"` 字段;
- 性能敏感场景下,Decoder 比多次调用 Unmarshal 更高效,因复用底层词法分析器状态。
通过采用 xml.Decoder 循环解码,即可稳定、准确地提取全部 HostSystemIdentificationInfo 实例,彻底解决“只拿到第一个元素”的问题。
# 多个
# 第一个
# 可在
# 文档
# 更清晰
# 而非
# app
# 复用
# 自动识别
# go
# 循环
# xml
# 字符串
# 结构体
# 命名空间
# Struct
# 切片
# 流式
# 不符合
# EOF
# vmware
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么恢复误删照片_Win11数据恢复工具
- Win11怎么查看局域网电脑_Windows 11
- C#如何在一个XML文件中查找并替换文本内容
- 如何用::实现工具类方法调用_php静态工具类设计
- MAC怎么使用表情符号面板_MAC Emoji快捷
- Python网络超时处理_健壮性设计说明【指导】
- Win11 explorer.exe频繁崩溃_修复
- Linux如何使用grep搜索文件内容_Linux
- Python深度学习实战教程_神经网络模型构建与训
- LINUX如何删除用户和用户组_Linux use
- mac怎么分屏_MAC双屏显示与分屏操作技巧【指南
- Win10如何更改开机密码_Windows10登录
- Mac如何备份到iCloud_Mac桌面与文稿文件
- Win11如何添加/删除输入法 Win11切换中英
- WindowsUSB驱动安装异常怎么办_USB驱动
- c++中如何求一个数的平方根_c++ sqrt函数
- Go 中的 := 运算符:类型推导机制与使用边界详
- php嵌入式多设备通信怎么实现_php同时管理多个
- php转exe用什么工具打包快_高效打包软件推荐【
- Win11系统更新后黑屏怎么办 Win11更新黑屏
- Win10怎么关闭自动更新错误重启 Win10策略
- Windows10系统怎么查看设备管理器_Win1
- Win11怎么关闭键盘按键音_Win11禁用打字声
- Win10电脑怎么设置IP地址_Windows10
- Windows10系统服务优化指南_Win10禁用
- win11 OneDrive怎么彻底关闭 Win1
- php8.4xdebug无法调试怎么办_php8.
- Win11怎么关闭自动调节亮度_Windows11
- Win11怎么查看已连接wifi密码 Win11查
- Mac如何与安卓手机传文件_Mac和Android
- Win11资源管理器卡顿怎么办 Win11文件资源
- Win11怎么硬盘分区 Win11新建磁盘分区详细
- Win11怎么更改电脑名称_Windows 11修
- Win11怎么解压RAR文件 Win11自带解压功
- Windows的便笺功能如何使用?(桌面备忘技巧)
- Win11怎么连接投影仪_Win11多显示器投屏设
- 如何使用Golang模拟请求超时_Golang c
- Windows 11登录时提示“用户配置文件服务登
- 如何在JavaScript中动态拼接PHP的bas
- Win11如何设置系统语言_Win11系统语言切换
- 如何使用Golang reflect检查方法数量_
- PythonGIL机制理解_多线程限制解析【教程】
- Python类装饰器使用_元编程解析【教程】
- Win11如何设置ipv6 Win11开启IPv6
- PHP cURL GET请求:正确设置认证与自定义
- GML (Geography Markup Lan
- Win11怎么关闭通知中心_Windows11系统
- 如何在Golang中验证模块完整性_Golangg
- Win11怎么激活Windows10_Win11激
- 如何在 Go 中比较自定义的数组类型(如 [20]

ode 可能提前失败;
QQ客服