Golang在XML结构中指定顶级标签

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

Golang specify top-level tag in xml structure

问题

所以我正在尝试将一些XML解组或解码为类型(我还不完全清楚它们之间的区别),但似乎无法指定最外层的类型(在这种情况下是<people>)。当我尝试指定此标签时,不会出现错误,但编组值不包含我期望的任何内容。如何指定最外层的标签,为什么第二个赋值没有预期的行为?

  1. package main
  2. import "fmt"
  3. import "encoding/xml"
  4. import "log"
  5. var data string = `
  6. <people>
  7. <person>
  8. <id>46</id>
  9. <name>John Smith</name>
  10. </person>
  11. <person>
  12. <id>3007</id>
  13. <name>Joe Smith</name>
  14. </person>
  15. </people>
  16. `
  17. type Person struct {
  18. Id int `xml:"id"`
  19. Name string `xml:"name"`
  20. }
  21. type People struct {
  22. PersonList []Person `xml:"person"`
  23. }
  24. type Response struct {
  25. PeopleItem People `xml:"people"`
  26. }
  27. func main() {
  28. // 解析People
  29. // 无法指定最外层标签<people></people>
  30. var people People
  31. err := xml.Unmarshal([]byte(data), &people)
  32. if err != nil {
  33. log.Fatal(err)
  34. }
  35. fmt.Println(people)
  36. // 输出"{[{46 John Smith} {3007 Joe Smith}]}"
  37. // 这是合理的
  38. // 尝试解析整个响应,得到的是一个空切片的结构体的结构体
  39. var response Response
  40. err = xml.Unmarshal([]byte(data), &response)
  41. if err != nil {
  42. log.Fatal(err)
  43. }
  44. // response是一个空数组的结构体的结构体
  45. // 为什么会这样?
  46. fmt.Println(response)
  47. // 为什么会输出"{{[]}}"?
  48. }

以上是你提供的代码的翻译。

英文:

So I am trying to Unmarshal or Decode some xml into a type (I am still not entirely clear on what the difference is), and I don't seem to be able to specify the outermost type (in this case &lt;people&gt;). When I try to specify this tag, instead of getting an error, the Marshalled value does not contain any of the content I am expecting. How do you specify the outermost tag and why doesn't the second assignment have the expected behavior?

  1. package main
  2. import &quot;fmt&quot;
  3. import &quot;encoding/xml&quot;
  4. import &quot;log&quot;
  5. var data string = `
  6. &lt;people&gt;
  7. &lt;person&gt;
  8. &lt;id&gt;46&lt;/id&gt;
  9. &lt;name&gt;John Smith&lt;/name&gt;
  10. &lt;/person&gt;
  11. &lt;person&gt;
  12. &lt;id&gt;3007&lt;/id&gt;
  13. &lt;name&gt;Joe Smith&lt;/name&gt;
  14. &lt;/person&gt;
  15. &lt;/people&gt;
  16. `
  17. type Person struct {
  18. Id int `xml:&quot;id&quot;`
  19. Name string `xml:&quot;name&quot;`
  20. }
  21. type People struct {
  22. PersonList []Person `xml:&quot;person&quot;`
  23. }
  24. type Response struct {
  25. PeopleItem People `xml:&quot;people&quot;`
  26. }
  27. func main() {
  28. // parsing People
  29. // cannot specify outermost tag &lt;people&gt;&lt;/people&gt;
  30. var people People
  31. err := xml.Unmarshal([]byte(data), &amp;people)
  32. if err != nil {
  33. log.Fatal(err)
  34. }
  35. fmt.Println(people)
  36. // prints &quot;{[{46 John Smith} {3007 Joe Smith}]}&quot;
  37. // which is reasonable
  38. // attempting to parse entire response, yields struct of struct of empty slice
  39. var response Response
  40. err = xml.Unmarshal([]byte(data), &amp;response)
  41. if err != nil {
  42. log.Fatal(err)
  43. }
  44. // response is struct of struct of empty array
  45. // why does this happen?
  46. fmt.Println(response)
  47. // why does this print &quot;{{[]}}&quot; ?
  48. }

答案1

得分: 2

你可以在不修改传入数据的情况下完成这个操作,你可以使用特殊的XMLName xml.Name字段来设置外部标签,然后使用xml:",chardata"来访问其内容。

以下是一个示例:在Go Playground上试一试

  1. package main
  2. import (
  3. "encoding/xml"
  4. "fmt"
  5. )
  6. type simpleInt struct {
  7. XMLName xml.Name `xml:"integer"`
  8. Int int `xml:",chardata"`
  9. }
  10. type simpleString struct {
  11. XMLName xml.Name `xml:"stringtag"`
  12. String string `xml:",chardata"`
  13. }
  14. type simpleBoolean struct {
  15. XMLName xml.Name `xml:"boolean"`
  16. Boolean bool `xml:",chardata"`
  17. }
  18. func main() {
  19. bint := []byte("<integer>1138</integer>")
  20. bstring := []byte("<stringtag>Caimeo</stringtag>")
  21. btrue := []byte("<boolean>true</boolean>")
  22. bfalse := []byte("<boolean>false</boolean>")
  23. i := simpleInt{}
  24. xml.Unmarshal(bint, &i)
  25. fmt.Println(i, i.Int)
  26. s := simpleString{}
  27. xml.Unmarshal(bstring, &s)
  28. fmt.Println(s, s.String)
  29. m := simpleBoolean{}
  30. xml.Unmarshal(btrue, &m)
  31. fmt.Println(m, m.Boolean)
  32. xml.Unmarshal(bfalse, &m)
  33. fmt.Println(m, m.Boolean)
  34. }
英文:

You can do this without hacking the incoming data, you use the special XMLName xml.Name field to set the outside tag and then use xml:&quot;,chardata&quot; to access it's contents.

Here is an example: Try it on the go playground

  1. package main
  2. import (
  3. &quot;encoding/xml&quot;
  4. &quot;fmt&quot;
  5. )
  6. type simpleInt struct {
  7. XMLName xml.Name `xml:&quot;integer&quot;`
  8. Int int `xml:&quot;,chardata&quot;`
  9. }
  10. type simpleString struct {
  11. XMLName xml.Name `xml:&quot;stringtag&quot;`
  12. String string `xml:&quot;,chardata&quot;`
  13. }
  14. type simpleBoolean struct {
  15. XMLName xml.Name `xml:&quot;boolean&quot;`
  16. Boolean bool `xml:&quot;,chardata&quot;`
  17. }
  18. func main() {
  19. bint := []byte(&quot;&lt;integer&gt;1138&lt;/integer&gt;&quot;)
  20. bstring := []byte(&quot;&lt;stringtag&gt;Caimeo&lt;/stringtag&gt;&quot;)
  21. btrue := []byte(&quot;&lt;boolean&gt;true&lt;/boolean&gt;&quot;)
  22. bfalse := []byte(&quot;&lt;boolean&gt;false&lt;/boolean&gt;&quot;)
  23. i := simpleInt{}
  24. xml.Unmarshal(bint, &amp;i)
  25. fmt.Println(i, i.Int)
  26. s := simpleString{}
  27. xml.Unmarshal(bstring, &amp;s)
  28. fmt.Println(s, s.String)
  29. m := simpleBoolean{}
  30. xml.Unmarshal(btrue, &amp;m)
  31. fmt.Println(m, m.Boolean)
  32. xml.Unmarshal(bfalse, &amp;m)
  33. fmt.Println(m, m.Boolean)
  34. }

答案2

得分: 1

这里有一个简单的解决方案:添加一个新的独特的顶级元素:

  1. var response Response
  2. err = xml.Unmarshal([]byte("<foo>"+data+"</foo>"), &response)
英文:

Here's a lazy solution: add a new, unique top level element:

  1. var response Response
  2. err = xml.Unmarshal([]byte(&quot;&lt;foo&gt;&quot;+data+&quot;&lt;/foo&gt;&quot;), &amp;response)

huangapple
  • 本文由 发表于 2015年10月29日 08:05:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/33403746.html
匿名

发表评论

匿名网友

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

确定