dowm41315 2015-03-09 16:52
浏览 57
已采纳

使用冲突的元素名称在Go中解组XML

I have the following XML, externally defined and outside of my organization's control:

<foo>
  <bar>
    <zip>zip</zip>
  </bar>
  <bar>
    <zap>zap</zap>
  </bar>
</foo>

I am using these structs:

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"`
}

Because of the conflicting 'bar' name, nothing gets unmarshaled. How can I populate the Bar1 and Bar2 structs?

This is what I have: https://play.golang.org/p/D2IRLojcTB

This is the result I want: https://play.golang.org/p/Ytrbzzy9Ok

In the second one, I have updated the second 'bar' to be 'bar1,' and it all works. I'd rather come up with a cleaner solution that modifying the incoming XML.

展开全部

  • 写回答

1条回答 默认 最新

  • drap5081683 2015-03-09 17:19
    关注

    The encoding/xml package won't be able to do exactly what you want, since it makes the decision over which field of Foo to decode into when it encounters the <bar> element, rather than when processing children of that element. Your struct definitions make this decision ambiguous, as the error from xml.Unmarshal indicates:

    main.Foo field "Bar1" with tag "" conflicts with field "Bar2" with tag ""

    Here are two alternatives that will work though:

    1. Use one Bar struct to cover both branches

    If you modify your types to read as:

    type Foo struct {
        XMLName xml.Name `xml:"foo"`
        Bars    []Bar    `xml:"bar"`
    }
    
    type Bar struct {
        Zip string `xml:"zip"`
        Zap string `xml:"zap"`
    }
    

    You will now get a slice that represents all the <bar> elements. You can tell whether the element had a <zip> or <zap> element by checking whether the corresponding fields are non-empty.

    You can try out this version here: https://play.golang.org/p/kguPCYmKX0

    2. Use child selectors

    If you are only interested in a single child element of <bar> in each branch, then you might not need a struct to represent that element at all. For example, you could decode into the following type:

    type Foo struct {
        XMLName xml.Name `xml:"foo"`
        Zip     string   `xml:"bar>zip"`
        Zap     string   `xml:"bar>zap"`
    }
    

    Now the children of the <bar> elements will be decoded directly into members of the Foo struct. Note that with this option you won't be able to distinguish your chosen input from e.g.

    <foo>
      <bar>
        <zip>zip</zip>
        <zap>zap</zap>
      </bar>
    </foo>
    

    If that will cause problems, then you should pick the first solution.

    You can try out this version here: https://play.golang.org/p/fAE_HSrv4y

    展开全部

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部