使用冲突的元素名称解压缩Go中的XML

use*_*232 5 xml encoding marshalling go unmarshalling

我有以下XML,外部定义并且在我的组织的控制之外:

<foo>
  <bar>
    <zip>zip</zip>
  </bar>
  <bar>
    <zap>zap</zap>
  </bar>
</foo>
Run Code Online (Sandbox Code Playgroud)

我正在使用这些结构:

type Foo struct {
    XMLName xml.Name `xml:"foo"`
    Bar1    Bar1
    Bar2    Bar2
}

type Bar1 struct {
    XMLName xml.Name `xml:"bar"`
    Zip     string   `xml:"zip"`
}

type Bar2 struct {
    XMLName xml.Name `xml:"bar"`
    Zap     string   `xml:"zap"`
}
Run Code Online (Sandbox Code Playgroud)

由于"bar"名称存在冲突,因此没有任何内容可以解组.如何填充Bar1和Bar2结构?

这就是我所拥有的:https://play.golang.org/p/D2IRLojcTB

这是我想要的结果:https://play.golang.org/p/Ytrbzzy9Ok

在第二个,我已经将第二个'bar'更新为'bar1',这一切都有效.我宁愿想出一个更清晰的解决方案来修改传入的XML.

Jam*_*dge 11

encoding/xml软件包将无法做你想要什么,因为它使决定在其领域Foo解码成在遇到<bar>处理该元素的子元素的时候,而不是.您的结构定义使此决定不明确,因为错误来自xml.Unmarshal:

带有标记""的main.Foo字段"Bar1"与带有标记""的字段"Bar2"冲突

以下两种方法可行:

1.使用一个Bar结构来覆盖两个分支

如果您将类型修改为:

type Foo struct {
    XMLName xml.Name `xml:"foo"`
    Bars    []Bar    `xml:"bar"`
}

type Bar struct {
    Zip string `xml:"zip"`
    Zap string `xml:"zap"`
}
Run Code Online (Sandbox Code Playgroud)

现在,您将获得一个表示所有<bar>元素的切片.你可以告诉元素是否有一个<zip><zap>通过检查相应的字段是否非空元素.

你可以在这里试用这个版本:https://play.golang.org/p/kguPCYmKX0

2.使用儿童选择器

如果您只对<bar>每个分支中的单个子元素感兴趣,那么您可能根本不需要结构来表示该元素.例如,您可以解码为以下类型:

type Foo struct {
    XMLName xml.Name `xml:"foo"`
    Zip     string   `xml:"bar>zip"`
    Zap     string   `xml:"bar>zap"`
}
Run Code Online (Sandbox Code Playgroud)

现在,<bar>元素的子元素将直接解码为Foo结构的成员.请注意,使用此选项,您将无法区分所选输入,例如

<foo>
  <bar>
    <zip>zip</zip>
    <zap>zap</zap>
  </bar>
</foo>
Run Code Online (Sandbox Code Playgroud)

如果这会导致问题,那么你应该选择第一个解决方案.

你可以在这里试用这个版本:https://play.golang.org/p/fAE_HSrv4y