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

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

How do I unmarshal nested XML elements into an array?

问题

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

  1. var xml_data = `<Parent>
  2. <Val>Hello</Val>
  3. <Children>
  4. <Child><Val>Hello</Val></Child>
  5. <Child><Val>Hello</Val></Child>
  6. <Child><Val>Hello</Val></Child>
  7. </Children>
  8. </Parent>`

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

  1. package main
  2. import (
  3. "fmt"
  4. "encoding/xml"
  5. )
  6. func main() {
  7. container := Parent{}
  8. err := xml.Unmarshal([]byte(xml_data), &container)
  9. if err != nil {
  10. fmt.Println(err)
  11. } else {
  12. fmt.Println(container)
  13. }
  14. }
  15. var xml_data = `<Parent>
  16. <Val>Hello</Val>
  17. <Children>
  18. <Child><Val>Hello</Val></Child>
  19. <Child><Val>Hello</Val></Child>
  20. <Child><Val>Hello</Val></Child>
  21. </Children>
  22. </Parent>`
  23. type Parent struct {
  24. Val string
  25. Children []Child
  26. }
  27. type Child struct {
  28. Val string
  29. }

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

  1. func main() {
  2. container := []Child{}
  3. err := xml.Unmarshal([]byte(xml_data), &container)
  4. if err != nil {
  5. fmt.Println(err)
  6. } else {
  7. fmt.Println(container)
  8. }
  9. /*
  10. 只有一个Child项被获取
  11. */
  12. }
  13. var xml_data = `
  14. <Child><Val>Hello</Val></Child>
  15. <Child><Val>Hello</Val></Child>
  16. <Child><Val>Hello</Val></Child>
  17. `
  18. type Child struct {
  19. Val string
  20. }
英文:

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

  1. var xml_data = `&lt;Parent&gt;
  2. &lt;Val&gt;Hello&lt;/Val&gt;
  3. &lt;Children&gt;
  4. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  5. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  6. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  7. &lt;/Children&gt;
  8. &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.

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;encoding/xml&quot;
  5. )
  6. func main() {
  7. container := Parent{}
  8. err := xml.Unmarshal([]byte(xml_data), &amp;container)
  9. if err != nil {
  10. fmt.Println(err)
  11. } else {
  12. fmt.Println(container)
  13. }
  14. }
  15. var xml_data = `&lt;Parent&gt;
  16. &lt;Val&gt;Hello&lt;/Val&gt;
  17. &lt;Children&gt;
  18. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  19. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  20. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  21. &lt;/Children&gt;
  22. &lt;/Parent&gt;`
  23. type Parent struct {
  24. Val string
  25. Children []Child
  26. }
  27. type Child struct {
  28. Val string
  29. }

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.

  1. func main() {
  2. container := []Child{}
  3. err := xml.Unmarshal([]byte(xml_data), &amp;container)
  4. if err != nil {
  5. fmt.Println(err)
  6. } else {
  7. fmt.Println(container)
  8. }
  9. /*
  10. ONLY ONE CHILD ITEM GETS PICKED UP
  11. */
  12. }
  13. var xml_data = `
  14. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  15. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  16. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  17. `
  18. type Child struct {
  19. Val string
  20. }

答案1

得分: 33

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

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

答案2

得分: 7

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

  1. package main
  2. import (
  3. "fmt"
  4. "encoding/xml"
  5. )
  6. func main() {
  7. container := Parent{}
  8. err := xml.Unmarshal([]byte(xml_data), &container)
  9. if err != nil {
  10. fmt.Println(err)
  11. } else {
  12. fmt.Println(container)
  13. }
  14. }
  15. var xml_data = `<Parent>
  16. <Val>Hello</Val>
  17. <Children>
  18. <Child><Val>Hello</Val></Child>
  19. <Child><Val>Hello</Val></Child>
  20. <Child><Val>Hello</Val></Child>
  21. </Children>
  22. </Parent>`
  23. type Parent struct {
  24. Val string
  25. Children Children
  26. }
  27. type Children struct {
  28. Child []Child
  29. }
  30. type Child struct {
  31. Val string
  32. }

也可以在这里查看:Go Playground

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

  1. <Parent>
  2. <Val>Hello</Val>
  3. <Child><Val>Hello</Val></Child>
  4. <Child><Val>Hello</Val></Child>
  5. <Child><Val>Hello</Val></Child>
  6. </Parent>
英文:

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

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;encoding/xml&quot;
  5. )
  6. func main() {
  7. container := Parent{}
  8. err := xml.Unmarshal([]byte(xml_data), &amp;container)
  9. if err != nil {
  10. fmt.Println(err)
  11. } else {
  12. fmt.Println(container)
  13. }
  14. }
  15. var xml_data = `&lt;Parent&gt;
  16. &lt;Val&gt;Hello&lt;/Val&gt;
  17. &lt;Children&gt;
  18. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  19. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  20. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  21. &lt;/Children&gt;
  22. &lt;/Parent&gt;`
  23. type Parent struct {
  24. Val string
  25. Children Children
  26. }
  27. type Children struct {
  28. Child []Child
  29. }
  30. type Child struct {
  31. Val string
  32. }

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:

  1. &lt;Parent&gt;
  2. &lt;Val&gt;Hello&lt;/Val&gt;
  3. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  4. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  5. &lt;Child&gt;&lt;Val&gt;Hello&lt;/Val&gt;&lt;/Child&gt;
  6. &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:

确定