【问题标题】:How to summarize, group 4000+ GPX Trackpoints as Tracks named for by each days date?如何总结,将 4000 多个 GPX 跟踪点分组为按每天日期命名的跟踪?
【发布时间】:2014-10-20 01:20:04
【问题描述】:

下面的 XSLT 仅从 Garmin GPX 文件(省略任何航点)中提取所有 Trackpoints (trkpt),并将结果作为一 (1) 个轨迹导出到一个新的 GPX 文件中,以供 MapSource 或 Basecamp 使用。 目前,该轨道的名称是第一个 Trackpoint 的日期。

如何实现以每个日期 (YYYY-MM-DD) 命名的每天一条轨道,其中每条轨道都包含其所有对应的追踪点?

(我认为必须考虑到trkpt/time的日期变化,但我在这里迷路了)。

GPX 源文件可以是 Garmin 创建的任何更大的 GPX 文件(其他不知道)。 我的源文件跨越了超过 3 个月的旅行,每四分钟记录一次轨迹点记录(75 天内总共有 7633 个 trkpt)。 当然,设备是在睡觉时关闭的。 下面请看文件的 XSLT 代码,名为:'extract-TRKPTs.xsl'

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:gpx="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">
<xsl:output method="text" indent="yes" encoding="utf-8" />
<!-- command: msxsl.exe 20101008.gpx extract-TRKPTs.xsl > 20101008-trkpts.gpx -->
<!-- extracts all trackpoints only from a given Garmin GPX file -->
<!-- output is piped into a new .gpx file -->
<xsl:template match="/">&#60;<xsl:text>?xml version="1.0" encoding="utf-8" standalone="no" ?&#62;</xsl:text>
&#60;<xsl:text>gpx xmlns="http://www.topografix.com/GPX/1/1" creator="MapSource 6.16.2" version="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"</xsl:text>&#62;
<gpx>
<trk>&#60;trk&#62;
&#60;name&#62;Trackpoints: <xsl:value-of select="substring(/gpx:gpx/gpx:trk/gpx:trkseg/gpx:trkpt/gpx:time,1,10)"/>&#60;/name&#62;
<trkseg>&#60;trkseg&#62;
    <xsl:for-each select="/gpx:gpx/gpx:trk/gpx:trkseg/gpx:trkpt">
    <xsl:value-of select="gpx:trkpt"/><trkpt>
        &#60;<xsl:text>trkpt lat="</xsl:text><xsl:value-of select="@lat"/><xsl:text>" lon="</xsl:text><xsl:value-of select="@lon"/><xsl:text>"</xsl:text>&#62;
        &#60;ele&#62;<xsl:value-of select="gpx:ele"/>&#60;/ele&#62;
        &#60;time&#62;<xsl:value-of select="gpx:time"/>&#60;/time&#62;
        &#60;/trkpt&#62;</trkpt>
    </xsl:for-each>
</trkseg>&#60;/trkseg&#62;
</trk>&#60;/trk&#62;
</gpx>&#60;/gpx&#62;
</xsl:template>
</xsl:stylesheet>

代码看起来很难看,因为它设置为输出“文本”,因此我需要使用特殊字符实体。但是,嘿,到目前为止它有效。抱歉,我是 XSLT 新手。 感谢您的反馈。

当前输出如下(单个轨迹中的所有轨迹点):

<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="MapSource 6.16.2" version="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>Trackpoints: 2010-09-21</name>
<trkseg>
    <trkpt lat="34.004124635830522" lon="-118.47464606165886">
    <ele>55.4130859375</ele>
    <time>2010-09-21T19:51:12Z</time>
    </trkpt>
    <trkpt lat="34.004120444878936" lon="-118.47464254125953">
    <ele>55.4130859375</ele>
    <time>2010-09-21T19:51:26Z</time>
    </trkpt>
    <trkpt lat="34.004129162058234" lon="-118.47465343773365">
    <ele>56.8551025390625</ele>
    <time>2010-09-22T21:02:55Z</time>
    </trkpt>
...
...
    <trkpt lat="37.042149296030402" lon="-112.52694656141102">
    <ele>1506.523193359375</ele>
    <time>2010-12-01T07:01:06Z</time>
    </trkpt>
    <trkpt lat="37.042256919667125" lon="-112.52645093947649">
    <ele>1504.1201171875</ele>
    <time>2010-12-01T07:01:23Z</time>
    </trkpt>
</trkseg>
</trk>
</gpx>

预期输出如下(请注意:每天一首曲目)。

<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="MapSource 6.16.2" version="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>Trackpoints: 2010-09-21</name>
<trkseg>
    <trkpt lat="34.004124635830522" lon="-118.47464606165886">
    <ele>55.4130859375</ele>
    <time>2010-09-21T19:51:12Z</time>
    </trkpt>
    <trkpt lat="34.004120444878936" lon="-118.47464254125953">
    <ele>55.4130859375</ele>
    <time>2010-09-21T19:51:26Z</time>
    </trkpt>
    <trkpt lat="34.004129162058234" lon="-118.47465343773365">
    <ele>56.8551025390625</ele>
    <time>2010-09-22T21:02:55Z</time>
    </trkpt>
</trkseg>
</trk>
...
...
<trk>
<name>Trackpoints: 2010-12-01</name>
<trkseg>

    <trkpt lat="37.042149296030402" lon="-112.52694656141102">
    <ele>1506.523193359375</ele>
    <time>2010-12-01T07:01:06Z</time>
    </trkpt>
    <trkpt lat="37.042256919667125" lon="-112.52645093947649">
    <ele>1504.1201171875</ele>
    <time>2010-12-01T07:01:23Z</time>
    </trkpt>
</trkseg>
</trk>
</gpx>

【问题讨论】:

  • 如果实际输出XML,为什么输出方式设置为“文本”?另外,请编辑您的帖子以显示 预期 输出以及它与您当前获得的输出有何不同。
  • @Mathias Müller:添加了预期的输出。文本输出的原因是节点“
  • 感谢编辑。原因是“节点的格式”是什么意思?我还没有和你在一起。作为最后一个请求,请发布一个我们可以用作 XML 输入的示例 GPX 文件(我想这里很少有人熟悉 GPX)。
  • @Mathias Müller:示例 gpx 文件放置在我的服务器上:[www.halo-photographs.com/exchange/2010-09-21_2010-12-06.gpx]。关于您的问题:我无法使用 xml 作为输出将属性“lat”和“lon”添加到节点“trkpt”。这就是我将上面发布的代码声明为“丑陋”的原因——是的,它是一个丑陋的 hack。仅此而已,但到底是什么 - 它确实有效。如您所知,XML 和 GPX 文件结构及其转换遵循相同的规则。感谢您对此进行调查。
  • +1 最后,您的问题很有帮助,值得一票!

标签: xml xslt gps gpx


【解决方案1】:

您应该可以使用Muenchian Grouping 执行此操作。

由于您没有提供示例输入,我自己制作了(示例的修改版本here)。

XML 输入

<gpx xmlns="http://www.topografix.com/GPX/1/1" 
    xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
    xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" 
    creator="Oregon 400t" 
    version="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 http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
    <metadata>
        <link href="http://www.garmin.com">
            <text>Garmin International</text>
        </link>
        <time>2009-10-17T22:58:43Z</time>
    </metadata>
    <trk>
        <name>Example 1</name>
        <trkseg>
            <trkpt lat="47.644548" lon="-122.326897">
                <ele>4.46</ele>
                <time>2009-10-17T18:37:26Z</time>
            </trkpt>
            <trkpt lat="47.644548" lon="-122.326898">
                <ele>4.47</ele>
                <time>2009-10-17T18:38:26Z</time>
            </trkpt>
            <trkpt lat="47.644548" lon="-122.326898">
                <ele>4.48</ele>
                <time>2009-10-18T18:39:26Z</time>
            </trkpt>
        </trkseg>
    </trk>
    <trk>
        <name>Example 2</name>
        <trkseg>
            <trkpt lat="47.644548" lon="-122.326899">
                <ele>4.49</ele>
                <time>2009-10-18T18:37:26Z</time>
            </trkpt>
            <trkpt lat="47.644548" lon="-122.326900">
                <ele>4.50</ele>
                <time>2009-10-18T18:38:26Z</time>
            </trkpt>
            <trkpt lat="47.644548" lon="-122.326901">
                <ele>4.51</ele>
                <time>2009-10-19T18:39:26Z</time>
            </trkpt>
        </trkseg>    
    </trk>
</gpx>

XSLT 1.0

<xsl:stylesheet version="1.0" 
    xmlns="http://www.topografix.com/GPX/1/1" 
    xmlns:gpx="http://www.topografix.com/GPX/1/1" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="gpx">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="date" match="gpx:trkpt" use="substring(gpx:time,1,10)"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:for-each select="//gpx:trkpt[generate-id(key('date',substring(gpx:time,1,10))[1])=generate-id()]">
                <trk>
                    <name>Trackpoints: <xsl:value-of select="substring(gpx:time,1,10)"/></name>
                    <trkseg>
                        <xsl:for-each select="key('date',substring(gpx:time,1,10))">
                            <xsl:copy-of select="."/>
                        </xsl:for-each>
                    </trkseg>
                </trk>
            </xsl:for-each>
        </xsl:copy>        
    </xsl:template>

</xsl:stylesheet>

XML 输出

<gpx xmlns="http://www.topografix.com/GPX/1/1"
     xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
     xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     creator="Oregon 400t"
     version="1.1"
     xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
   <trk>
      <name>Trackpoints: 2009-10-17</name>
      <trkseg>
         <trkpt lat="47.644548" lon="-122.326897">
            <ele>4.46</ele>
            <time>2009-10-17T18:37:26Z</time>
         </trkpt>
         <trkpt lat="47.644548" lon="-122.326898">
            <ele>4.47</ele>
            <time>2009-10-17T18:38:26Z</time>
         </trkpt>
      </trkseg>
   </trk>
   <trk>
      <name>Trackpoints: 2009-10-18</name>
      <trkseg>
         <trkpt lat="47.644548" lon="-122.326898">
            <ele>4.48</ele>
            <time>2009-10-18T18:39:26Z</time>
         </trkpt>
         <trkpt lat="47.644548" lon="-122.326899">
            <ele>4.49</ele>
            <time>2009-10-18T18:37:26Z</time>
         </trkpt>
         <trkpt lat="47.644548" lon="-122.326900">
            <ele>4.50</ele>
            <time>2009-10-18T18:38:26Z</time>
         </trkpt>
      </trkseg>
   </trk>
   <trk>
      <name>Trackpoints: 2009-10-19</name>
      <trkseg>
         <trkpt lat="47.644548" lon="-122.326901">
            <ele>4.51</ele>
            <time>2009-10-19T18:39:26Z</time>
         </trkpt>
      </trkseg>
   </trk>
</gpx>

【讨论】:

  • 感谢您的反馈。我收到一个错误:代码:0x80004005 表达式必须计算为节点集。 /gpx:trkpt[-->generate-id(key('date',substring(gpx:time,1,10)))
  • 示例 gpx 文件放置在我的服务器上:[www.halo-photographs.com/exchange/2010-09-21_2010-12-06.gpx]
  • @snahl - 抱歉。有一个不会导致我使用的 XSLT 2.0 处理器出错的错字。我更新了我的答案。
  • @snahl - 你使用了更新的样式表吗?确保第一个 xsl:for-each 具有选择 //gpx:trkpt[generate-id(key('date',substring(gpx:time,1,10))[1])=generate-id()]。它适用于我使用这两个数据集和 Xalan 或 Saxon 6.5.5 作为 1.0 处理器。
  • 发帖后才看到。这次效果很好!刚刚将我的 1.4MB 示例文件泵入其中,2 分钟后它在 MapSource - BINGO 中完美打开!非常感谢。我能再问你一个与本案有关的问题吗?
猜你喜欢
  • 2015-03-05
  • 2011-02-24
  • 2017-04-10
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多