转到XML编组和根元素

sca*_*off 4 xml-serialization go

在Go中,您可以将结构编组为XML,例如:

package main

import (
    "encoding/xml"
    "fmt"
    )

type person struct {
    Name string
    Starsign string
}

func main() {
    p := &person{"John Smith", "Capricorn"}
    b,_ := xml.MarshalIndent(p,"","   ")
    fmt.Println(string(b))
}
Run Code Online (Sandbox Code Playgroud)

产生输出:

<person>
   <Name>John Smith</Name>
   <Starsign>Capricorn</Starsign>
</person>
Run Code Online (Sandbox Code Playgroud)

我的问题是,人类型是小写的"p",因为我希望它是私有的包.但我更喜欢XML元素是大写的:<Person>.结构中的字段可以使用标记(例如`xml:"name"`)对结构字段编组到其他名称,但这似乎不是结构类型的选项.

我有一个使用模板的解决方法,但知道一个更好的答案会很高兴.

Ste*_*erg 6

根据encoding/xml.Marshal文档:

XML元素的名称取自优先顺序:

  • XMLName字段上的标记,如果数据是结构
  • xml.Name类型的XMLName字段的值
  • 用于获取数据的struct字段的标记
  • 用于获取数据的struct字段的名称
  • 编组类型的名称

您可以在结构中的XMLName字段上使用标记来覆盖person结构的XML标记名称.为了避免将它放在你的实际person结构中,你可以创建一个嵌入你正在编组的人结构的匿名结构.

package main

import (
    "encoding/xml"
    "fmt"
)

type person struct {
    Name        string
    Starsign    string
}

func marshalPerson(p person) ([]byte, error) {
    tmp := struct {
        person
        XMLName struct{}    `xml:"Person"`
    }{person: p}

    return xml.MarshalIndent(tmp, "", "   ")
}

func main() {
    p := person{"John Smith", "Capricorn"}
    b, _ := marshalPerson(p)
    fmt.Println(string(b))
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这也有效,尽管我认为它不是特别漂亮。

然而,这对我来说比 5 年前接受的其他解决方案更直接。

package main

import (
    "encoding/xml"
    "fmt"
    )

type person struct {
    XMLName xml.Name
    Name string
    Starsign string
}

func main() {
    p := &person{xml.Name{Local: "Person"}, "John Smith", "Capricorn"}
    b,_ := xml.MarshalIndent(p,"","   ")
    fmt.Println(string(b))
}
Run Code Online (Sandbox Code Playgroud)