在go中迭代xml

时间:2012-08-23 02:41:29

标签: xml struct go xml-parsing

给出类似于以下内容的xml块:

<data>
  <entry>
    ... several nested elements
  </entry>
  <entry>
    ... more nested elements
  </entry>
</data>

如何迭代文档中的每个<entry>元素并将其放入结构中以对其执行某些操作,然后再转到下一个条目?

我已经能够将数据解析并存储到上面的XML块中的结构中,其中只存在一个<entry>元素。也就是说我成功地将这样的东西存储到结构中:

<entry>
  ... several nested elements
</entry>

3 个答案:

答案 0 :(得分:10)

解析xml文件,直到找到入口元素是一种方式:

xmlFile, err := os.Open(filename)
    if err != nil {
    log.Fatal(err)
}
defer xmlFile.Close()
decoder := xml.NewDecoder(xmlFile)
total := 0
for {
    token, _ := decoder.Token()
    if token == nil {
        break
    }
    switch startElement := token.(type) {
        case xml.StartElement:
        if startElement.Name.Local == "entry" {
            // do what you need to do for each entry below
        }
    }
}

答案 1 :(得分:7)

根据http://golang.org/pkg/encoding/xml/

中的文档和示例,我就是这样做的
package main

import (
    "encoding/xml"
    "log"
)

// Represents a <data> element
type Data struct {
    XMLName xml.Name `xml:"data"`
    Entry   []Entry  `xml:"entry"`
}

// Represents an <entry> element
type Entry struct {
    Name string `xml:"name"`
    Age  int    `xml:"age"`
}

// Test data
var testXML string = `
<data>
    <entry>
        <name>John Doe</name>
        <age>28</age>
    </entry>
    <entry>
        <name>Jane Doe</name>
        <age>29</age>
    </entry>
    <entry>
        <name>Bob Doe</name>
        <age>30</age>
    </entry>
    <entry>
        <name>Beth Doe</name>
        <age>31</age>
    </entry>
</data>
`

func main() {

    data := &Data{}

    err := xml.Unmarshal([]byte(testXML), data)
    if err != nil {
        log.Fatal(err)
    }

    for i := 0; i < len(data.Entry); i++ {
        log.Printf("%#v", data.Entry[i])
    }
}

输出是:

main.Entry{Name:"John Doe", Age:28}
main.Entry{Name:"Jane Doe", Age:29}
main.Entry{Name:"Bob Doe", Age:30}
main.Entry{Name:"Beth Doe", Age:31}

答案 2 :(得分:0)

确保正确处理EOF

for {
    // Read tokens from the XML document in a stream.
    t, err := decoder.Token()
    if t == nil {
        if err == nil {
            continue
        }
        if err == io.EOF {
            break
        }
        log.Fatal(err)
    }

    //...
}