英文:
Go XML parsing: set missing attributes to "true"
问题
以下是翻译好的内容:
下面的代码片段:
package main
import (
"encoding/xml"
"fmt"
)
func main() {
var r struct {
Item []struct {
Value string `xml:"value,attr"`
Flag bool `xml:"flag,attr"`
} `xml:"item"`
}
xml.Unmarshal([]byte(`
<result>
<item value="1" flag="false" />
<item value="2" flag="true" />
<item value="3" />
</result>`,
), &r)
fmt.Printf("%+v\n", r)
}
将打印以下结果:
{Item:[{Value:1 Flag:false} {Value:2 Flag:true} {Value:3 Flag:false}]}
在某些元素中,flag
属性可能会缺失(例如上面的 item 3),但我希望它的默认值为 true
,而不是 false
。
- 我不能在构造函数中赋值,因为我不知道数组中元素的数量。
- 我不能使用实现了
UnmarshalerAttr
接口的自定义类型,并在解组过程中进行赋值,因为如果属性缺失,UnmarshalXMLAttr
方法不会被调用。 - 我可以将其定义为指针,然后检查是否为 nil,然后设置为 true,但这样做很繁琐且容易出错。
我该如何解决这个问题?
英文:
The snippet below,
package main
import (
"encoding/xml"
"fmt"
)
func main() {
var r struct {
Item []struct {
Value string `xml:"value,attr"`
Flag bool `xml:"flag,attr"`
} `xml:"item"`
}
xml.Unmarshal([]byte(`
<result>
<item value="1" flag="false" />
<item value="2" flag="true" />
<item value="3" />
</result>`,
), &r)
fmt.Printf("%+v\n", r)
}
Will print the following result:
{Item:[{Value:1 Flag:false} {Value:2 Flag:true} {Value:3 Flag:false}]}
In some elements, flag
attribute will be missing (e.g. item 3 above), but I want it to take the default value of true
, instead than false
.
- I cannot assign it in the constructor, because I don't know the number of elements in the array upfront.
- I cannot use a custom type that implements
UnmarshalerAttr
and assign during unmarshaling because if the attribute is missing,UnmarshalXMLAttr
is not run. - I could make it a pointer, and then check if nil, then true, but that's just gross and error-prone.
How would I go about doing this?
答案1
得分: 5
你是正确的,你不能使用UnmarshalerAttr
来实现这个功能。相反,ResultItem
可以实现Unmarshaler
,这将允许你设置默认的属性值:
package main
import (
"encoding/xml"
"fmt"
)
type ResultItem struct {
Value string `xml:"value,attr"`
Flag bool `xml:"flag,attr"`
}
func (ri *ResultItem) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type resultItem ResultItem // new type to prevent recursion
item := resultItem{
Flag: true,
}
if err := d.DecodeElement(&item, &start); err != nil {
return err
}
*ri = (ResultItem)(item)
return nil
}
func main() {
var r struct {
Item[] ResultItem `xml:"item"`
}
xml.Unmarshal([]byte(`
<result x="ASDASD">
<item value="1" flag="false" />
<item value="2" flag="true" />
<item value="3" />
</result>`,
), &r)
fmt.Printf("%+v\n", r)
}
希望对你有帮助!
英文:
You're correct in that you cannot use UnmarshalerAttr
for this. Instead, ResultItem
can implement Unmarshaler
which will allow you to set default attribute values:
package main
import (
"encoding/xml"
"fmt"
)
type ResultItem struct {
Value string `xml:"value,attr"`
Flag bool `xml:"flag,attr"`
}
func (ri *ResultItem) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type resultItem ResultItem // new type to prevent recursion
item := resultItem{
Flag: true,
}
if err := d.DecodeElement(&item, &start); err != nil {
return err
}
*ri = (ResultItem)(item)
return nil
}
func main() {
var r struct {
Item[] ResultItem `xml:"item"`
}
xml.Unmarshal([]byte(`
<result x="ASDASD">
<item value="1" flag="false" />
<item value="2" flag="true" />
<item value="3" />
</result>`,
), &r)
fmt.Printf("%+v\n", r)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论