I am dealing with an API that is expecting XML that is generally formatted like so.


Therefore, in my Go code, I made these structs to use in my functions and marshal into the XML structure. Note that different receivers can have different sets of credentials.

type Receiver1 struct {
    XMLName      xml.Name             `xml:"receiver"`
    ReceiverType string               `xml:"receiver_type"`
    HostNames    string               `xml:"hostnames"`
    Credentials  Receiver1Credentials `xml:"credentials"`

type Receiver2 struct {
    XMLName      xml.Name             `xml:"receiver"`
    ReceiverType string               `xml:"receiver_type"`
    HostNames    string               `xml:"hostnames"`
    Credentials  Receiver2Credentials `xml:"credentials"`

type Receiver1Credentials struct {
    AppID     Credential `xml:"credential"`
    AppSecret Credential `xml:"credential"`

type Receiver2Credentials struct {
    UserName Credential `xml:"credential"`
    Password Credential `xml:"credential"`
    AppID    Credential `xml:"credential"`

type Credential struct {
    Name  string `xml:"name"`
    Value string `xml:"value"`
    Safe  bool   `xml:"safe"`

However this produces runtime errors along the lines of Receiver1Credentials field "AppID" with tag "credential" conflicts with field "AppSecret" with tag "credential" meaning that I can't directly tag the Credentials fields the same thing. I've tried using a field XMLName xml.Name xml:"credential" (like on the Receiver structs) on the Credential struct, but it gets overwritten by the tag on the Credentials structs. Does anyone know how I could work around this?


To Marshal the data into xml, you can simply create a simple receiver struct, initialize it, and call xml.Marshal(...).

(Note that to nest credential into credentials, explicit xml tag needs to be associated with the fields)

type Receiver struct {
    XMLName      xml.Name     `xml:"receiver"`
    ReceiverType string       `xml:"receiver_type"`
    HostNames    string       `xml:"hostnames"`
    Credentials  []Credential `xml:"credentials>credential"` // necessary to allow tag nesting

type Credential struct {
    Name  string `xml:"name"`
    Value string `xml:"value"`
    Safe  bool   `xml:"safe,omitempty"` // omitempty does not include the tag if if it's empty

Now you can simply initialize a Receiver and marshal it into xml:

r := &Receiver{
        ReceiverType: "test",
        HostNames: "http://posttestserver.com",
        Credentials: []Credential{
            Credential{"app-id", "1234", true},
            Credential{"app-secret", "5678", false},
    a, _ := xml.MarshalIndent(r, "", "  ") // a is []byte containing xml encoded data

(working example: https://play.golang.org/p/JZcUUK9P1f)

Original answer - method to unmarshal the above xml into receiver

If you can avoid parsing the xml data directly into Receiver[12]Credentials, you can unmarshal the xml data into a much simpler structure (Receiver and Credential above) using the following method:

receiver := &Receiver{}
xml.Unmarshal(xmlDataByteSlice, receiver)

This would store all the Credential objects in receiver.Credentials above:

// [{app-id 1234 true} {app-secret 5678 false}]

You can then perhaps use a switch case on receiver,Credential.Name to initialize Receiver[12]Credentials accordingly.

Working example: https://play.golang.org/p/jq3BrxKVo-

dongling0519 确实有效,您是对的。 我将标记您的答案正确,但是为了使问题和答案保持一致,您可以更改答案以显示封送而不是取消封送吗?
大约 4 年之前 回复
doumiebiao6827 要将数据编组为xml,您可以简单地创建一个接收器结构,对其进行初始化,然后调用xml.Marshal(...):play.golang.org/p/JZcUUK9P1f还是我在这里缺少什么?
大约 4 年之前 回复
donglu9743 我没有在帖子中明确指出这一点,但是我想封送XML而不是封送。 道歉。
大约 4 年之前 回复
Csdn user default icon