
go 的 encoding/xml 包支持通过 ,chardata 标签选项将 xml 元素的文本内容(如 <depth>1200</depth> 中的 1200)直接解码为结构体字段,这是处理带属性和文本值混合的 xml 元素的关键技巧。
go 的 encoding/xml 包支持通过 ,chardata 标签选项将 xml 元素的文本内容(如 <depth>1200</depth> 中的 1200)直接解码为结构体字段,这是处理带属性和文本值混合的 xml 元素的关键技巧。
在 Go 中解析类似 <depth measurementUnitCode="MMT">1200</depth> 这类既含属性又含文本值的 XML 元素时,需明确区分两类数据源:属性(attribute)对应结构体字段的 xml:"name,attr" 标签,而元素内部的纯文本内容(即 character data)则必须使用特殊的 xml:",chardata" 标签。
以问题中的 XML 为例:
<packaging>
<depth measurementUnitCode="MMT">1200</depth>
<height measurementUnitCode="MMT">1320</height>
</packaging>我们希望将 depth 和 height 解析为统一的 Measurement 类型,其中既包含单位代码(属性),也包含数值(文本内容)。正确的结构体定义如下:
type Packaging struct {
Depth Measurement `xml:"depth"`
Height Measurement `xml:"height"`
}
type Measurement struct {
UnitOfMeasure string `xml:"measurementUnitCode,attr"`
Value float64 `xml:",chardata"`
}⚠️ 注意事项:
- xml:",chardata" 必须单独使用,不能与其他路径或名称组合(如 xml:"value,chardata" 是非法的);
- 字段类型需能被 xml.Unmarshal 支持(float64、int、string 等均可,但需确保 XML 内容可转换);
- 若 XML 文本为空或含非数字字符而目标字段为 float64,解码将失败并返回错误(建议在生产环境添加错误检查);
- 同一 XML 元素内仅允许一个 ,chardata 字段;若存在多个,只有第一个会被填充。
完整可运行示例:
package main
import (
"encoding/xml"
"fmt"
"log"
)
type Packaging struct {
Depth Measurement `xml:"depth"`
Height Measurement `xml:"height"`
}
type Measurement struct {
UnitOfMeasure string `xml:"measurementUnitCode,attr"`
Value float64 `xml:",chardata"`
}
func main() {
xmlData := `<packaging>
<depth measurementUnitCode="MMT">1200</depth>
<height measurementUnitCode="MMT">1320</height>
</packaging>`
var pkg Packaging
err := xml.Unmarshal([]byte(xmlData), &pkg)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Depth: %.0f %s\n", pkg.Depth.Value, pkg.Depth.UnitOfMeasure) // 输出:Depth: 1200 MMT
fmt.Printf("Height: %.0f %s\n", pkg.Height.Value, pkg.Height.UnitOfMeasure) // 输出:Height: 1320 MMT
}✅ 总结:当 XML 元素同时携带属性与文本值时,xml:",chardata" 是获取其内部文本内容的唯一标准方式。它简洁、高效,且与属性解析完全正交,是构建健壮 XML 解析逻辑的基础能力。

















