golang学习笔记---encoding/xml

xml vs json

xml和json都是文本表示的数据格式:
跨平台
跨系统交换数据

但是,XML更适合标记文档,JSON更适合数据交互。

两者最大的不同在于,XML是一个完整的标记语言,而JSON不是。XML利用标记语言的特性提供了绝佳的延展性(如XPath),在数据存储,扩展及高级检索方面优势明显。

而JSON则由于比XML更加小巧,以及浏览器的内建快速解析支持,使得其更适用于网络数据传输领域。

就可读性而言,两者都具备很好的可读性,但XML文档的可读性更高。
就数据表示和传输性能而言,JSON明显比XML简洁,格式简单,占用带宽少。

例子:json

{"employees":[
    { "firstName":"John", "lastName":"Doe" },
    { "firstName":"Anna", "lastName":"Smith" },
    { "firstName":"Peter", "lastName":"Jones" }
]}

例子:xml

<employees>
    <employee>
        <firstName>John</firstName> <lastName>Doe</lastName>
    </employee>
    <employee>
        <firstName>Anna</firstName> <lastName>Smith</lastName>
    </employee>
    <employee>
        <firstName>Peter</firstName> <lastName>Jones</lastName>
    </employee>
</employees>

JSON
Simple syntax, which results in less “markup” overhead compared to XML.
Easy to use with JavaScript as the markup is a subset of JS object literal notation and has the same basic data types as JavaScript.
JSON Schema for description and datatype and structure validation
JsonPath for extracting information in deeply nested structures

XML
Generalized markup; it is possible to create “dialects” for any kind of purpose
XML Schema for datatype, structure validation. Makes it also possible to create new datatypes
XSLT for transformation into different output formats
XPath/XQuery for extracting information in deeply nested structures
built in support for namespaces

下面开始正式介绍go中如何操作xml的,当然为我们提供了encoding/xml package。

encoding/xml
作用:
Package xml implements a simple XML 1.0 parser that understands XML name spaces.
xml 包实现了一个简单的 XML 1.0 语法分析器, 这个分析器能够理解 XML 命名空间。

常量

const (
        // A generic XML header suitable for use with the output of Marshal.
        // This is not automatically added to any output of this package,
        // it is provided as a convenience.
        Header = `<?xml version="1.0" encoding="UTF-8"?>` + "
"
)

Marshal 函数

func Marshal(v interface{}) ([]byte, error)

Marshal returns the XML encoding of v.
Marshal 在遇到一个数组或切片时, 会对其包含的每个元素进行封装; 在遇到指针时, 会对指针的值进行封装, 并忽略那些未 nil 的指针; 在遇到接口时, 会对接口包含的值进行封装, 并忽略那些值为 nil 的接口; 在遇到其他数据时, Marshal 将写入一个或多个包含这些数据的 XML 元素。

在进行封装时, XML 元素的名字由一系列规则决定, 这些规则的优先级从高到低依次为:

  • 如果给定的数据是一个结构, 那么使用 XMLName 字段的标签作为元素名
  • 使用类型为 Name 的 XMLName 字段的值为元素名
  • 将用于获取数据的结构字段的标签用作元素名
  • 将用于获取数据的结构字段的名字用作元素名
  • 将被封装类型的名字用作元素名

结构中的每个已导出字段都会被封装为相应的元素并包含在 XML 里面, 但以下规则中提到的内容除外:

-XMLName 字段,因为前面提到的原因,会被忽略
- 带有 “-” 标签的字段会被忽略
- 带有 “name,attr” 标签的字段会成为 XML 元素的属性, 其中属性的名字为这里给定的 name
- 带有 ”,attr” 标签的字段会成为 XML 元素的属性, 其中属性的名字为字段的名字
- 带有 ”,chardata” 标签的字段将会被封装为字符数据而不是 XML 元素。
- 带有 ”,cdata” 标签的字段将会被封装为字符数据而不是 XML 元素, 并且这些数据还会被一个或多个

func Unmarshal(data []byte, v interface{}) error

Unmarshal parses the XML-encoded data and stores the result in the value pointed to by v, which must be an arbitrary struct, slice, or string. Well-formed data that does not fit into v is discarded.

例子:

package main

import (
    "encoding/xml"
    "fmt"
    "os"
)

func main() {
    type Address struct {
        City, State string
    }
    type Person struct {
        XMLName   xml.Name `xml:"person"`
        Id        int      `xml:"id,attr"`
        FirstName string   `xml:"name>first"`
        LastName  string   `xml:"name>last"`
        Age       int      `xml:"age"`
        Height    float32  `xml:"height,omitempty"`
        Married   bool
        Address
        Comment string `xml:",comment"`
    }

    v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}
    v.Comment = " Need more details. "
    v.Address = Address{"Hanga Roa", "Easter Island"}

    output, err := xml.MarshalIndent(v, "  ", "    ")
    if err != nil {
        fmt.Printf("error: %v
", err)
    }

    os.Stdout.Write(output)
    fmt.Println("
")
}

输出结果:
这里写图片描述

Unmarshal 函数

func Unmarshal(data []byte, v interface{}) error

Unmarshal 会对 XML 编码的数据进行语法分析, 并将结果储存到 v 指向的值里面, 其中 v 必须是一个任意的(arbitrary)结构、切片或者字符串。 格式良好但是无法放入到 v 里面的数据将被抛弃。
例子:

package main

import (
    "encoding/xml"
    "fmt"
)

func main() {
    type Email struct {
        Where string `xml:"where,attr"`
        Addr  string
    }
    type Address struct {
        City, State string
    }
    type Result struct {
        XMLName xml.Name `xml:"Person"`
        Name    string   `xml:"FullName"`
        Phone   string
        Email   []Email
        Groups  []string `xml:"Group>Value"`
        Address
    }
    v := Result{Name: "none", Phone: "none"}

    data := `
        <Person>
            <FullName>Grace R. Emlin</FullName>
            <Company>Example Inc.</Company>
            <Email where="home">
                <Addr>gre@example.com</Addr>
            </Email>
            <Email where='work'>
                <Addr>gre@work.com</Addr>
            </Email>
            <Group>
                <Value>Friends</Value>
                <Value>Squash</Value>
            </Group>
            <City>Hanga Roa</City>
            <State>Easter Island</State>
        </Person>
    `
    err := xml.Unmarshal([]byte(data), &v)
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }
    fmt.Printf("XMLName: %#v
", v.XMLName)
    fmt.Printf("Name: %q
", v.Name)
    fmt.Printf("Phone: %q
", v.Phone)
    fmt.Printf("Email: %v
", v.Email)
    fmt.Printf("Groups: %v
", v.Groups)
    fmt.Printf("Address: %v
", v.Address)
}

运行结果:
这里写图片描述

Decoder
A Decoder represents an XML parser reading a particular input stream. The parser assumes that its input is encoded in UTF-8.

NewDecoder 函数

func NewDecoder(r io.Reader) *Decoder

创建一个新的读取 r 的 XML 语法分析器。 如果 r 没有实现 io.ByteReader , 那么函数将使用它自有的缓冲机制。

(*Decoder) Decode 方法

func (d *Decoder) Decode(v interface{}) error

执行与 Unmarshal 一样的解码工作, 唯一的不同在于这个方法会通过读取解码器流来查找起始元素。

Encoder
Encoder 负责把 XML 数据写入至输出流里面。

NewEncoder 函数

func NewEncoder(w io.Writer) *Encoder

返回一个能够对 w 进行写入的编码器。

(*Encoder) Encode 方法

func (enc *Encoder) Encode(v interface{}) error

将 XML 编码的 v 写入到流里面。

原文地址:https://www.cnblogs.com/saryli/p/13404520.html