2017-04-22 3 views
0

Saxon9.7 및 다음 .xsl 파일을 사용하여 처리하는 .GPX 파일이 있습니다. 두 트랙 포인트 사이의 거리를 계산하여 다른 트랙 포인트 사이의 거리를 합산하려고합니다 (@lon & @lat 값).함수를 사용하여 XSLT에서 변수를 합치거나 증분

이 함수를 사용하여이 값을 증가 (또는 합산)하려고합니다.

  • gDistance 거리의 함수

    <xsl:function name="of:gesDistance"> 
        <xsl:param name="gDistance"/> 
        <xsl:param name="distance"/> 
        <xsl:value-of select="($gDistance + $distance)"/> 
    </xsl:function> 
    

    내 끝내고 .xsl 추가 거리를 반환한다 gDistance

추가되어야 수인

  • 현재 합산 거리를이고 파일은 다음과 같이 보입니다.

    <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&#xA;dLat: </xsl:text> 
         <xsl:value-of select="$dLat"/> 
         <xsl:text>&#xA;dLon: </xsl:text> 
         <xsl:value-of select="$dLon"/> 
         <xsl:text>&#xA;Distance: </xsl:text> 
         <xsl:value-of select="$distance"/> 
         <xsl:text> km &#xA;Length: </xsl:text> 
         <xsl:value-of select="$gDistance"/> 
    
        <xsl:text>&#xA;</xsl:text> 
    </xsl:for-each> 
    </xsl:template> 
    
    에서

    691,363,210 난 항상 거리를 dLon, 앞의 추적 점에 dLat을 계산하기위한-각 부분. 나중에 km 단위 거리가 계산됩니다.

    XSL : 가변 gDistance가 전에 0으로 설정되어 다음 라인이 기능은 이전 gDistance 값과 이전 형제 현재 거리 호출되는 부분을 설명 피 각 문장

     <xsl:variable name="gDistance" select="0"/> 
    

    .

    <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 
    

    당신이 요약 거리가 항상 앞의 형제까지의 거리와 동일하다 볼 수 있듯이. 하지만 왜? 내 문제에 대한 방법이나 해결 방법이 있습니까?

    다른 Saxon 명령을 사용하여 내 문제에 대한 다른 접근 방식을 시도했지만 그 중 하나가 작동하지 않았습니다.

    필요한 기능이있는 준비된 XML 네임 스페이스가 있습니까? 나는 우리가 예를 단순화하면 쉽게 생각 내 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> 
    ... 
    
  • +0

    변수는 XSLT에서 변수가 아닙니다. 원하는 총계를 계산하는 표현식을 작성해야하며, 절차형 언어 에서처럼 값을 조금씩 누적 할 수 없습니다. XSLT는 기능적이지 절차 적이 아닙니다. –

    +0

    Saxon 9.7에서 명령형 프로그래밍 방식을 실제로 사용하려면 PE 또는 EE가 필요하고 XSLT 3.0 및'xsl : iterate'를 사용해야합니다. 그러나 Jim이 말한 것처럼 XSLT 2.0에서는 값을 더하고 누적하는 표현식 및/또는 재귀 함수/템플릿을 작성할 수 있습니다. –

    +0

    @ JimGarrison 그래서 노드 수를 알 수없는 거리를 계산하고이를 요약하는 식을 만들어야합니다. 내가 맞습니까? 이 작품과 같은 것을 만들 수있는 다른 방법이 없습니까? –

    답변

    1

    의 일부 -

    은 ... 당신에게 내가 가진 모든 것을 제공합니다. 내가 사용하는 표준 예는 "은행 거래 내역서"문제입니다. 계좌에 입금되거나 출금되는 일련의 거래가있을 경우 모든 거래와 계좌에 누계 금액을 더한 은행 계좌 내역서를 보여줍니다.

    이 가장 간단한 솔루션은 트랜잭션의 수를 제외하고이 솔루션을 사용하지 않도록, 비용

    $balance = $initial-balance + sum(preceding-sibling::transaction/value) 
    

    하지만 각 트랜잭션에 대한 것을 계산하는 것은 O (N^2)를 계산하는 것이다 매우 작습니다.

    기능 프로그래밍에는이 문제를 해결하기위한 두 가지 주요 접근 방식이 있습니다. 하나는 재귀입니다 : 당신은 재귀 함수와의 거래의 순서의 함수로 균형의 순서를 계산할 수 있습니다 :

    이 기능은 첫 번째 트랜잭션 후 잔액을 계산 한 다음에 대한 잔액을 계산하기 위해 자신을 호출
    <xsl:function name="f:balances" as="xs:decimal*"> 
        <xsl:param name="initial-balance" as="xs:decimal*"/> 
        <xsl:param name="transactions" as="element(transaction)*"/> 
        <xsl:variable name="first-balance" select="initial-balance + head(transactions)/value"/> 
        <xsl:sequence select="$first-balance"/> 
        <xsl:sequence select="f:balances($first-balance, tail($transactions)"/> 
    </xsl:function> 
    

    트랜잭션의 나머지 - 고전적인 헤드/테일 재귀.

    이렇게하는 또 다른 방법은 폴드 작업입니다. fold 연산은 초기 값과 시퀀스를 취하고, 차례대로 각 초기 값으로 시퀀스의 각 항목에 제공된 함수를 적용합니다. 그래서

    fn:fold-left($transactions, $initial-balance, function($balance, $transaction) {$balance + $transaction/value}) 
    

    XSLT 3.0은 XSL을 소개 : 명령형 프로그래밍이 점에 당신의 두뇌를 왜곡했기 때문에 조금 어려운 이러한 개념을 발견하면

    <xsl:iterate select="$transactions"> 
        <xsl:param name="initial-balance"/> 
        <xsl:variable name="balance" select="./value + $initial-balance"/> 
        <xsl:sequence select="$balance"/> 
        <xsl:next-iteration> 
        <xsl:with-param name="initial-balance" select="$balance"/> 
        </xsl:next-iteration> 
    </xsl:iterate> 
    

    , 그건 : 겹 동작으로 문법 설탕을 반복

    i = i + 1 
    

    과 같은 성명서는 정상적인 것으로 간주됩니다.

    관련 문제