我希望使用不同的类型来根据其父节点的name属性对子节点的XML内容进行解密。
在下面的示例中,我有两个具有属性"apple“和”桃“的子节点。我想在属性为"apple"时使用"apple"类型,当属性为"peach"时使用Peach类型。基本上,Apple和Peach有非常不同的结构,所以这就是场景。我将如何做到这一点,或者建议的方法是什么?
下面是这个问题的基本设置的游乐场。
<element>
<node name="apple">
<apple>
<color>red<color>
</apple>
</node>
<node name="peach">
<peach>
<size>medium</size>
</peach>
</node>
</element>var x = `...` // xml
type Element struct {
Nodes []struct{
Name string `xml:"name,attr"`
} `xml:"node"`
Apple Apple
Peach Peach
}
type Apple struct { // use this struct if name is "apple"
Color string
}
type Peach struct { // use this struct if name is "peach"
Size string
}
func main() {
e := Element{}
err := xml.Unmarshal([]byte(x), &e)
if err != nil {
panic(err)
}
fmt.Println(e.Apple.Color)
fmt.Println(e.Peach.Size
}发布于 2019-06-17 05:58:41
您可以简单地在Element类型的节点上迭代,并在运行过程中创建Apple和Peach结构,方法是切换它们的Name属性:
for _, element := range e.Nodes {
switch element.Name {
case "apple":
apples = append(apples, Apple{})
case "peach":
peaches = append(peaches, Peach{})
}
}另一个更复杂的解决方案(但也更优雅和实用)是在您的UnmarshalXML类型上实现您自己的Element方法,它将直接用适当的类型填充它:
type Apple struct {
Color string
}
type Peach struct {
Size string
}
type Fruits struct {
Apples []Apple
Peaches []Peach
}
type Element struct {
XMLName xml.Name `xml:"element"`
Nodes []struct {
Name string `xml:"name,attr"`
Apple struct {
Color string `xml:"color"`
} `xml:"apple"`
Peach struct {
Size string `xml:"size"`
} `xml:"peach"`
} `xml:"node"`
}
func (f *Fruits) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var element Element
d.DecodeElement(&element, &start)
for _, el := range element.Nodes {
switch el.Name {
case "apple":
f.Apples = append(f.Apples, Apple{
Color: el.Apple.Color,
})
case "peach":
f.Peaches = append(f.Peaches, Peach{
Size: el.Peach.Size,
})
}
}
return nil
}
func main() {
f := Fruits{}
err := xml.Unmarshal([]byte(x), &f)
if err != nil {
panic(err)
}
fmt.Println("Apples:", f.Apples)
fmt.Println("Peaches", f.Peaches)
}结果:
苹果:桃子
https://stackoverflow.com/questions/56625287
复制相似问题