首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解除封送XML:根据属性值使用不同的目标类型

解除封送XML:根据属性值使用不同的目标类型
EN

Stack Overflow用户
提问于 2019-06-17 05:41:39
回答 1查看 51关注 0票数 1

我希望使用不同的类型来根据其父节点的name属性对子节点的XML内容进行解密。

在下面的示例中,我有两个具有属性"apple“和”桃“的子节点。我想在属性为"apple"时使用"apple"类型,当属性为"peach"时使用Peach类型。基本上,ApplePeach有非常不同的结构,所以这就是场景。我将如何做到这一点,或者建议的方法是什么?

下面是这个问题的基本设置的游乐场

代码语言:javascript
复制
<element>
    <node name="apple">
        <apple>
            <color>red<color>
        </apple>
    </node>
    <node name="peach"> 
        <peach>
            <size>medium</size>
        </peach>
    </node>
</element>
代码语言:javascript
复制
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
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-17 05:58:41

您可以简单地在Element类型的节点上迭代,并在运行过程中创建ApplePeach结构,方法是切换它们的Name属性:

代码语言:javascript
复制
    for _, element := range e.Nodes {
        switch element.Name {
        case "apple":
            apples = append(apples, Apple{})
        case "peach":
            peaches = append(peaches, Peach{})
        }
    }

这里有一个操场链接

另一个更复杂的解决方案(但也更优雅和实用)是在您的UnmarshalXML类型上实现您自己的Element方法,它将直接用适当的类型填充它:

代码语言:javascript
复制
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)
}

下面是第二个解决方案的操场链接

结果:

苹果:桃子

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56625287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档