如何将嵌套的 XML 元素解组为数组?

huangapple go评论79阅读模式
英文:

How do I unmarshal nested XML elements into an array?

问题

我的XML包含一个预定义元素的数组,但我无法获取该数组。以下是XML的结构:

var xml_data = `<Parent>
                   <Val>Hello</Val>
                   <Children>
                       <Child><Val>Hello</Val></Child>
                       <Child><Val>Hello</Val></Child>
                       <Child><Val>Hello</Val></Child>
                   </Children>
               </Parent>`

这是完整的代码,这是playground链接。运行此代码将获取Parent.Val,但不会获取Parent.Children。

package main

import (
    "fmt"
    "encoding/xml"
)

func main() {

    container := Parent{}
    err := xml.Unmarshal([]byte(xml_data), &container)

    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(container)    
    }
}

var xml_data = `<Parent>
                   <Val>Hello</Val>
                   <Children>
                       <Child><Val>Hello</Val></Child>
                       <Child><Val>Hello</Val></Child>
                       <Child><Val>Hello</Val></Child>
                   </Children>
               </Parent>`

type Parent struct {
    Val string
    Children []Child
}

type Child struct {
    Val string
}

我简化了问题在这里。基本上,我无法解组任何数组,不仅仅是预定义结构的数组。以下是更新后的工作代码。在该示例中,只有一个项目出现在容器接口中。

func main() {

    container := []Child{}
    err := xml.Unmarshal([]byte(xml_data), &container)

    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(container)    
    }

    /* 
        只有一个Child项被获取
    */
}

var xml_data = `
                <Child><Val>Hello</Val></Child>
                <Child><Val>Hello</Val></Child>
                <Child><Val>Hello</Val></Child>
            `

type Child struct {
    Val string
}
英文:

My XML contains an array of predefined elements, but I can't pick up the array. Here is the XML structure:

var xml_data = `&lt;Parent&gt;
		           &lt;Val&gt;Hello&lt;/Val&gt;
			       &lt;Children&gt;
				      &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
				      &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
				      &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
		           &lt;/Children&gt;
	            &lt;/Parent&gt;`

Here is the full code and here is the playground link. Running this will pick up Parent.Val, but not Parent.Children.

package main

import (
	&quot;fmt&quot;
	&quot;encoding/xml&quot;
)

func main() {

	container := Parent{}
	err := xml.Unmarshal([]byte(xml_data), &amp;container)

	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(container)	
	}
}

var xml_data = `&lt;Parent&gt;
		           &lt;Val&gt;Hello&lt;/Val&gt;
			       &lt;Children&gt;
				      &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
				      &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
				      &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
		           &lt;/Children&gt;
	            &lt;/Parent&gt;`

type Parent struct {
	Val string
	Children []Child
}

type Child struct {
	Val string
}

EDIT: I simplified the problem a bit here. Basically I can't unmarshal any array, not just of predefined structure. Below is the updated work code. In that example, only one item ends up in the container interface.

func main() {

	container := []Child{}
	err := xml.Unmarshal([]byte(xml_data), &amp;container)

	if err != nil {
    	fmt.Println(err)
    } else {
    	fmt.Println(container)	
    }

	/* 
		ONLY ONE CHILD ITEM GETS PICKED UP
    */
}

var xml_data = `
	    	&lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
    		&lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
    		&lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
    	`

type Child struct {
	Val string
}

答案1

得分: 33

类型 Parent 结构体 {
Val 字符串
Children []Child xml:"Children>Child" //只需使用 '>'
}

英文:
type Parent struct {
    Val string
    Children []Child  `xml:&quot;Children&gt;Child&quot;`  //Just use the &#39;&gt;&#39;
}

答案2

得分: 7

对于这种嵌套,你还需要为Children元素创建一个结构体:

package main

import (
	"fmt"
	"encoding/xml"
)

func main() {

	container := Parent{}
	err := xml.Unmarshal([]byte(xml_data), &container)
	
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(container)	
	}
}

var xml_data = `<Parent>
			<Val>Hello</Val>
			<Children>
				<Child><Val>Hello</Val></Child>
				<Child><Val>Hello</Val></Child>
				<Child><Val>Hello</Val></Child>
			</Children>
		</Parent>`

type Parent struct {
	Val string
	Children Children
}

type Children struct {
	Child []Child
}

type Child struct {
	Val string
}

也可以在这里查看:Go Playground

请注意,如果使用以下XML结构,你的代码将可以工作(在将变量名从Children更改为Child后):

<Parent>
    <Val>Hello</Val>
    <Child><Val>Hello</Val></Child>
    <Child><Val>Hello</Val></Child>
    <Child><Val>Hello</Val></Child>
</Parent>
英文:

For this kind of nesting, you'll need also a struct for Children element:

package main

import (
	&quot;fmt&quot;
	&quot;encoding/xml&quot;
)

func main() {

	container := Parent{}
	err := xml.Unmarshal([]byte(xml_data), &amp;container)
	
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(container)	
	}
}

var xml_data = `&lt;Parent&gt;
			&lt;Val&gt;Hello&lt;/Val&gt;
			&lt;Children&gt;
				&lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
				&lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
				&lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
			&lt;/Children&gt;
		&lt;/Parent&gt;`

type Parent struct {
	Val string
	Children Children
}

type Children struct {
	Child []Child
}

type Child struct {
	Val string
}

Also pasted here: Go Playground

Note that your code would work (after changing variable name from Children to Child) with this kind of XML structure:

&lt;Parent&gt;
    &lt;Val&gt;Hello&lt;/Val&gt;
    &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
    &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
    &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
&lt;/Parent&gt;

1: https://play.golang.org/p/-rNryBSq01 "Go Playground"

huangapple
  • 本文由 发表于 2016年1月22日 15:48:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/34941539.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定