在 Go 中解组具有交替内容类型的 XML 元素

Unmarshal XML element with alternating content type in Go

我正在尝试像这样解组 xml:

<message numerus="yes">
    <source>%n part(s)</source>
    <translation>
        <numerusform>%n part</numerusform>
        <numerusform>%n parts</numerusform>
    </translation>
</message>

<message>
    <source>Foo</source>
    <translation>Bar</translation>
</message>

请注意,<translation> 标签可以包含一个简单的字符串或多个 <numerusform> 标签。

使用 go 的 xml 包,我正在解组的结构如下所示:

type Message struct {
    Source       string   `xml:"source"`
    Numerus      string   `xml:"numerus,attr"`
    Translation  string   `xml:"translation"`
    NumerusForms []string `xml:"translation>numerusform"`
}

问题:可以使用字段 TranslationNumerusForms。如果像此处所示同时使用两者,则会发生错误:

Error on unmarshalling xml: main.Message field "Translation" with tag "translation" conflicts with field "NumerusForms" with tag "translation>numerusform"

非常合理,因为解组程序无法决定如何处理 <translation> 标记。

有什么办法可以解决这个问题吗?可以有两个不同的命名字段(一个用于纯字符串,一个用于字符串列表,如上所示的结构)。

完整的可运行代码,请参考this go playground

旁注:我正在尝试解析 Qt Linguist TS file。该示例被大量剥离以使其更容易推理。

一个不需要实现自定义解组器逻辑的简单解决方案是创建一个包含 2 个字段的 Translation 结构:1 个用于可选文本内容,一个用于可选 <numerusform>子元素:

type Message struct {
    Source      string      `xml:"source"`
    Numerus     string      `xml:"numerus,attr"`
    Translation Translation `xml:"translation"`
}

type Translation struct {
    Content      string   `xml:",cdata"`
    NumerusForms []string `xml:"numerusform"`
}

这将输出(在 Go Playground 上尝试):

Source: %n part(s)
Numerus: yes
Translation: "\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t"
NumerusForms: [%n part %n parts]
  Numerus: %n part
  Numerus: %n parts

Source: Foo
Numerus: 
Translation: "Bar"
NumerusForms: []

请注意,当实际上有 <numerusform> 个子元素时,Translation.Content 字段仍会填充缩进字符,您可以安全地忽略这些缩进字符。