在运行时更改结构标记(xml)

There's a struct:

type S struct {
  Value string `xml:"value,attr"`
}

I want to encode the struct to an XML file. However, I want the attribute name of Value to be different in each file:

s1 := S{
  Value: "One"
}

should encode to:

<S value="One"></S>

and

s2 := S{
  Value: "Two"
}

should encode to:

<S category="Two"></S>

So, I need either to change the XML element name somehow, or change the tag on the field. Is this possible?

I checked reflect (https://golang.org/pkg/reflect/#Value.FieldByName), but since FieldByName returns a value type and there are no Set methods, I don't think it's possible to use reflection.

(I don't know why did the other person delete their answer, but here's mine.)

You can either use a combination of ,attr and ,omitempty

type S struct {
    Value    string `xml:"value,attr,omitempty"`
    Category string `xml:"category,attr,omitempty"`
}

(playground: http://play.golang.org/p/C9tRlA80RV) or create a custom xml.MarshalerAttr

type S struct {
    Value Val `xml:",attr"`
}

type Val struct{ string }

func (v Val) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
    if v.string == "One" {
        return xml.Attr{Name: xml.Name{Local: "value"}, Value: v.string}, nil
    }

    return xml.Attr{Name: xml.Name{Local: "category"}, Value: v.string}, nil
}

(playground: http://play.golang.org/p/a1Wd2gonb_).

The first approach is easier but less flexible, and also makes the struct bigger. The second approach is slightly more complex, but also more robust and flexible.