【问题标题】:How to extract data from GPX file (and to parse gpx file)?如何从 GPX 文件中提取数据(并解析 gpx 文件)?
【发布时间】:2018-12-28 05:01:29
【问题描述】:

我在 Linux 下使用 bash 进行编码。我正在尝试提取 gpx 文件系列中每个轨道的 轨道名称第一个时间戳

我尝试使用以下命令(和其他变体)使用 xmllint 解析 gpx 文件:

xmllint --xpath "//gpx/trk/name/text()" test.gpx
xmllint --xpath "//gpx/trk/trkseg[1]/time/text()" test.gpx

失败并返回消息:XPath set is empty

这里是一个文件test.gpx

的例子
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<gpx creator="www.flyisfun.com" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
  <trk>
    <name>Track_n1</name>
    <trkseg>
      <trkpt lat="-48.843895" lon="10.9835696">
        <ele>126.75549</ele>
        <time>2016-04-16T11:05:00Z</time>
      </trkpt>
      <trkpt lat="-48.843254" lon="11.9823042">
        <ele>126.90486</ele>
        <time>2016-04-16T11:05:05Z</time>
      </trkpt>
    </trkseg>
  </trk>
</gpx>

我期待得到这个测试用例

Track_n1
2016-04-16T11:05:00Z

我想知道为什么带有 xmllint 的命令不起作用,以及是否可以在不更改原始 gpx 文件的情况下调整它们以使其正常工作。

感谢您的帮助。

【问题讨论】:

    标签: xml gpx xmllint


    【解决方案1】:

    也可以用perl解决:

    #!/usr/bin/perl
    # https://unix.stackexchange.com/questions/343636/from-gpx-to-csv-file
    
    use warnings;
    use strict;
    use XML::Twig;
    
        my $xml = XML::Twig -> new -> parsefile('my_track.gpx'); 
    
    foreach my $wpt ( $xml -> get_xpath('/gpx/trk/trkseg/trkpt') ) {
         print $wpt -> att('lat') . "|" . $wpt -> att('lon') . "|" . $wpt -> first_child_text('ele') . "|" . $wpt -> first_child_text('time') . "\n";
    }
    

    【讨论】:

      【解决方案2】:

      我已经设法将我的 Garmin GPX 从这里给出的解决方案转换为文本格式。以下是一些有效的语法:

      xmlstarlet sel -N g="http://www.topografix.com/GPX/1/1" -T -t -m "/g:gpx/g:trk/g:trkseg/g:trkpt" -v "@lat" -o "|" -v "@lon" -o "|" -v "g:ele" -o "|" -v "g:time" -n my_track.gpx
      
      xmlstarlet sel -N g="http://www.topografix.com/GPX/1/1" -T -t -m "/g:gpx/g:trk/g:trkseg/g:trkpt" -v "concat(@lat,'|',@lon,'|',g:ele,'|',g:time)" -n my_track.gpx
      
      xmlstarlet sel -T -t -m "/_:gpx/_:trk/_:trkseg/_:trkpt" -v "concat(@lat,'|',@lon,'|',_:ele,'|',_:time)" -n my_track.gpx
      
      xmlstarlet select --text --template --match "/_:gpx/_:trk/_:trkseg/_:trkpt" --value-of "concat(@lat,'|',@lon,'|',_:ele,'|',_:time)" --nl my_track.gpx
      

      【讨论】:

        【解决方案3】:

        如果您愿意替代 xmllint,xmlstarlet 是一个不错的选择。 xmlstarlet 里面有不少命令,但是只查询数据sel (select) 就可以了。

        我喜欢您如何将命名空间绑定到前缀或使用_ 作为默认命名空间的前缀(在版本 1.5.0+ 中)。 See here for more details. 我更喜欢这个而不是管道 echo 到 xmllint。

        将默认命名空间绑定到前缀的示例...

        xmlstarlet sel -N g="http://www.topografix.com/GPX/1/1" -t -m "/g:gpx/g:trk" -v "g:name" -n -v "g:trkseg/g:trkpt[1]/g:time" -n test.gpx
        

        使用_作为默认命名空间前缀的示例...

        xmlstarlet sel -t -m "/_:gpx/_:trk" -v "_:name" -n -v "_:trkseg/_:trkpt[1]/_:time" -n test.gpx
        

        以上两个示例都产生以下输出...

        Track_n1
        2016-04-16T11:05:00Z
        

        【讨论】:

        • 感谢您的帮助,以及 xmlstarlet 的示例。我使用了您的解决方案:我发现语法更容易理解和概括。
        【解决方案4】:

        XML 示例包含一个默认命名空间 xmlns="http://www.topografix.com/GPX/1/1"xmllint --shellsetns 组合可用于获取值。
        将默认(空)命名空间更改为已知命名空间:

        echo -e 'setns ns=http://www.topografix.com/GPX/1/1\ncat //ns:gpx/ns:trk/ns:name/text()' \
        | xmllint --shell test.xml | grep -Ev '^([/]| [-])'
        

        结果:

        Track_n1
        

        local-name()xml 函数也可以使用,但有时会导致复杂的 xpath 表达式难以阅读。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-06-22
          • 2012-01-28
          • 2011-02-28
          • 2022-08-02
          • 2018-07-25
          • 2019-01-19
          • 2010-10-14
          • 2012-06-06
          相关资源
          最近更新 更多