使用Go解析XML文件

I'm new on Go. I have a task to do where I have a xml file with the following structure. There many other tag record in this file.

I need to read all the records, and print the information about the Kind of music but only where datafield tag is equal "650" and the subfield code tag = "a".

<record>
  <leader>01153cjm a22002771a 4500</leader>
  <controlfield tag="001">   00000838 </controlfield>
  <controlfield tag="003">DLC</controlfield>
  <controlfield tag="005">20030506181700.0</controlfield>
  <controlfield tag="007">sd|zsngnnmmned</controlfield>
  <controlfield tag="008">000824s1998    nyuppn                  d</controlfield>
  <datafield tag="050" ind1="0" ind2="0">
    <subfield code="a">SDA 16949</subfield>
  </datafield>
  <datafield tag="010" ind1=" " ind2=" ">
    <subfield code="a">   00000838 </subfield>
  </datafield>
  <datafield tag="020" ind1=" " ind2=" ">
    <subfield code="c">$15.98</subfield>
  </datafield>
  <datafield tag="024" ind1="1" ind2=" ">
    <subfield code="a">601215312621</subfield>
  </datafield>
  <datafield tag="650" ind1=" " ind2="0">
    <subfield code="a">Rap (Music)</subfield>
  </datafield>
</record>

My code is:

package main

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

type Record struct {
    XMLName      xml.Name `xml:"record"`
    Text         string   `xml:",chardata"`
    Leader       string   `xml:"leader"`
    Controlfield []struct {
        Text string `xml:",chardata"`
        Tag  string `xml:"tag,attr"`
    } `xml:"controlfield"`
    Datafield []struct {
        Text     string `xml:",chardata"`
        Tag      string `xml:"tag,attr"`
        Ind1     string `xml:"ind1,attr"`
        Ind2     string `xml:"ind2,attr"`
        Subfield []struct {
            Text string `xml:",chardata"`
            Code string `xml:"code,attr"`
        } `xml:"subfield"`
    } `xml:"datafield"`
}

func main() {

    xmlFile, err := os.Open("music_lite3.xml")

    if err != nil {
        fmt.Println(err)
    }

    fmt.Println("Successfully Opened music_lite3.xml")

    defer xmlFile.Close()

    data, _ := ioutil.ReadAll(xmlFile)

    var record Record

    xml.Unmarshal(data, &record)

    for j := 0; j < len(record.Controlfield); j++ {
        for i := 0; i < len(record.Datafield); i++ {
            if record.Datafield == "650" {
                if record.Datafield.Subfield.Code == "a" {
                    fmt.Println("Kind of Music: " + record.Datafield.Subfield.Text)
                }
            }
        }
    }
}

I'm having problems to acess the structs datafield and subfield. It seems that when a call record.Datafield and record.Datafield.Subfield.Code Go is not recognizing the structs.

Anyone can help me? Thanks in advance.

=)

Your code doesn't even compile. You need to index the slices inside the loops, you can't refer to fields of elements of slices without indexing them. Also Record.Controlfield and Record.Datafield are not "related", it's senseless to process them with embedded loops.

However, you do need to use nested loops to check Subfield of a Datafield whose tag matches.

Something like this:

for i := range record.Datafield {
    df := &record.Datafield[i]
    if df.Tag == "650" {
        for j := range df.Subfield {
            if df.Subfield[j].Code == "a" {
                fmt.Println("Kind of Music: " + df.Subfield[j].Text)
            }
        }
    }
}

Try it on the Go Playground.

Note that you could use for range to also "get" the element at the given index, but since you have some kind of generated struct which uses anonymous structs (and not pointers), such a loop would copy all elements (hence I stayed with "manual indexing").

Also do check all errors, e.g. ioutil.ReadAll(xmlFile) and xml.Unmarshal(data, &record).