英文:
Change struct tag (xml) at runtime
问题
有一个结构体:
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元素名字,或者改变字段上的标签。这可行吗?
我查看了reflect
(https://golang.org/pkg/reflect/#Value.FieldByName),但是由于FieldByName
返回一个值类型,并且没有Set
方法,我认为不能使用反射来实现。
英文:
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.
答案1
得分: 2
你可以使用,attr
和,omitempty
的组合方式来实现。
type S struct {
Value string `xml:"value,attr,omitempty"`
Category string `xml:"category,attr,omitempty"`
}
或者你可以创建一个自定义的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
}
第一种方法更简单但不够灵活,而且会使结构体变得更大。第二种方法稍微复杂一些,但更健壮和灵活。
英文:
(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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论