如何在 Go 中正确反序列化多个同级 XML 元素(而非单个根节点)
技术百科
聖光之護
发布时间:2026-01-01
浏览: 次 go 的 `xml.unmarshal` 要求输入 xml 有且仅有一个根元素;若原始数据是多个并列的 `
在 Go 中处理 VMware vSphere 等系统返回的 XML 数据时,一个常见陷阱是:summary.hardware.otherIdentifyingInfo 字段的值并非标准 XML 文档(即带单一根节点),而是多个同级
✅ 正确解法是使用 xml.Decoder,它支持流式解析,可多次调用 Decode() 方法,每次读取并解析一个独立的 XML 元素:
import (
"bytes"
"encoding/xml"
"io"
)
type HostSystemIdentificationInfo struct { // 注意:此处改为普通 struct,非切片
IdentifierValue string `xml:"identifierValue"`
IdentifierType struct {
Label string `xml:"label"`
Summary string `xml:"summary"`
Key string `xml:"key"`
} `xml:"identifierType"`
}
// 解析多个并列的 HostSystemIdentificationInfo
func parseIdentificationInfos(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, fmt.Errorf("failed to decode XML item: %w", err)
}
results = append(results, item)
}
return results, nil
}? 关键要点:
- 不要将类型定义为切片(如 []struct{}):xml.Decode() 期望接收一个可寻址的单个值(如 &item),而非切片地址;切片应由调用方手动 append 维护。
- 字段名需与 XML 标签名严格匹配:原代码中 IdentiferValue 拼写错误(多了一个 e),应为 IdentifierValue;Go 的 XML 反序列化对大小写和拼写敏感,否则字段将为空。
- 无需手动处理 xsi:type 属性:只要结构体字段标签正确,encoding/xml 会自动跳过未知属性,不影响主体解析。
- 错误处理不可省略:decoder.Decode() 在遇到格式错误时会返回具体错误(如标签不闭合、非法字符),应显式检查而非忽略。
在你的 vSphere 客户端逻辑中,只需将原 xml.Unmarshal 替换为上述 parseIdentificationInfos 调用:
if p.Name == "summary.hardware.otherIdentifyingInfo" {
infos, err := parseIdentificationInfos(p.Val.Inner)
if err != nil {
return fmt.Errorf("f
ailed to parse host identification info: %w", err)
}
fmt.Printf("Parsed %d identification entries\n", len(infos))
for _, info := range infos {
fmt.Printf("- Value: %q, Type: %q (Key: %q)\n",
info.IdentifierValue,
info.IdentifierType.Label,
info.IdentifierType.Key)
}
}✅ 总结:当面对“无根多节点 XML 字符串”时,xml.Decoder + 循环 Decode() 是 Go 标准库提供的标准、可靠且内存友好的解决方案。避免强行添加虚拟根节点(如
# ai
# 多个
# 第一个
# 只需
# 文档
# 跳过
# 而非
# app
# 只会
# 要将
# go
# 循环
# 字节
# 标准库
# xml
# 字符串
# bug
# 结构体
# 命名空间
# Struct
# 切片
# 不符合
# append
# 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; ?>
】
相关推荐
- Windows服务无法启动错误1067是什么_进程
- Win11怎么关闭通知消息_屏蔽Windows 1
- Windows10如何更改桌面图标间距_Win10
- Win11怎么设置鼠标宏_Win11鼠标按键自定义
- Win11怎么设置默认图片查看器_Windows1
- php打包exe如何加密代码_防反编译保护方法【技
- Django 测试数据库表缺失与字段未创建问题的完
- Win11时间格式怎么改成12小时制 Win11时
- Win10怎么卸载爱奇艺_Win10彻底卸载爱奇艺
- 如何使用Golang benchmark测量函数延
- 新手学PHP架构总混淆概念咋办_重点梳理【教程】
- Win11怎样激活系统密钥_Win11系统密钥激活
- php订单日志怎么记录发货_php记录订单发货操作
- Mac怎么给文件夹加密_Mac创建加密磁盘映像教程
- 如何在Windows中创建新的用户账户?(标准与管
- Win11怎么查看wifi信号强度_检测Windo
- php删除数据怎么软删除_添加is_del字段标记
- Win11怎么设置开机自动连接宽带_Windows
- Windows 11无法安全删除U盘提示设备正在使
- Win11任务栏颜色怎么改_Win11自定义任务栏
- Win11关机界面怎么改_Win11自定义关机画面
- php高频调试功能有哪些_php常用调试函数与工具
- Python技术债务管理_长期维护解析【教程】
- 如何使用Golang实现云原生应用弹性伸缩_自动应
- Windows10如何更改桌面背景_Win10个性
- XML的“混合内容”是什么 怎么用DTD或XSD定
- 如何使用Golang实现容器健康检查_监控和自动重
- Django密码修改后会话失效的解决方案
- Win10如何更改任务栏高度_Windows10解
- Python模块的__name__属性如何由导入方
- Windows10怎么查看硬件信息_Windows
- Windows 11怎么设置默认解压软件_Wind
- Win11如何设置ipv6 Win11开启IPv6
- 如何使用Golang recover捕获panic
- c++如何实现一个高性能的环形队列(Ring Bu
- Win11如何更改任务栏颜色 Win11自定义任务
- Windows10系统怎么查看防火墙状态_Win1
- c++ std::atomic如何保证原子性 c+
- How to Properly Use NumPy
- Win10怎样安装PPT模板_Win10安装PPT
- 如何使用Golang构建基础消息队列模拟_Gola
- Windows怎样关闭桌面弹窗广告_Windows
- Python项目维护经验_长期演进说明【指导】
- PythonGIL机制理解_多线程限制解析【教程】
- Win11怎样安装钉钉客户端_Win11安装钉钉教
- win11如何清理传递优化文件 Win11为C盘瘦
- PHP主流架构怎么监控运行状态_工具推荐【操作】
- 如何使用Golang实现跨域请求支持_Golang
- Win11怎么关闭内容自适应亮度_Windows1
- Win11无法拖拽文件到任务栏怎么办_Win11开

ailed to parse host identification info: %w", err)
}
fmt.Printf("Parsed %d identification entries\n", len(infos))
for _, info := range infos {
fmt.Printf("- Value: %q, Type: %q (Key: %q)\n",
info.IdentifierValue,
info.IdentifierType.Label,
info.IdentifierType.Key)
}
}
QQ客服