结构体字段必须导出且标签精准匹配XML层级:小写字母开头字段不被序列化,嵌套需严格对齐,xml:"name"区分大小写和层级,属性值仅支持基础类型,命名空间、CDATA、omitempty等须显式声明。

直接用 encoding/xml 解析复杂 XML 配置文件,只要结构体字段与 XML 树严格对齐,就能生成干净的对象;但标签写错、嵌套不匹配、属性类型不对或命名空间漏处理,会导致字段全空或 panic。
结构体字段必须导出且标签精准匹配 XML 层级
Go 不会序列化小写字母开头的字段,哪怕加了 xml:"name" 也没用。XML 中每层嵌套都得对应一个可导出结构体字段,不能靠“自动展开”省事。
-
xml:"book"表示子元素叫<book>,不是<books>或<Book> - 若 XML 是
<author><name>Alice</name></author>,就得定义Author struct{ Name string `xml:"name"` }字段,而不是把Name直接挂在顶层 - 想跳过中间层(如
author>name),可用xml:"author>name",但只支持单级跳转,author>contact>email会失败 - 同名多个节点(如多个
<item>)必须用切片:Items []Item `xml:"item"`,否则只取第一个
属性值只能是基础类型,别往 struct 上硬套 ,attr
xml:"id,attr" 要求字段类型是 string、int、bool 等,不能是自定义 struct。常见错误是给一个嵌套结构体字段加 ,attr,结果报 xml: unsupported type: struct { }。
- 正确:
ID string `xml:"id,attr"` - 错误:
Meta MetaInfo `xml:"meta,attr"`—— MetaInfo 是结构体,不合法 - 如果真要存结构化属性(比如 JSON 字符串),先
json.Marshal成string,再塞进string字段 +,attr - 空属性也要显式赋值,
omitempty对属性无效,它只作用于元素
命名空间和 CDATA 必须显式声明,不能靠猜测
带 xmlns 的 XML(如 RSS、SOAP)必须在结构体里显式捕获,否则整个解析会静默失败或字段为空。CDATA 也一样,不加 ,cdata 就当普通子元素处理,内容被丢弃。
立即学习“go语言免费学习笔记(深入)”;
- 根元素带命名空间:
<rss xmlns="http://purl.org/rss/1.0">→ 结构体需加XMLName xml.Name `xml:"rss"`,并用Space捕获:XMLName xml.Name `xml:"rss"`+ 单独字段XMLNS string `xml:"xmlns,attr"` - 文本块需原样保留(如 HTML 片段):
Content string `xml:",cdata"`,不是,innerxml—— 后者会包含子标签,cdata只取纯文本 - 混合内容(文本 + 子元素共存)无法用结构体直接映射,得退回到
xml.Token流式解析
生成 XML 时中文乱码、缺声明、空字段干扰输出
xml.Marshal 默认输出 UTF-8 字节流,没 XML 声明;omitempty 控制不好会让配置缺失关键字段;而零值字段(如空字符串、0)不加约束就会被写入,破坏语义。
- 强制加声明:
xml.Header + string(xmlBytes),xml.Header是常量"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - 可选字段用指针:
Title *string `xml:"title,omitempty"`,这样nil才不输出,""仍会输出空标签 - 避免中文乱码:确保源字符串是 UTF-8 编码(Go 字符串默认就是),别用
[]byte("中文")混淆编码 - 格式化输出用
xml.MarshalIndent,缩进参数传""和" ",别传错顺序
最易被忽略的是:XML 层级和结构体嵌套必须一一对应,没有“智能推断”;属性值类型检查在运行时才暴露;命名空间不声明就等于不存在;而 xml:",chardata" 和 xml:",innerxml" 行为差异极大,混用会导致内容丢失或标签泄露。


















