Go 语言

Go 语言教程 Go 语言环境安装 Go 语言结构 Go 语言基础语法 Go 语言数据类型 Go 语言变量 Go 语言常量 Go 语言运算符 Go 语言条件语句 Go 语言 if 语句 Go 语言 if...else 语句 Go 语言 if 语句嵌套 Go 语言 switch 语句 Go 语言 select 语句 Go 语言循环语句 Go 语言 for 循环 Go 语言循环嵌套 Go 语言 break 语句 Go 语言 continue 语句 Go 语言 goto 语句 Go 语言函数 Go 语言函数值传递值 Go 语言函数引用传递值 Go 语言函数作为值 Go 语言函数闭包 Go 语言函数方法 Go 语言变量作用域 Go 语言数组 Go 语言多维数组 Go 语言向函数传递数组 Go 语言指针 Go 语言指针数组 Go 语言指向指针的指针 Go 语言指针作为函数参数 Go 语言结构体 Go 语言切片(Slice) Go 语言范围(Range) Go 语言Map(集合) Go 语言递归函数 Go 语言类型转换 Go 语言接口 Go 错误处理 Go 语言开发工具Go 语言标准库

Go 语言标准库


package xml

import "encoding/xml"

Package xml implements a simple XML 1.0 parser that understands XML name spaces.

Go语言标准库 >>


  • Constants
  • Variables
  • type SyntaxError
  • type TagPathError
  • type UnsupportedTypeError
  • type UnmarshalError
  • type CharData
  • type Comment
  • type Directive
  • type ProcInst
  • type Name
  • type Attr
  • type StartElement
  • type EndElement
  • type Token
  • type Marshaler
  • type Unmarshaler
  • type MarshalerAttr
  • type UnmarshalerAttr
  • func Escape(w io.Writer, s []byte)
  • func EscapeText(w io.Writer, s []byte) error
  • func Marshal(v interface{}) ([]byte, error)
  • func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
  • func Unmarshal(data []byte, v interface{}) error
  • type Decoder
  • type Encoder
  • Examples

    Go语言标准库 >>


  • Encoder
  • MarshalIndent
  • Unmarshal
  • Constants

    const (
        // 适用于本包Marshal输出的一般性XML header
        // 本常数并不会自动添加到本包的输出里,这里提供主要是出于便利的目的
        Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
    )

    Variables

    var HTMLAutoClose = htmlAutoClose

    HTMLAutoClose是应当考虑到自动关闭的HTML元素的集合。

    var HTMLEntity = htmlEntity

    HTMLEntity是标准HTML entity字符到其翻译的映射。

    type SyntaxError

    type SyntaxError struct {
        Msg  string
        Line int
    }

    SyntaxError代表XML输入流的格式错误。

    func (*SyntaxError) Error

    func (e *SyntaxError) Error() string

    type TagPathError

    type TagPathError struct {
        Struct       reflect.Type
        Field1, Tag1 string
        Field2, Tag2 string
    }

    反序列化时,如果字段标签的路径有冲突,就会返回TagPathError。

    func (*TagPathError) Error

    func (e *TagPathError) Error() string

    type UnsupportedTypeError

    type UnsupportedTypeError struct {
        Type reflect.Type
    }

    当序列化时,如果遇到不能转化为XML的类型,就会返回UnsupportedTypeError。

    func (*UnsupportedTypeError) Error

    func (e *UnsupportedTypeError) Error() string

    type UnmarshalError

    type UnmarshalError string

    UnmarshalError代表反序列化时出现的错误。

    func (UnmarshalError) Error

    func (e UnmarshalError) Error() string

    type CharData

    type CharData []byte

    CharData类型代表XML字符数据(原始文本),其中XML转义序列已经被它们所代表的字符取代。

    func (CharData) Copy

    func (c CharData) Copy() CharData

    type Comment

    type Comment []byte

    Comment代表XML注释,格式为<!--comment-->,切片中不包含注释标记<!—和-->。

    func (Comment) Copy

    func (c Comment) Copy() Comment

    type Directive

    type Directive []byte

    Directive代表XML指示,格式为<!directive>,切片中不包含标记<!和>。

    func (Directive) Copy

    func (d Directive) Copy() Directive

    type ProcInst

    type ProcInst struct {
        Target string
        Inst   []byte
    }

    ProcInst代表XML处理指令,格式为<?target inst?>。

    func (ProcInst) Copy

    func (p ProcInst) Copy() ProcInst

    type Name

    type Name struct {
        Space, Local string
    }

    Name代表一个XML名称(Local字段),并指定名字空间(Space)。Decoder.Token方法返回的Token中,Space标识符是典型的URL而不是被解析的文档里的短前缀。

    type Attr

    type Attr struct {
        Name  Name
        Value string
    }

    Attr代表一个XML元素的一条属性(Name=Value)

    type StartElement

    type StartElement struct {
        Name Name
        Attr []Attr
    }

    StartElement代表一个XML起始元素。

    func (StartElement) Copy

    func (e StartElement) Copy() StartElement

    func (StartElement) End

    func (e StartElement) End() EndElement

    返回e对应的XML结束元素。

    type EndElement

    type EndElement struct {
        Name Name
    }

    EndElement代表一个XML结束元素。

    type Token

    type Token interface{}

    Token接口用于保存token类型(CharData、Comment、Directive、ProcInst、StartElement、EndElement)的值。

    func CopyToken

    func CopyToken(t Token) Token

    CopyToken返回一个Token的拷贝。

    type Marshaler

    type Marshaler interface {
        MarshalXML(e *Encoder, start StartElement) error
    }

    实现了Marshaler接口的类型可以将自身序列化为合法的XML元素。

    MarshalXML方法将自身调用者编码为零或多个XML元素。 按照惯例,数组或切片会编码为一系列元素,每个成员一条。使用start作为元素标签并不是必须的,但这么做可以帮助Unmarshal方法正确的匹配XML元素和结构体字段。一个常用的策略是在同一个层次里将每个独立的值对应到期望的XML然后使用e.EncodeElement进行编码。另一个常用的策略是重复调用e.EncodeToken来一次一个token的生成XML输出。编码后的token必须组成零或多个XML元素。

    type Unmarshaler

    type Unmarshaler interface {
        UnmarshalXML(d *Decoder, start StartElement) error
    }

    实现了Unmarshaler接口的类型可以根据自身的XML元素描述反序列化自身。

    UnmarshalXML方法解码以start起始单个XML元素。如果它返回了错误,外层Unmarshal的调用将停止执行并返回该错误。UnmarshalXML方法必须正好“消费”一个XML元素。一个常用的策略是使用d.DecodeElement 将XML分别解码到各独立值,然后再将这些值写入UnmarshalXML的调用者。另一个常用的策略是使用d.Token一次一个token的处理XML对象。UnmarshalXML通常不使用d.RawToken。

    type MarshalerAttr

    type MarshalerAttr interface {
        MarshalXMLAttr(name Name) (Attr, error)
    }

    实现了MarshalerAttr接口的类型可以将自身序列化为合法的XML属性。

    MarshalXMLAttr返回一个值为方法调用者编码后的值的XML属性。使用name作为属性的name并非必须的,但这么做可以帮助Unmarshal方法正确的匹配属性和结构体字段。如果MarshalXMLAttr返回一个零值属性Attr{},将不会生成属性输出。MarshalXMLAttr只用于有标签且标签有"attr"选项的结构体字段。

    type UnmarshalerAttr

    type UnmarshalerAttr interface {
        UnmarshalXMLAttr(attr Attr) error
    }

    实现了UnmarshalerAttr接口的类型可以根据自身的XML属性形式的描述反序列化自身。

    UnmarshalXMLAttr解码单个的XML属性。如果它返回一个错误,外层的Umarshal调用会停止执行并返回该错误。UnmarshalXMLAttr只有在结构体字段的标签有"attr"选项时才被使用。

    func Escape

    func Escape(w io.Writer, s []byte)

    Escape类似EscapeText函数但会忽略返回的错误。本函数是用于保证和Go 1.0的向后兼容。应用于Go 1.1及以后版本的代码请使用EscapeText。

    func EscapeText

    func EscapeText(w io.Writer, s []byte) error

    EscapeText向w中写入经过适当转义的、有明文s具有相同意义的XML文本。

    func 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元素里。

    参见MarshalIndent的例子。如果要求Marshal序列化通道、函数或者映射会返回错误。

    func MarshalIndent

    func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)

    MarshalIndent功能类似Marshal。但每个XML元素会另起一行并缩进,该行以prefix起始,后跟一或多个indent的拷贝(根据嵌套层数)。

    Example
    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\n", err)
    }
    os.Stdout.Write(output)

    Output:

      <person id="13">
          <name>
              <first>John</first>
              <last>Doe</last>
          </name>
          <age>42</age>
          <Married>false</Married>
          <City>Hanga Roa</City>
          <State>Easter Island</State>
          <!-- Need more details. -->
      </person>
    

    func 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元素映射入该值。

    Example
    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\n", v.XMLName)
    fmt.Printf("Name: %q\n", v.Name)
    fmt.Printf("Phone: %q\n", v.Phone)
    fmt.Printf("Email: %v\n", v.Email)
    fmt.Printf("Groups: %v\n", v.Groups)
    fmt.Printf("Address: %v\n", v.Address)

    Output:

    XMLName: xml.Name{Space:"", Local:"Person"}
    Name: "Grace R. Emlin"
    Phone: "none"
    Email: [{home gre@example.com} {work gre@work.com}]
    Groups: [Friends Squash]
    Address: {Hanga Roa Easter Island}
    

    type Decoder

    type Decoder struct {
        // Strict默认设为true,强制要求符合XML规范
        // 如果设为false,则解析器允许输入中包含常见的错误:
        //   * 如果元素缺少结束标签,解析器会虚构一个结束标签以保证返回值来自良好平衡的Token
        //   * 属性值和字符数据中,未知或畸形的字符entity(以&开始的序列)会丢在一边
        //
        // 设置:
        //
        //   d.Strict = false
        //   d.AutoClose = HTMLAutoClose
        //   d.Entity = HTMLEntity
        //
        // 可以创建一个能处理标准HTML的解析器。
        //
        // Strict模式不会强制要求XML名称空间TR,特别注意它不会拒绝使用未定义前缀的名字空间标签
        // 这些标签会将未知前缀作为名字空间URL来记录
        Strict bool
        // 当Strict == false时,AutoClose指定一个元素的集合:
        // 这些元素在开启后就立刻结束,不管有没有对应关闭标签存在
        AutoClose []string
        // Entity字段用于将非标准的实体名映射到替换的字符串
        // parser的行为就好像标准实体映射存在于本字段,即使实际上本字段没有:
        //
        //	"lt": "<",
        //	"gt": ">",
        //	"amp": "&",
        //	"apos": "'",
        //	"quot": `"`,
        Entity map[string]string
        // CharsetReader字段如果非nil,会定义一个函数来生成转换字符集的io.Reader,
        // 将给定的非utf-8字符集转换为utf-8字符集。如果CharsetReader字段为nil
        // 或者返回一个错误,解析将会停止并发挥该错误。CharsetReader的返回值不能都是nil
        CharsetReader func(charset string, input io.Reader) (io.Reader, error)
        // DefaultSpace设置未修饰标签的默认名字空间,就好像整个XML流都包装进有个具有属性
        // xmlns="DefaultSpace"的元素内
        DefaultSpace string
        // 内含隐藏或非导出字段
    }

    Decoder代表一个XML解析器,可以读取输入流的部分数据,该解析器假定输入是utf-8编码的。

    func NewDecoder

    func NewDecoder(r io.Reader) *Decoder

    创建一个从r读取XML数据的解析器。如果r未实现io.ByteReader接口,NewDecoder会为其添加缓存。

    func (*Decoder) Decode

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

    Decode方法功能类似xml.Unmarshal函数,但会从底层读取XML数据并查找StartElement。

    func (*Decoder) DecodeElement

    func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error

    DecodeElement方法的功能类似xml.Unmarshal函数,但它会启出一个指向XML起始标签后将解析结果写入v。当客户端自己读取了一些原始XML token但仍想defer调用Unmarshal处理一些元素时很有用。

    func (*Decoder) Token

    func (d *Decoder) Token() (t Token, err error)

    Token返回输入流里的下一个XML token。在输入流的结尾处,会返回(nil, io.EOF)

    返回的token数据里的[]byte数据引用自解析器内部的缓存,只在下一次调用Token之前有效。如要获取切片的拷贝,调用CopyToken函数或者token的Copy方法。

    成功调用的Token方法会将自我闭合的元素(如<br/>)扩展为分离的起始和结束标签。

    Token方法会保证它返回的StartElement和EndElement两种token正确的嵌套和匹配:如果本方法遇到了不正确的结束标签,会返回一个错误。

    Token方法实现了XML名字空间,细节参见http://www.w3.org/TR/REC-xml-names/。每一个包含在Token里的Name结构体,都会将Space字段设为URL标识(如果可知的话)。如果Token遇到未知的名字空间前缀,它会使用该前缀作为名字空间,而不是报错。

    func (*Decoder) RawToken

    func (d *Decoder) RawToken() (Token, error)

    RawToken方法Token方法,但不会验证起始和结束标签,也不将名字空间前缀翻译为它们相应的URL。

    func (*Decoder) Skip

    func (d *Decoder) Skip() error

    Skip从底层读取token,直到读取到最近一次读取到的起始标签对应的结束标签。如果读取中遇到别的起始标签会进行迭代,因此可以跳过嵌套结构。如果本方法找到了对应起始标签的结束标签,会返回nil;否则返回一个描述该问题的错误。

    type Encoder

    type Encoder struct {
        // 内含隐藏或非导出字段
    }

    Encoder向输出流中写入XML数据。

    Example
    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"}
    enc := xml.NewEncoder(os.Stdout)
    enc.Indent("  ", "    ")
    if err := enc.Encode(v); err != nil {
        fmt.Printf("error: %v\n", err)
    }

    Output:

      <person id="13">
          <name>
              <first>John</first>
              <last>Doe</last>
          </name>
          <age>42</age>
          <Married>false</Married>
          <City>Hanga Roa</City>
          <State>Easter Island</State>
          <!-- Need more details. -->
      </person>
    

    func NewEncoder

    func NewEncoder(w io.Writer) *Encoder

    NewEncoder创建一个写入w的*Encoder。

    func (*Encoder) Encode

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

    Encode将v编码为XML后写入底层。参见Marshal函数获取go到XML转换的细节。在返回前enc会调用Flush。

    func (*Encoder) EncodeElement

    func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error

    EncodeElement将v的XML编码写入底层, 并使用start作为编码的最外层。参见Marshal函数获取go到XML转换的细节。在返回前enc会调用Flush方法。

    func (*Encoder) EncodeToken

    func (enc *Encoder) EncodeToken(t Token) error

    EncodeToken向底层写入一个token。如果StartElement和EndElement的匹配不正确,本方法会返回错误。

    EncodeToken 方法不会调用Flush,因为它通常是更大型操作如Encode或EncodeElement方法的一部分(或者用户自定义的Marshaler接口MarshalXML 方法里调用本方法),这些方法会在结束前Flush。调用者创建一个Encoder并直接使用本方法而不使用Encode或EncodeElement方法的话,必须在结束时调用Flush以保证XML数据写入底层的io.Writer接口。

    EncodeToken写入ProcInst类型Token时,只允许在底层流最开始写入目标是"xml"的ProcInst。

    func (*Encoder) Flush

    func (enc *Encoder) Flush() error

    Flush方法会将缓存中的XML数据写入底层。参见EncodeToken函数获取细节信息。

    func (*Encoder) Indent

    func (enc *Encoder) Indent(prefix, indent string)

    Indent函数设定编码器生成XML数据时的格式化缩进信息。细节请参见MarshalIndent函数。

    Bugs

    XML元素和数据结构体的映射有天生的缺陷:XML元素是依赖顺序的匿名值的集合,而结构体是不依赖顺序的命名值的集合。参见json包获取更适用于数据结构体的文本表示。