使用Go解析XML,其中包含多个小写元素。

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

Parsing XML with Go, having multiple elements in lowercase

问题

我不知道如何使这段代码工作。我只是尝试解析一个简单的XML文件,像这样:

  1. package main
  2. import (
  3. "encoding/xml"
  4. "fmt"
  5. )
  6. type Data struct {
  7. XMLName xml.Name `xml:"data"`
  8. Nam string `xml:"nam,attr"`
  9. }
  10. type Struct struct {
  11. XMLName xml.Name `xml:"struct"`
  12. Data []Data
  13. }
  14. func main() {
  15. x := `
  16. <struct>
  17. <data nam="MESSAGE_TYPE">
  18. </data>
  19. <data nam="MESSAGE_TYPE2">
  20. </data>
  21. </struct>
  22. `
  23. s := Struct{}
  24. err := xml.Unmarshal([]byte(x), &s)
  25. if err != nil {
  26. panic(err)
  27. }
  28. fmt.Printf("%v\n", s)
  29. fmt.Println(s.Data)
  30. }

我得到的结果是:

  1. {{ struct} []}
  2. []
  3. 但是当我将"data"元素改为大写时,像这样:
  4. ```go
  5. package main
  6. import (
  7. "encoding/xml"
  8. "fmt"
  9. )
  10. type Data struct {
  11. XMLName xml.Name `xml:"Data"`
  12. Nam string `xml:"nam,attr"`
  13. }
  14. type Struct struct {
  15. XMLName xml.Name `xml:"struct"`
  16. Data []Data
  17. }
  18. func main() {
  19. x := `
  20. <struct>
  21. <Data nam="MESSAGE_TYPE">
  22. </Data>
  23. <Data nam="MESSAGE_TYPE2">
  24. </Data>
  25. </struct>
  26. `
  27. s := Struct{}
  28. err := xml.Unmarshal([]byte(x), &s)
  29. if err != nil {
  30. panic(err)
  31. }
  32. fmt.Printf("%v\n", s)
  33. fmt.Println(s.Data)
  34. }

我得到的结果是:

  1. {{ struct} [{{ Data} MESSAGE_TYPE} {{ Data} MESSAGE_TYPE2}]}
  2. [{{ Data} MESSAGE_TYPE} {{ Data} MESSAGE_TYPE2}]

有人能告诉我为什么吗?

英文:

I don't know how to make this code work. I'm just trying to parse a simple XML file like this:

  1. package main
  2. import (
  3. &quot;encoding/xml&quot;
  4. &quot;fmt&quot;
  5. )
  6. type Data struct {
  7. XMLName xml.Name `xml:&quot;data&quot;`
  8. Nam string `xml:&quot;nam,attr&quot;`
  9. }
  10. type Struct struct {
  11. XMLName xml.Name `xml:&quot;struct&quot;`
  12. Data []Data
  13. }
  14. func main() {
  15. x := `
  16. &lt;struct&gt;
  17. &lt;data nam=&quot;MESSAGE_TYPE&quot;&gt;
  18. &lt;/data&gt;
  19. &lt;data nam=&quot;MESSAGE_TYPE2&quot;&gt;
  20. &lt;/data&gt;
  21. &lt;/struct&gt;
  22. `
  23. s := Struct{}
  24. err := xml.Unmarshal([]byte(x), &amp;s)
  25. if err != nil {
  26. panic(err)
  27. }
  28. fmt.Printf(&quot;%v\n&quot;, s)
  29. fmt.Println(s.Data)
  30. }

what I got is:

  1. {{ struct} []}
  2. []

But when I change the "data" elements to uppercase, like this:

  1. package main
  2. import (
  3. &quot;encoding/xml&quot;
  4. &quot;fmt&quot;
  5. )
  6. type Data struct {
  7. XMLName xml.Name `xml:&quot;Data&quot;`
  8. Nam string `xml:&quot;nam,attr&quot;`
  9. }
  10. type Struct struct {
  11. XMLName xml.Name `xml:&quot;struct&quot;`
  12. Data []Data
  13. }
  14. func main() {
  15. x := `
  16. &lt;struct&gt;
  17. &lt;Data nam=&quot;MESSAGE_TYPE&quot;&gt;
  18. &lt;/Data&gt;
  19. &lt;Data nam=&quot;MESSAGE_TYPE2&quot;&gt;
  20. &lt;/Data&gt;
  21. &lt;/struct&gt;
  22. `
  23. s := Struct{}
  24. err := xml.Unmarshal([]byte(x), &amp;s)
  25. if err != nil {
  26. panic(err)
  27. }
  28. fmt.Printf(&quot;%v\n&quot;, s)
  29. fmt.Println(s.Data)
  30. }

I got this:

  1. {{ struct} [{{ Data} MESSAGE_TYPE} {{ Data} MESSAGE_TYPE2}]}
  2. [{{ Data} MESSAGE_TYPE} {{ Data} MESSAGE_TYPE2}]

Can anybody tell me why?

答案1

得分: 7

如果您在结构字段上没有放置XML注释,字段的名称将被视为XML元素的名称。

在encoding/xml包的Unmarshal文档中,我们可以找到以下内容:

Unmarshal使用以下规则将XML元素映射到结构体。在规则中,字段的标签指的是结构体字段标签中与键'xml'关联的值(参见上面的示例)。

  • 如果XML元素包含一个子元素,其名称与没有任何模式标志(",attr"、",chardata"等)的字段匹配,Unmarshal将该子元素映射到该结构体字段。

匹配是区分大小写的,所以在您的情况下会有所区别。

我建议像这样对结构进行注释以适应实际数据:

  1. type Struct struct {
  2. XMLName xml.Name `xml:"struct"`
  3. Data []Data `xml:"data"`
  4. }
英文:

If you do not put XML annotation on the structure field the name of the field is taken as name of XML element.

In the documentation on Unmarshal in endoding/xml package we can find the following:

> Unmarshal maps an XML element to a struct using the following rules. In the rules, the tag of a field refers to the value associated with the key 'xml' in the struct field's tag (see the example above).

> - If the XML element contains a sub-element whose name matches a
field without any mode flags (",attr", ",chardata", etc), Unmarshal
maps the sub-element to that struct field.

The matching is case sensitive so it makes a difference in your case.

I recommend annotating the structure like this to fit the actual data:

  1. type Struct struct {
  2. XMLName xml.Name `xml:&quot;struct&quot;`
  3. Data []Data `xml:&quot;data&quot;`
  4. }

huangapple
  • 本文由 发表于 2014年11月2日 23:15:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/26700825.html
匿名

发表评论

匿名网友

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

确定