在运行时更改struct tag(xml)

时间:2015-06-19 14:12:07

标签: xml reflection struct go

有一个结构:

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

我想将结构编码为XML文件。但是,我希望每个文件中的Value属性名称不同:

s1 := S{
  Value: "One"
}

应编码为:

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

s2 := S{
  Value: "Two"
}

应编码为:

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

因此,我需要以某种方式更改XML元素名称,或者更改字段上的标记。这可能吗?

我检查了reflecthttps://golang.org/pkg/reflect/#Value.FieldByName),但由于FieldByName返回了值类型且没有Set方法,我认为不可能使用反射

1 个答案:

答案 0 :(得分:2)

(我不知道为什么对方会删除他们的答案,但这是我的。)

您可以使用,attr,omitempty

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

(playground:http://play.golang.org/p/C9tRlA80RV)或创建自定义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_)。

第一种方法更容易但不太灵活,也使结构更大。第二种方法稍微复杂一些,但也更加健壮和灵活。