This question already has an answer here:
Can't decode XML with golang, always empty struct

(1个答案)


9个月前关闭。




我想解析一个GPX文件。我想获得以下信息:

文件中的所有点(trkpt)及其值:
  • 经度
  • 纬度
  • 海拔
  • 时间

  • 为此,我编写了结构:
    type gpx file{
        filepointer *os.file
        points []xmlPoints
    }
    
    type gpx struct {
        XMLName xml.Name `xml:"gpx"`
        trks trk `xml:"trk"`
    }
    
    type trk struct {
        XMLName xml.Name `xml:"trk"`
        trksegs []trkseg `xml:"trkseg"`
    }
    
    type trkseg struct {
        XMLName xml.Name   `xml:"trkseg"`
        points  []XMLPoint `xml:"trkpt"`
    }
    
    type XMLPoint struct {
        XMLName   xml.Name  `xml:"trkpt"`
        longitude float64   `xml:"lon,attr"`
        latitude  float64   `xml:"lat,attr"`
        elevation float64   `xml:"ele"`
        time      time.Time `xml:"time"`
    }
    

    我使用以下方法尝试获取这些值:
    func (f *GPXFile) setPoints() {
        //Reads the GPXfile to get a slice of all Points and set them to f.points
        //read GPXFile
        file, _ := os.Open(f.filePointer.Name())
        fileByte, _ := ioutil.ReadAll(file)
        //get points
        var g gpx
        //should read points and puts them to &points, result empty
        err :=xml.Unmarshal(fileByte, &g)
        fmt.Print(err)
        //set points
        f.points = g.trks.trksegs[1].points
    }
    

    我的GPX文件如下所示:
    <?xml version="1.0" encoding="UTF-8"?>
    <gpx version="1.1" ...>
     <metadata>
      <time>2019-09-14T13:14:17.094Z</time>
     </metadata>
    
     <trk>
      <name>Cube – Sa., 14. Sep. 2019, 15:14</name>
      <trkseg>
      </trkseg>
      <trkseg>
       <trkpt lat="49.3547198000" lon="9.1508659200"><time>2019-09-14T13:14:00.000Z</time><extensions><gpxpx:PowerInWatts>120</gpxpx:PowerInWatts></extensions></trkpt>
       <trkpt lat="49.3546998700" lon="9.1509324100"><time>2019-09-14T13:14:10.003Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22.9</gpxtpx:atemp></gpxtpx:TrackPointExtension><gpxpx:PowerInWatts>120</gpxpx:PowerInWatts></extensions></trkpt>
       <trkpt lat="49.3547521100" lon="9.1510961900"><time>2019-09-14T13:14:14.293Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22.9</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt>
       <trkpt lat="49.3547585400" lon="9.1513071400"><time>2019-09-14T13:14:20.310Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22.9</gpxtpx:atemp></gpxtpx:TrackPointExtension></extensions></trkpt>
       <trkpt lat="49.3549890600" lon="9.1519649400"><ele>172.50</ele><time>2019-09-14T13:14:30.276Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22.8</gpxtpx:atemp><gpxtpx:speed>5.54</gpxtpx:speed></gpxtpx:TrackPointExtension></extensions></trkpt>
       <trkpt lat="49.3550175500" lon="9.1520317100"><ele>172.23</ele><time>2019-09-14T13:14:32.291Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22.8</gpxtpx:atemp><gpxtpx:speed>4.86</gpxtpx:speed></gpxtpx:TrackPointExtension></extensions></trkpt>
       <trkpt lat="49.3550991300" lon="9.1520247100"><ele>171.90</ele><time>2019-09-14T13:14:34.290Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22.8</gpxtpx:atemp><gpxtpx:speed>4.54</gpxtpx:speed></gpxtpx:TrackPointExtension></extensions></trkpt>
       <trkpt lat="49.3551844700" lon="9.1519891400"><ele>171.33</ele><time>2019-09-14T13:14:36.275Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22.8</gpxtpx:atemp><gpxtpx:speed>4.88</gpxtpx:speed></gpxtpx:TrackPointExtension></extensions></trkpt>
       <trkpt lat="49.3553612700" lon="9.1518673700"><ele>170.61</ele><time>2019-09-14T13:14:40.015Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:atemp>22.8</gpxtpx:atemp><gpxtpx:speed>5.55</gpxtpx:speed></gpxtpx:TrackPointExtension><gpxpx:PowerInWatts>121</gpxpx:PowerInWatts></extensions></trkpt>
      </trkseg>
     </trk>
    </gpx>
    

    问题是,从解组函数中,我得到了一个带有gpxtrk,但是trkseq是nil ...
    如果我将trkseq中的trk设为单个trkseq而不是数组,则可以,但是要点为零。所以我想知道如何解析trkseq数组。从那里,我可以使用相同的方法来获取点数组。

    最佳答案

    在golang中编组/解组任何类型的编码/序列化数据时,解组的类型有时会作为interface{}类型传递。 (取消编组)代码将必须依赖reflect包来查找可用于将数据映射到的标签和字段。此代码只能使用(写入)的字段是导出字段(以大写字母开头的字段)。您的所有类型都具有未导出的字段和类型(如果可以,则为 private )。

    只需更改以下内容:

    type gpx struct {
        XMLName xml.Name `xml:"gpx"`
        trks    trk      `xml:"trk"`
    }
    


    type Gpx struct {
        XMLName xml.Name `xml:"gpx"`
        Trks    Trk      `xml:"trk"`
    }
    

    另外,在Golang中,惯例是使用所有大写字母作为首字母缩写(例如URL,而不是urlUrl),因此可以说,您需要:
    type GPX struct {
        XMLName xml.Name `xml:"gpx"`
        TRKS    TRK      `xml:"trk"`
    }
    

    09-04 11:21