aruthecrsov
aruthecrsov

Reputation: 41

Zero output after parsing xml

I'm having trouble parsing xml in Go.

An xml example with only one 'game':

<root>
<game>
<id>z0046-54</id>
<creation_time>1612988348</creation_time>
<black>aivo</black>
<white>gosha</white>
<turn_color>white</turn_color>
<board>h8 h9 i6 i8 j6 g9 j9 j7 k6 l6 g10 k7 l7 i10 i9 g6 j10 k11 j5 i4 k4 l3 h5 m5 j8 j11 g8 h7 i7 l5 k9 h6 m7 k12 l13 n6 m8 n9 m9</board>
<moves>h8 swap h9 i6 swap i8 swap j6 g9 j9 j7 k6 l6 g10 k7 l7 i10 i9 g6 j10 k11 j5 i4 k4 l3 h5 m5 j8 j11 g8 h7 i7 l5 k9 h6 m7 k12 l13 n6 m8 n9 m9</moves>
<alt5></alt5>
<proposition></proposition>
<proposer></proposer>
<status>finished</status>
<rule>taraguchi10</rule>
<time>7776000</time>
<tpm>2592000</tpm>
<start_time>1612988348</start_time>
<end_time>1613736768</end_time>
<winner>black</winner>
<winby>resign</winby>
<time_left_black>7536372</time_left_black>
<time_left_white>7267413</time_left_white>
<tid>z0046</tid>
</game>

</root>

I want to get slice of games from xml. Code with game and all file sctructs:

package data

type ro struct {
    RoGames []roGame `xml:"root>game"`
}
type roGame struct {
    Id     int    `xml:"game>id"`
    Black  string `xml:"game>black"`
    White  string `xml:"game>white"`
    Moves  string `xml:"game>moves"`
    Alt5   string `xml:"game>alt_5"`
    Rule   string `xml:"game>rule"`
    Winner string `xml:"game>winner"`
}

Another file:

package data

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

func Xml() {

    xmlFile, err := os.Open("data.xml")
    if err != nil {
        panic(err)
    }
    fmt.Println("Successfully Opened xml")

    defer xmlFile.Close()

    inBytes, err := ioutil.ReadAll(xmlFile)
    if err != nil {
        panic(err)
    }
    var ro ro
    xml.Unmarshal(inBytes, &ro)
    fmt.Println(ro)

}

I am calling 'Xml' function from main package and getting this output:

Successfully Opened xml
{[]}

I think parsing process is ok, and this is problem with sctructs.

Upvotes: 1

Views: 66

Answers (1)

xarantolus
xarantolus

Reputation: 2029

The struct tag for RoGames in the ro struct includes root, but it doesn't seem to need to. If you change it to game, parsing seems to do the correct thing:

type ro struct {
    RoGames []roGame `xml:"game"`
}

And since you're then already "in" the game tag, you don't need to add it to every field of the roGame struct.

Another thing to note is that you should handle all errors while parsing, because with the fix above a new error occurs. One only notices it when adjusting the parser code:

var ro ro
err = xml.Unmarshal(inBytes, &ro)
if err != nil {
    panic(err)
}

At first, this outputs the following:

panic: strconv.ParseInt: parsing "z0046-54": invalid syntax

This is because the Id field in your struct definition is an int, but the data for it is z0046-54, which cannot be interpreted as an integer.

So if we change that, we get this for your roGame struct:

type roGame struct {
    Id     string `xml:"id"` // <-- Change is here
    Black  string `xml:"black"`
    White  string `xml:"white"`
    Moves  string `xml:"moves"`
    Alt5   string `xml:"alt_5"`
    Rule   string `xml:"rule"`
    Winner string `xml:"winner"`
}

Now the code outputs your data in a useful format. You can also use tools like this to generate your structs, it makes it easier and is less error-prone.

Upvotes: 2

Related Questions