为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
翻过高山走不出你 2023-06-26 16:35:51
我想使用不同的类型根据父节点的 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 = `...` // xmltype 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}
查看完整描述

1 回答

?
桃花长相依

TA贡献1860条经验 获得超8个赞

您可以简单地迭代您的类型的节点,并通过打开它们的属性来Element创建Apple和结构:PeachName


    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)

}

这是第二个解决方案的游乐场链接

结果:


Apples: [{red}]

Peaches [{medium}]


查看完整回答
反对 回复 2023-06-26
  • 1 回答
  • 0 关注
  • 163 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信