Как извлечь данные из файла GPX (и разобрать файл gpx)?

Пишу на bash под линуксом. Я пытаюсь извлечь название дорожки и первую метку времени каждой дорожки в серии файлов gpx.

Я попытался разобрать файл gpx с помощью xmllint со следующими командами (и другими вариантами):

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.

Спасибо за помощь.


person kFly    schedule 19.07.2018    source источник


Ответы (4)


Если вы открыты для альтернативы xmllint, xmlstarlet является Неплохо. В xmlstarlet довольно много команд, но только для запроса данных sel ( выберите).

Мне нравится, как вы можете либо привязывать пространства имен к префиксам, либо использовать _ для префикса пространства имен по умолчанию (в версии 1.5.0+). Дополнительную информацию см. здесь. Я предпочитаю это конвейерному эху. в xmlint.

Пример привязки пространства имен по умолчанию к префиксу...

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
person Daniel Haley    schedule 20.07.2018
comment
Спасибо за помощь и пример для xmlstarlet. Я использовал ваше решение: я обнаружил, что синтаксис легче понять и обобщить. - person kFly; 25.07.2018

Образец XML содержит пространство имен по умолчанию xmlns="http://www.topografix.com/GPX/1/1". xmllint --shell в сочетании с setns можно использовать для получения значений.
Изменение стандартного (пустого) пространства имен на известное:

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.

person LMC    schedule 20.07.2018

Мне удалось преобразовать мой 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
person Bellera    schedule 05.06.2021

Также возможно решить с помощью 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";
}
person Bellera    schedule 05.06.2021