
本文详解如何使用 Go 的 encoding/xml 包解析含内联标签(如 <ph>)的 XML 文本节点,通过组合 ",chardata"、",innerxml" 和结构体嵌套,精准提取混合内容并重构为模板字符串。
本文详解如何使用 go 的 `encoding/xml` 包解析含内联标签(如 `
在国际化(i18n)场景中,常见 XLIFF 或自定义 XML 格式将翻译单元(<trans-unit>)的源文本(<source>)设计为“纯文本 + 内联占位符标签”的混合结构,例如:
<source>hello %<ph id="first_name">{0}</ph> %<ph id="last_name">{1}</ph></source>目标是将其解析为可读、可重构的 Go 数据结构,并最终生成形如 hello %{first_name} %{last_name} 的模板字符串。直接将 <source> 映射为 string 会丢失 <ph> 标签信息;而仅用 xml:",innerxml" 则获得含原始标签的 HTML 片段,无法分离文本与变量。
正确解法:利用 encoding/xml 的多语义字段标签协同工作
Go 的 XML 解析器支持在同一结构体中同时捕获三种内容:
- xml:",chardata":捕获纯文本节点(不含标签的字符数据);
- xml:",innerxml":捕获该元素内所有原始 XML 内容(含标签、文本、注释);
- xml:"tagname":捕获子元素并反序列化为结构体切片。
因此,我们定义嵌套结构体 Source,让 Raw、Text 和 Vars 各司其职:
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"` // 纯文本部分("hello % " + " % ")
Vars []Var `xml:"ph"` // 所有 <ph> 子元素
}
type Var struct {
ID string `xml:"id,attr"` // 如 "first_name"
Value string `xml:",innerxml"` // <ph> 内的原始内容,如 "{0}"
}⚠️ 关键注意事项:
- ",chardata" 和 ",innerxml" 不可共存于同一字段,但可共存于同一结构体的不同字段 —— 解析器会智能分发内容;
- ",chardata" 仅捕获直接子文本节点(即 <source> 开始标签后、第一个 <ph> 前,以及各 <ph> 之间的文本),不包含标签内的文本;
- Vars 字段必须声明为切片([]Var),否则解析器只会匹配第一个 <ph>;
- 若 <source> 中存在多个连续文本片段(如换行、空格),Text 将合并为单个字符串(含空白),需按需 strings.TrimSpace 处理。
重构为模板字符串的实用函数示例:
import "strings"
func (s *Source) ToTemplate() string {
var parts []string
parts = append(parts, s.Text)
for _, v := range s.Vars {
// 将 {0} → %{first_name},{1} → %{last_name}
placeholder := "%{" + v.ID + "}"
parts = append(parts, placeholder)
}
return strings.Join(parts, "")
}
// 使用示例:
// tu := TransUnit{}
// xml.Unmarshal(data, &tu)
// fmt.Println(tu.Source.ToTemplate()) // 输出:hello % %{first_name} % %{last_name}
// (注意:原始 XML 中的空格和换行会保留在 Text 中,实际中建议规范化)✅ 总结:面对混合内容 XML,不要试图“一刀切”地用单一字段解析。合理组合 ",chardata"(获取上下文文本)、",innerxml"(保留结构全貌)与结构化子元素映射(提取语义变量),是 Go XML 解析中处理复杂文本嵌套的标准范式。此方案兼具健壮性与可维护性,适用于 XLIFF、OSX Stringsdict、自定义本地化格式等真实工程场景。

















