【发布时间】:2017-04-22 14:08:21
【问题描述】:
我有一个使用 Saxon9.7 处理的 .GPX 文件和以下 .xsl 文件。我尝试通过计算两个轨迹点之间的距离(使用 @lon 和 @lat 值)来总结不同轨迹点之间的距离。
使用这个函数,我尝试增加(或累加)这些值。
- gDistance 是当前求和的距离
- 距离是应该添加到 gDistance 的数字
函数应该返回增加的距离
<xsl:function name="of:gesDistance">
<xsl:param name="gDistance"/>
<xsl:param name="distance"/>
<xsl:value-of select="($gDistance + $distance)"/>
</xsl:function>
我的 .xsl 文件如下所示:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://www.topografix.com/GPX/1/1"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:of ="http://lul.org">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:function name="of:gesDistance">
<xsl:param name="gDistance"/>
<xsl:param name="distance"/>
<xsl:value-of select="($gDistance + $distance)"/>
</xsl:function>
<xsl:template match="trkseg">
<xsl:variable name="gDistance" select="0"/>
<xsl:for-each select="trkpt">
<xsl:variable name="dLat" select="(@lat - preceding-sibling::*[1]/@lat)"/>
<xsl:variable name="dLon" select="(@lon - preceding-sibling::*[1]/@lon)"/>
<xsl:variable name="cLon" select="(@lon)"/>
<xsl:variable name="cLat" select="(@lat)"/>
<xsl:variable name="pLon" select="(preceding-sibling::*[1]/@lon)"/>
<xsl:variable name="pLat" select="(preceding-sibling::*[1]/@lat)"/>
<xsl:variable name="distance" select="6378.388 * math:acos(math:sin($cLat)*math:sin($pLat) + math:cos($cLat) * math:cos($pLat) * math:cos($dLon))"/>
<xsl:variable name="gDistance" select="of:gesDistance($gDistance, $distance)"/>
<xsl:text>newNode
dLat: </xsl:text>
<xsl:value-of select="$dLat"/>
<xsl:text>
dLon: </xsl:text>
<xsl:value-of select="$dLon"/>
<xsl:text>
Distance: </xsl:text>
<xsl:value-of select="$distance"/>
<xsl:text> km 
Length: </xsl:text>
<xsl:value-of select="$gDistance"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
在 for-each 部分中,我总是计算 dLon、dLat 到前一个跟踪点的距离。稍后计算以公里为单位的距离。
xsl:variable gDistance 在 for-each 语句之前设置为 0
<xsl:variable name="gDistance" select="0"/>
以下行描述了使用旧 gDistance 值和与前一个兄弟的当前距离调用函数的部分。
<xsl:variable name="gDistance" select="of:gesDistance($gDistance, $distance)"/>
使用 Saxon9 运行它会得到以下输出:
dLat: -0.0001660000000001105
dLon: -0.0004770000000000607
Distance: 1.1425320012289337 km
Length: 1.1425320012289337
newNode
dLat: -0.00023200000000400678
dLon: -0.0006450000000004508
Distance: 1.5892769562498525 km
Length: 1.5892769562498525
newNode
dLat: -0.00023799999999596366
dLon: -0.0004939999999997724
Distance: 1.5814420943745287 km
Length: 1.5814420943745287
如您所见,总和的距离始终与到前一个兄弟的距离相同。但为什么?有没有办法解决我的问题?
我使用不同的撒克逊命令尝试了不同的方法来解决我的问题,但也没有用。
是否有准备好的 xml-namespace 以及我需要的功能?
...给你我所有的一切——我的 GPX 文件的一部分
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="" 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>ACTIVE LOG133212</name>
<trkseg>
<trkpt lat="48.813909" lon="9.249088">
<ele>-21.666</ele>
<time>2008-05-25T13:32:07Z</time>
</trkpt>
<trkpt lat="48.814533" lon="9.248918">
<ele>49.192</ele>
<time>2008-05-25T13:32:14Z</time>
</trkpt>
...
【问题讨论】:
-
变量在 XSLT 中不是变量。你必须编写一个表达式来计算你想要的总数,你不能像在过程语言中那样零碎地累积值。 XSLT 是功能性的,而不是程序性的。
-
如果您真的想在 Saxon 9.7 中使用这种命令式编程方法,那么您需要 PE 或 EE 并使用 XSLT 3.0 和
xsl:iterate。但正如 Jim 所说,在 XSLT 2.0 中,您可以编写表达式和/或递归函数/模板来添加/累积值。 -
@JimGarrison 所以我必须创建一个表达式来计算未知数量节点的距离并将它们相加。我对吗?没有其他方法可以使这样的事情发挥作用吗?
-
一种“增加变量”(或者更准确地说是累积余额)的简单方法是采用一种称为兄弟递归的技术。参见,例如:stackoverflow.com/a/21809106/3016153
-
P.S.你确定你计算距离的公式是正确的吗?