
本文详解如何使用 Go 的 encoding/xml 包解析包含内联 XML 标签(如 )的混合内容字段(如 ),通过组合 chardata、innerxml 和嵌套结构体实现精准提取原始文本与属性数据。
本文详解如何使用 go 的 `encoding/xml` 包解析包含内联 xml 标签(如 `
在 Go 中解析类似 XLIFF 或自定义本地化 XML 时,常遇到
以下为推荐的结构体定义:
type TransUnit struct {
ID string `xml:"id,attr"`
Source Source `xml:"source"`
Target string `xml:"target"`
}
type Source struct {
Raw string `xml:",innerxml"` // 完整原始内容(含标签)
Text string `xml:",chardata"` // 仅纯文本内容(不含标签)
Vars []Var `xml:"ph"` // 所有 <ph> 子元素
}
type Var struct {
ID string `xml:"id,attr"`
Value string `xml:",innerxml"` // <ph> 内部的文本(如 "{0}")
}</ph></ph>
✅ 关键要点说明:
- chardata 捕获节点中所有非标签的纯文本(自动拼接相邻文本片段),适用于提取 "hello % " 和 " % " 等占位符前缀;
- innerxml 获取整个节点的原始 XML 字符串(含所有子标签),可用于调试或备用解析;
- xml:"ph" 直接映射子元素为结构体切片,每个 Var 实例携带 id 属性及内部值;
- 注意:chardata 与 innerxml 可共存于同一结构体,Go 解析器会智能分配——chardata 得纯文本,xml:"ph" 得结构化子节点。
? 实际应用示例(生成目标格式字符串):
假设需将
func (s Source) Format() string {
parts := []string{s.Text} // 初始文本
for _, v := range s.Vars {
parts = append(parts, fmt.Sprintf("%%{%s}", v.ID))
}
return strings.Join(parts, "")
}
// 调用:tu.Source.Format() → "hello %{first_name} %{last_name}"
⚠️ 注意事项:
- chardata 不会包含子元素内的文本(如
{0} 中的 {0} 属于 Var.Value,而非 Source.Text); - 若 XML 中存在多个连续文本节点(如换行+空格),chardata 会合并为单一字符串,需自行处理多余空白;
- 避免在 Source 中同时使用 xml:",any" 或未声明字段,否则可能干扰 chardata 提取;
- 测试时建议使用 xml.Unmarshal 并检查 Source.Text 和 Source.Vars 是否非空,确保结构体标签无拼写错误。
通过这种分层建模方式,你无需二次解析 innerxml 字符串,即可安全、高效地还原带变量插槽的本地化模板字符串。











