使用Go生成XML文件时,如何创建doctype声明?

21

Go的xml包非常出色,使得处理XML变得非常容易。但有一件事我不确定如何做:当从本地结构创建XML文档时,如何指定文档类型?

例如,这些结构:

type Person struct {
    XMLName    xml.Name `xml:"person"`
    FirstName  string   `xml:"firstName"`
    MiddleName string   `xml:"middleName"`
    LastName   string   `xml:"lastName"`
    Age        int64    `xml:"age"`
    Skills     []Skill  `xml:"skills"`
}

type Skill struct {
    XMLName        xml.Name `xml:"skill"`
    Name           string   `xml:"skillName"`
    YearsPracticed int64    `xml:"practice"`
}

将生成这样的XML:

<person>
    <firstName>Bob</firstName>
    <middleName></middleName>
    <lastName>Jones</middleName>
    <age>23</age>
    <skills>
        <skill>
            <skillName>Cooking</skillName>
            <practice>3</practice>
        </skill>
        <skill>
            <skillName>Basketball</skillName>
            <practice>4</practice>
        </skill>
    </skills>
</person>

这很棒,但我该怎么做才能得到这个:

<?xml version="1.0" encoding="UTF-8"?>
<person>
    <firstName>Bob</firstName>
    <middleName></middleName>
    ...

这似乎太简单了,但只需要进行字符串追加吗?

另一方面,如果你想将带有文档类型的文本块反序列化为一组结构体,Go的XML解析器会如何处理? 忽略它?

2个回答

35

只需将您的编组字节附加到标题即可。如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"?>` + "\n"
)

所以,这样做就可以了:

myString, err := xml.MarshalIndent(...) // abbreviated here
myString = []byte(xml.Header + string(myString))

我找到的一个可用的工作示例(不是我的代码),链接在:http://play.golang.org/p/Rbfb717tvh


谢谢,我在软件包源代码中忽略了这个。有关标题在取消编组期间如何处理的任何数据吗? - Matt Mc
我想你可能能够收集它,因为简要查看源代码显示它们正在解析<?前缀标签;我不确定所需的结构标记是什么。也许是“xml”。 - Momer
由于在[]bytestring之间进行转换涉及到内存复制,这样的事情是不幸的。毕竟,myString可能非常大。 - Torsten Bronger

7
另一种值得一提的方法是使用来自Go的本地XML编码器,与常见的marshal函数相比,在处理XML流或计划处理较大的XML文件时更加适用。在这种情况下,您将首先创建要编码的结构对象,然后创建*File引用,并将xml.Header写入其中,步骤与之前类似。
xmlFile, err := os.Create("my-file.xml")
if err != nil {
    fmt.Println("Error creating XML file: ", err)
    return
}
xmlFile.WriteString(xml.Header)

接下来,您需要创建XML编码器,设置其缩进,并最终将必要的结构体编码为XML文件:

encoder := xml.NewEncoder(xmlFile)
encoder.Indent("", "\t")
err = encoder.Encode(&myStruct)
if err != nil {
    fmt.Println("Error encoding XML to file: ", err)
    return
}

你应该在此之后看到所需的文档头的XML文件。
以下是使用您提供的示例快速创建POF:
package main

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

// Person represents a <person> node in the XML
type Person struct {
    XMLName    xml.Name `xml:"person"`
    FirstName  string   `xml:"firstName"`
    MiddleName string   `xml:"middleName"`
    LastName   string   `xml:"lastName"`
    Age        int64    `xml:"age"`
    Skills     []Skill  `xml:"skills"`
}

// Skill represents a <skill> node in the XML
type Skill struct {
    XMLName        xml.Name `xml:"skill"`
    Name           string   `xml:"skillName"`
    YearsPracticed int64    `xml:"practice"`
}

func main() {
    person := Person{
        FirstName:  "Bob",
        MiddleName: "",
        LastName:   "Jones",
        Age:        23,
        Skills: []Skill{
            {
                Name:           "Cooking",
                YearsPracticed: 3,
            },
            {
                Name:           "Basketball",
                YearsPracticed: 4,
            },
        },
    }

    xmlFile, err := os.Create("person.xml")
    if err != nil {
        fmt.Println("Error creating XML file: ", err)
        return
    }
    xmlFile.WriteString(xml.Header)
    encoder := xml.NewEncoder(xmlFile)
    encoder.Indent("", "\t")
    err = encoder.Encode(&person)
    if err != nil {
        fmt.Println("Error encoding XML to file: ", err)
        return
    }
}

这将生成以下XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<person>
    <firstName>Bob</firstName>
    <middleName></middleName>
    <lastName>Jones</lastName>
    <age>23</age>
    <skill>
        <skillName>Cooking</skillName>
        <practice>3</practice>
    </skill>
    <skill>
        <skillName>Basketball</skillName>
        <practice>4</practice>
    </skill>
</person>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接