12.10 XML 数据格式

下面是与 12.9 节 JSON 例子等价的 XML 版本:

  1. <Person>
  2. <FirstName>Laura</FirstName>
  3. <LastName>Lynn</LastName>
  4. </Person>

如同 json 包一样,也有 xml.Marshal()xml.Unmarshal() 从 XML 中编码和解码数据;但这个更通用,可以从文件中读取和写入(或者任何实现了 io.Readerio.Writer 接口的类型)

和 JSON 的方式一样,XML 数据可以序列化为结构,或者从结构反序列化为 XML 数据;这些可以在例子 15.8(twitter_status.go)中看到。

encoding/xml 包实现了一个简单的 XML 解析器(SAX),用来解析 XML 数据内容。下面的例子说明如何使用解析器:

示例 12.17 xml.go

  1. // xml.go
  2. package main
  3. import (
  4. "encoding/xml"
  5. "fmt"
  6. "strings"
  7. )
  8. var t, token xml.Token
  9. var err error
  10. func main() {
  11. input := "<Person><FirstName>Laura</FirstName><LastName>Lynn</LastName></Person>"
  12. inputReader := strings.NewReader(input)
  13. p := xml.NewDecoder(inputReader)
  14. for t, err = p.Token(); err == nil; t, err = p.Token() {
  15. switch token := t.(type) {
  16. case xml.StartElement:
  17. name := token.Name.Local
  18. fmt.Printf("Token name: %s\n", name)
  19. for _, attr := range token.Attr {
  20. attrName := attr.Name.Local
  21. attrValue := attr.Value
  22. fmt.Printf("An attribute is: %s %s\n", attrName, attrValue)
  23. // ...
  24. }
  25. case xml.EndElement:
  26. fmt.Println("End of token")
  27. case xml.CharData:
  28. content := string([]byte(token))
  29. fmt.Printf("This is the content: %v\n", content)
  30. // ...
  31. default:
  32. // ...
  33. }
  34. }
  35. }

输出:

  1. Token name: Person
  2. Token name: FirstName
  3. This is the content: Laura
  4. End of token
  5. Token name: LastName
  6. This is the content: Lynn
  7. End of token
  8. End of token

包中定义了若干 XML 标签类型:StartElement,Chardata(这是从开始标签到结束标签之间的实际文本),EndElement,Comment,Directive 或 ProcInst。

包中同样定义了一个结构解析器:NewParser() 方法持有一个 io.Reader(这里具体类型是 strings.NewReader)并生成一个解析器类型的对象。还有一个 Token() 方法返回输入流里的下一个 XML token。在输入流的结尾处,会返回 (nil,io.EOF)

XML 文本被循环处理直到 Token() 返回一个错误,因为已经到达文件尾部,再没有内容可供处理了。通过一个 type-switch 可以根据一些 XML 标签进一步处理。Chardata 中的内容只是一个 []byte,通过字符串转换让其变得可读性强一些。

链接