go - 如何使用 unmarshal 解析 gpx

标签 go

这个问题在这里已经有了答案:





Can't decode XML with golang, always empty struct

(1 个回答)


2年前关闭。




我想解析一个 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>
    

    问题是,从 unmarshal 函数中我得到一个 gpxtrk在其中,但 trkseq是零……
    如果我制作 trkseqtrktrkseq它不是数组,而是有效,但点数为零。所以我想知道如何解析 trkseq 的数组.从那里我可以使用相同的方法来获取点数组。

    最佳答案

    在 golang 中编码/解码任何类型的编码/序列化数据时,您解码的类型作为 interface{} 传递在某个时候输入。 (un)marshalling 代码必须依赖 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"`
    }
    

    关于go - 如何使用 unmarshal 解析 gpx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59683938/

    相关文章:

    sql - 使用 Postgres 时为 "Operator does not exist: integer =?"

    go - 如何只将参数值传递给 Makefile 目标?

    go - Curl 因这个 swagger 规范而失败

    go - 使用更新的 CommonName 重新生成新的 x509 证书

    go - Golang扫描函数中 "ERROR: IOError: closed stream"如何处理?

    json - 将结构的 time.Time 字段编码为具有自定义格式的 JSON 的通用方法

    go - 使用函数通过方法满足接口(interface)

    GORM 和外键关联

    go - 使用 gob 在 Go 中编码 websockets

    Goland 读取每行命令输出的衬垫