Go语言xml格式

幸运草 2020年4月16日20:53:41前端框架评论阅读模式

XML是可扩展标记语言(标准通用标记语言的子集)是一种简单的数据存储语言。
使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立,虽然可扩展标记语言占用的空间比二进制数据要占用更多的空间,但可扩展标记语言极其简单易于掌握和使用。

Go语言中提供了处理XML的标准库 encoding/xml 包,该包实现了一个简单的XML 1.0 解析器(支持XML命名空间)。

Marshal函数

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

Marshal函数返回v的XML编码。

Marshal处理数组或者切片时会序列化每一个元素。Marshal处理指针时,会序列化其指向的值;如果指针为nil,则啥也不输出。Marshal处理接口时,会序列化其内包含的具体类型值,如果接口值为nil,也是不输出。Marshal处理其余类型数据时,会输出一或多个包含数据的XML元素。

XML元素的名字按如下优先顺序获取:

- 如果数据是结构体,其XMLName字段的标签
- 类型为xml.Name的XMLName字段的值
- 数据是某结构体的字段,其标签
- 数据是某结构体的字段,其字段名
- 被序列化的类型的名字

一个结构体的XML元素包含该结构体所有导出字段序列化后的元素,有如下例外:

- XMLName字段,如上所述,会省略
- 具有标签"-"的字段会省略
- 具有标签"name,attr"的字段会成为该XML元素的名为name的属性
- 具有标签",attr"的字段会成为该XML元素的名为字段名的属性
- 具有标签",chardata"的字段会作为字符数据写入,而非XML元素
- 具有标签",innerxml"的字段会原样写入,而不会经过正常的序列化过程
- 具有标签",comment"的字段作为XML注释写入,而不经过正常的序列化过程,该字段内不能有"--"字符串
- 标签中包含"omitempty"选项的字段如果为空值会省略
  空值为false、0、nil指针、nil接口、长度为0的数组、切片、映射
- 匿名字段(其标签无效)会被处理为其字段是外层结构体的字段

如果一个字段的标签为"a>b>c",则元素c将会嵌套进其上层元素a和b中。如果该字段相邻的字段标签指定了同样的上层元素,则会放在同一个XML元素里。

Unmarshal函数

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

Unmarshal解析XML编码的数据并将结果存入v指向的值。v只能指向结构体、切片或者和字符串。良好格式化的数据如果不能存入v,会被丢弃。

因为Unmarshal使用reflect包,它只能填写导出字段。本函数好似用大小写敏感的比较来匹配XML元素名和结构体的字段名/标签键名。

Unmarshal函数使用如下规则将XML元素映射到结构体字段上。这些规则中,字段标签指的是结构体字段的标签键'xml'对应的值(参见上面的例子):

* 如果结构体字段的类型为字符串或者[]byte,且标签为",innerxml",
  Unmarshal函数直接将对应原始XML文本写入该字段,其余规则仍适用。
* 如果结构体字段类型为xml.Name且名为XMLName,Unmarshal会将元素名写入该字段
* 如果字段XMLName的标签的格式为"name"或"namespace-URL name",
  XML元素必须有给定的名字(以及可选的名字空间),否则Unmarshal会返回错误。
* 如果XML元素的属性的名字匹配某个标签",attr"为字段的字段名,或者匹配某个标签为"name,attr"
  的字段的标签名,Unmarshal会将该属性的值写入该字段。
* 如果XML元素包含字符数据,该数据会存入结构体中第一个具有标签",chardata"的字段中,
  该字段可以是字符串类型或者[]byte类型。如果没有这样的字段,字符数据会丢弃。
* 如果XML元素包含注释,该数据会存入结构体中第一个具有标签",comment"的字段中,
  该字段可以是字符串类型或者[]byte类型。如果没有这样的字段,字符数据会丢弃。
* 如果XML元素包含一个子元素,其名称匹配格式为"a"或"a>b>c"的标签的前缀,反序列化会深入
  XML结构中寻找具有指定名称的元素,并将最后端的元素映射到该标签所在的结构体字段。
  以">"开始的标签等价于以字段名开始并紧跟着">" 的标签。
* 如果XML元素包含一个子元素,其名称匹配某个结构体类型字段的XMLName字段的标签名,
  且该结构体字段本身没有显式指定标签名,Unmarshal会将该元素映射到该字段。
* 如果XML元素的包含一个子元素,其名称匹配够格结构体字段的字段名,且该字段没有任何模式选项
  (",attr"、",chardata"等),Unmarshal会将该元素映射到该字段。
* 如果XML元素包含的某个子元素不匹配以上任一条,而存在某个字段其标签为",any",
  Unmarshal会将该元素映射到该字段。
* 匿名字段被处理为其字段好像位于外层结构体中一样。
* 标签为"-"的结构体字段永不会被反序列化填写。

Unmarshal函数将XML元素写入string或[]byte时,会将该元素的字符数据串联起来作为值,目标[]byte不能是nil。

Unmarshal函数将属性写入string或[]byte时,会将属性的值以字符串/切片形式写入。

Unmarshal函数将XML元素写入切片时,会将切片扩展并将XML元素的子元素映射入新建的值里。

Unmarshal函数将XML元素/属性写入bool值时,会将对应的字符串转化为布尔值。

Unmarshal函数将XML元素/属性写入整数或浮点数类型时,会将对应的字符串解释为十进制数字。不会检查溢出。

Unmarshal函数将XML元素写入xml.Name类型时,会记录元素的名称。

Unmarshal函数将XML元素写入指针时,会申请一个新值并将XML元素映射入该值。

xml转换应用

package main

import (
    "encoding/xml"
    "fmt"
)

type School struct {
    Name    string `xml:"name"`
    Age     int    `xml:"-"`
    slogan  string `xml:"slogan"`
    Courses []string
}

func XmlStruct() {
    var arg = School{
        Name:    "oldboy",
        Age:     100,
        slogan:  "老男孩IT教育,只培养技术精英。",
        Courses: []string{"oldboy", "Linux", "Python", "Golang", "Java", "DBA"},
    }
    data, err := xml.Marshal(arg)
    if err != nil {
        fmt.Printf("xml.marshal failed, err : %vn", err)
        return
    }
    var reply School
    err = xml.Unmarshal(data, &reply)

    fmt.Printf("struct 类型nXML序列化 string(data) => %snXML反序列化 reply => %vn", string(data), reply)
}

func main() {
    XmlStruct()
}

运行结果:

struct 类型
XML序列化 string(data) => <School><name>oldboy</name><Courses>oldboy</Courses><Courses>Linux</Courses><Courses>Python</Courses><Courses>Golang</Courses><Courses>Java</Courses><Courses>DBA</Courses></School>
XML反序列化 reply => {oldboy 0  [oldboy Linux Python Golang Java DBA]}

特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

  • 赞助本站
  • 微信扫一扫
  • weinxin
  • 加入Q群
  • QQ扫一扫
  • weinxin
幸运草
Go语言接口规则 前端框架

Go语言接口规则

Go语言接口规则 接口是一个或多个方法签名的集合。任何类型的方法集中只要拥有该接口对应的全部方法签名。就表示它 "实现" 了该接口,无须在该类型上显式声明实现了哪个接口。对应方法,是指有相同名称、参数...
Go语言中处理 HTTP 服务器 前端框架

Go语言中处理 HTTP 服务器

1 概述 包 net/http 提供了HTTP服务器端和客户端的实现。本文说明关于服务器端的部分。 快速开始: package main import (   "log"   "net/http" )...

发表评论