Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating through xml in go

Given a block of xml similar to the following:

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

How can I iterate over each <entry> element in the document and put it into a struct to perform some operations on it before moving to the next entry?

I'm already able to parse and store data into structs from a block of XML as above where only a single <entry> element exists. That is to say that I am successfully able to store something like this into a struct:

<entry>
  ... several nested elements
</entry>
like image 616
cmhobbs Avatar asked Dec 03 '22 02:12

cmhobbs


2 Answers

Parsing an xmml file until you get to the entry elements is one way:

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
        }
    }
}
like image 84
VonC Avatar answered Dec 14 '22 23:12

VonC


Here's how I'd do it, per the documentation and examples in 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])
    }
}

Output is:

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}
like image 24
Kai Avatar answered Dec 14 '22 22:12

Kai