解组 XML:根据属性值使用不同的目标类型

我想使用不同的类型根据父节点的 name 属性来解组子节点的 XML 内容。

在下面的示例中,我有 2 个具有属性“apple”和“peach”的子节点。我想Apple在属性为 时"apple"使用Peachtype "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

}


翻过高山走不出你
浏览 164回答 1
1回答

桃花长相依

您可以简单地迭代您的类型的节点,并通过打开它们的属性来Element创建Apple和结构:PeachName&nbsp; &nbsp; for _, element := range e.Nodes {&nbsp; &nbsp; &nbsp; &nbsp; switch element.Name {&nbsp; &nbsp; &nbsp; &nbsp; case "apple":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; apples = append(apples, Apple{})&nbsp; &nbsp; &nbsp; &nbsp; case "peach":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; peaches = append(peaches, Peach{})&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }这是游乐场链接。另一个更复杂的解决方案(但也更优雅和实用)是在您的类型上实现您自己的UnmarshalXML方法,这将直接用正确的类型填充它:Elementtype Apple struct {&nbsp; &nbsp; Color string}type Peach struct {&nbsp; &nbsp; Size string}type Fruits struct {&nbsp; &nbsp; Apples&nbsp; []Apple&nbsp; &nbsp; Peaches []Peach}type Element struct {&nbsp; &nbsp; XMLName xml.Name `xml:"element"`&nbsp; &nbsp; Nodes&nbsp; &nbsp;[]struct {&nbsp; &nbsp; &nbsp; &nbsp; Name&nbsp; string `xml:"name,attr"`&nbsp; &nbsp; &nbsp; &nbsp; Apple struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color string `xml:"color"`&nbsp; &nbsp; &nbsp; &nbsp; } `xml:"apple"`&nbsp; &nbsp; &nbsp; &nbsp; Peach struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Size string `xml:"size"`&nbsp; &nbsp; &nbsp; &nbsp; } `xml:"peach"`&nbsp; &nbsp; } `xml:"node"`}func (f *Fruits) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {&nbsp; &nbsp; var element Element&nbsp; &nbsp; d.DecodeElement(&element, &start)&nbsp; &nbsp; for _, el := range element.Nodes {&nbsp; &nbsp; &nbsp; &nbsp; switch el.Name {&nbsp; &nbsp; &nbsp; &nbsp; case "apple":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.Apples = append(f.Apples, Apple{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color: el.Apple.Color,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; case "peach":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.Peaches = append(f.Peaches, Peach{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Size: el.Peach.Size,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return nil}func main() {&nbsp; &nbsp; f := Fruits{}&nbsp; &nbsp; err := xml.Unmarshal([]byte(x), &f)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println("Apples:", f.Apples)&nbsp; &nbsp; fmt.Println("Peaches", f.Peaches)}这是第二个解决方案的游乐场链接结果:Apples: [{red}]Peaches [{medium}]
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go