﻿<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"    
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" >

<!-- (c) 2010, Trimble Navigation Limited. All rights reserved.                                -->
<!-- Permission is hereby granted to use, copy, modify, or distribute this style sheet for any -->
<!-- purpose and without fee, provided that the above copyright notice appears in all copies   -->
<!-- and that both the copyright notice and the limited warranty and restricted rights notice  -->
<!-- below appear in all supporting documentation.                                             -->

<!-- TRIMBLE NAVIGATION LIMITED PROVIDES THIS STYLE SHEET "AS IS" AND WITH ALL FAULTS.         -->
<!-- TRIMBLE NAVIGATION LIMITED SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY -->
<!-- OR FITNESS FOR A PARTICULAR USE. TRIMBLE NAVIGATION LIMITED DOES NOT WARRANT THAT THE     -->
<!-- OPERATION OF THIS STYLE SHEET WILL BE UNINTERRUPTED OR ERROR FREE.                        -->

<xsl:output method="text" omit-xml-declaration="yes" encoding="ISO-8859-1"/>

<!-- Set the numeric display details i.e. decimal point, thousands separator etc -->
<xsl:variable name="DecPt" select="'.'"/>    <!-- Change as appropriate for US/European -->
<xsl:variable name="GroupSep" select="','"/> <!-- Change as appropriate for US/European -->
<!-- Also change decimal-separator & grouping-separator in decimal-format below 
     as appropriate for US/European output -->
<xsl:decimal-format name="Standard" 
                    decimal-separator="."
                    grouping-separator=","
                    infinity="Infinity"
                    minus-sign="-"
                    NaN=""
                    percent="%"
                    per-mille="&#2030;"
                    zero-digit="0" 
                    digit="#" 
                    pattern-separator=";" />

<xsl:variable name="DecPl0" select="'#0'"/>
<xsl:variable name="DecPl1" select="concat('#0', $DecPt, '0')"/>
<xsl:variable name="DecPl2" select="concat('#0', $DecPt, '00')"/>
<xsl:variable name="DecPl3" select="concat('#0', $DecPt, '000')"/>
<xsl:variable name="DecPl4" select="concat('#0', $DecPt, '0000')"/>
<xsl:variable name="DecPl5" select="concat('#0', $DecPt, '00000')"/>
<xsl:variable name="DecPl6" select="concat('#0', $DecPt, '000000')"/>
<xsl:variable name="DecPl8" select="concat('#0', $DecPt, '00000000')"/>
<xsl:variable name="DecPl10" select="concat('#0', $DecPt, '0000000000')"/>

<xsl:variable name="Pi" select="3.14159265358979323846264"/>
<xsl:variable name="halfPi" select="$Pi div 2.0"/>
<xsl:variable name="WGS84SemiMajorAxis" select="6378137.000"/>
<xsl:variable name="WGS84Flattening" select="298.257222101"/>
<xsl:variable name="WGS84EccentricitySquared" select="0.00669438002290"/>

<xsl:variable name="fileExt" select="'dat'"/>

<!-- Define keys to speed up search for reduced point, target ht abd backsight point details -->
<xsl:key name="stnID-search" match="//JOBFile/FieldBook/StationRecord" use="ID"/>
<xsl:key name="reducedPtName-search" match="//JOBFile/Reductions/Point" use="Name"/>
<xsl:key name="tgtID-search" match="//JOBFile/FieldBook/TargetRecord" use="@ID"/>
<xsl:key name="BSPt-search" match="//JOBFile/FieldBook/BackBearingRecord" use="@ID"/>
<xsl:key name="atmosID-search" match="//JOBFile/FieldBook/AtmosphereRecord" use="@ID"/>

<!-- User variable definitions - Appropriate fields are displayed on the       -->
<!-- Survey Controller screen to allow the user to enter specific values       -->
<!-- which can then be used within the style sheet definition to control the   -->
<!-- output data.                                                              -->
<!--                                                                           -->
<!-- All user variables must be identified by a variable element definition    -->
<!-- named starting with 'userField' (case sensitive) followed by one or more  -->
<!-- characters uniquely identifying the user variable definition.             -->
<!--                                                                           -->
<!-- The text within the 'select' field for the user variable description      -->
<!-- references the actual user variable and uses the '|' character to         -->
<!-- separate the definition details into separate fields as follows:          -->
<!-- For all user variables the first field must be the name of the user       -->
<!-- variable itself (this is case sensitive) and the second field is the      -->
<!-- prompt that will appear on the Survey Controller screen.                  -->
<!-- The third field defines the variable type - there are four possible       -->
<!-- variable types: Double, Integer, String and StringMenu.  These variable   -->
<!-- type references are not case sensitive.                                   -->
<!-- The fields that follow the variable type change according to the type of  -->
<!-- variable as follow:                                                       -->
<!-- Double and Integer: Fourth field = optional minimum value                 -->
<!--                     Fifth field = optional maximum value                  -->
<!--   These minimum and maximum values are used by the Survey Controller for  -->
<!--   entry validation.                                                       -->
<!-- String: No further fields are needed or used.                             -->
<!-- StringMenu: Fourth field = number of menu items                           -->
<!--             Remaining fields are the actual menu items - the number of    -->
<!--             items provided must equal the specified number of menu items. -->
<!--                                                                           -->
<!-- The style sheet must also define the variable itself, named according to  -->
<!-- the definition.  The value within the 'select' field will be displayed in -->
<!-- the Survey Controller as the default value for the item.                  -->

<xsl:variable name="userField1" select="'Protocollo|Protocollo|Integer|1|200'"/>
<xsl:variable name="Protocollo" select="1"/>
<xsl:variable name="userField2" select="'Comune|Comune|String'"/>
<xsl:variable name="Comune" select="'G337'"/>
<xsl:variable name="userField3" select="'Foglio|Foglio|String'"/>
<xsl:variable name="Foglio" select="'0220'"/>
<xsl:variable name="userField4" select="'Mappali|Mappali|Integer|1|10000'"/>
<xsl:variable name="Mappali" select="32"/>
<xsl:variable name="userField5" select="'Cognome|Cognome|String'"/>
<xsl:variable name="Cognome" select="'PAOLINO'"/>
<xsl:variable name="userField6" select="'Nome|Nome|String'"/>
<xsl:variable name="Nome" select="'PAPERINO'"/>
<xsl:variable name="userField7" select="'Qualifica|Qualifica|stringMenu|7|AGROTECNICO|ARCHITETTO|DOTTORE IN AGRARIA|GEOMETRA|INGEGNERE|PERITO AGRARIO|PERITO EDILE'"/>
<xsl:variable name="Qualifica" select="'GEOMETRA'"/>
<xsl:variable name="userField8" select="'Provincia|Provincia|stringMenu|103|AGRIGENTO|ALESSANDRIA|ANCONA|AOSTA|ASCOLI PICENO|L` AQUILA|AREZZO|ASTI|AVELLINO|BARI|BERGAMO|BIELLA|BELLUNO|BENEVENTO|BOLOGNA|BRINDISI|BRESCIA|BOLZANO|CAGLIARI|CAMPOBASSO|CASERTA|CHIETI|CALTANISSETTA|CUNEO|COMO|CREMONA|COSENZA|CATANIA|CATANZARO|ENNA|FERRARA|FOGGIA|FIRENZE|FORLI`|FROSINONE|GENOVA|GORIZIA|GROSSETO|IMPERIA|ISERNIA|CROTONE|LECCO|LECCE|LIVORNO|LODI|LATINA|LUCCA|MACERATA|MESSINA|MILANO|MANTOVA|MODENA|MASSA CARRARA|MATERA|NAPOLI|NOVARA|NUORO|ORISTANO|PALERMO|PIACENZA|PADOVA|PESCARA|PERUGIA|PISA|PORDENONE|PRATO|PARMA|PESARO E URBINO|PISTOIA|PAVIA|POTENZA|RAVENNA|REGGIO CALABRIA|REGGIO NELL`EMILIA|RAGUSA|RIETI|ROMA|RIMINI|ROVIGO|SALERNO|SIENA|SONDRIO|LA SPEZIA|SIRACUSA|SASSARI|SAVONA|TARANTO|TERAMO|TRENTO|TORINO|TRAPANI|TERNI|TRIESTE|TREVISO|UDINE|VARESE|VERBANIA|VERCELLI|VENEZIA|VICENZA|VERONA|VITERBO|VIBO VALENTIA'"/>
<xsl:variable name="Provincia" select="'PARMA'"/>
<xsl:variable name="userField9" select="'livelloMedioDelMare|Quota sul livello medio del mare|Double|-10000|10000'"/>
<xsl:variable name="livelloMedioDelMare" select="0"/>
<xsl:variable name="userField10" select="'estMedia|Est Media|Double|-10000000|10000000'"/>
<xsl:variable name="estMedia" select="0"/>
<xsl:variable name="userField11" select="'linearPrecision|Precisione lineare (mm)|stringMenu|2|10|100'"/>
<xsl:variable name="linearPrecision" select="'10'"/>
<xsl:variable name="userField12" select="'angularPrecision|Precisione angolare (cc)|stringMenu|2|100|20'"/>
<xsl:variable name="angularPrecision" select="'20'"/>
<xsl:variable name="userField13" select="'Nota|Nota|String'"/>
<xsl:variable name="Nota" select="'Nota: '"/>
<xsl:variable name="userField14" select="'tipoAggiomamento|Tipo di Aggiomamento|stringMenu|5|FRazionamento  (FR)|Mappale per nuova Costr.  (MC)|Mappale per Ampliamento  (MA)|mod. 26 per fabbr. rurale  (26)|PArticellare  (PA)'"/>
<xsl:variable name="tipoAggiomamento" select="'FRazionamento  (FR)'"/>
<xsl:variable name="userField15" select="'basePtName|Punto di base (opzionale)|string'"/>
<xsl:variable name="basePtName" select="''"/>
<xsl:variable name="userField16" select="'exportOffsetMeasurements|Esporta gli allineamenti|stringMenu|2|Sì|No'"/>
<xsl:variable name="exportOffsetMeasurements" select="'Sì'"/>
<xsl:variable name="userField17" select="'includeCalibPts|Include punti di calibrazione|stringMenu|2|Sì|No'"/>
<xsl:variable name="includeCalibPts" select="'No'"/>

<!-- **************************************************************** -->
<!-- Set global variables from the Environment section of JobXML file -->
<!-- **************************************************************** -->
<xsl:variable name="DistUnit"   select="/JOBFile/Environment/DisplaySettings/DistanceUnits" />
<xsl:variable name="AngleUnit"  select="/JOBFile/Environment/DisplaySettings/AngleUnits" />
<xsl:variable name="CoordOrder" select="/JOBFile/Environment/DisplaySettings/CoordinateOrder" />
<xsl:variable name="TempUnit"   select="/JOBFile/Environment/DisplaySettings/TemperatureUnits" />
<xsl:variable name="PressUnit"  select="/JOBFile/Environment/DisplaySettings/PressureUnits" />
<xsl:variable name="EarthRadius">
  <xsl:choose>
    <xsl:when test="/JOBFile/Environment/CoordinateSystem/Ellipsoid/EarthRadius != ''">
      <xsl:value-of select="/JOBFile/Environment/CoordinateSystem/Ellipsoid/EarthRadius"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="6378137.0"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:variable name="ProjectHeight" select="/JOBFile/Environment/CoordinateSystem/LocalSite/ProjectLocationHeight"/>


<!-- Setup conversion factor for coordinate and distance values -->
<!-- Dist/coord values in JobXML file are always in metres -->
<xsl:variable name="DistConvFactor">
  <xsl:choose>
    <xsl:when test="$DistUnit='Metres'">1.0</xsl:when>
    <xsl:when test="$DistUnit='InternationalFeet'">3.280839895</xsl:when>
    <xsl:when test="$DistUnit='USSurveyFeet'">3.2808333333357</xsl:when>
    <xsl:otherwise>1.0</xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<!-- Setup conversion factor for angular values -->
<xsl:variable name="AngleConvFactor">
  <xsl:choose>
    <xsl:when test="$AngleUnit='DMSDegrees'">1.0</xsl:when>
    <xsl:when test="$AngleUnit='Gons'">1.111111111111</xsl:when>
    <xsl:when test="$AngleUnit='Mils'">17.77777777777</xsl:when>
    <xsl:otherwise>1.0</xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<!-- Setup boolean variable for coordinate order -->
<xsl:variable name="NECoords">
  <xsl:choose>
    <xsl:when test="$CoordOrder='North-East-Elevation'">true</xsl:when>
    <xsl:when test="$CoordOrder='X-Y-Z'">true</xsl:when>
    <xsl:otherwise>false</xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<!-- Setup conversion factor for pressure values -->
<!-- Pressure values in JobXML file are always in millibars (hPa) -->
<xsl:variable name="PressConvFactor">
  <xsl:choose>
    <xsl:when test="$PressUnit='MilliBar'">1.0</xsl:when>
    <xsl:when test="$PressUnit='InchHg'">0.029529921</xsl:when>
    <xsl:when test="$PressUnit='mmHg'">0.75006</xsl:when>
    <xsl:otherwise>1.0</xsl:otherwise>
  </xsl:choose>
</xsl:variable>


<!-- **************************************************************** -->
<!-- ************************** Main Loop *************************** -->
<!-- **************************************************************** -->
<xsl:template match="/" >
  <xsl:value-of select="'0|'"/>
  <xsl:value-of select="substring(JOBFile/@TimeStamp, 9, 2)"/> <!-- The day -->
  <xsl:value-of select="substring(JOBFile/@TimeStamp, 6, 2)"/> <!-- The month -->
  <xsl:value-of select="substring(JOBFile/@TimeStamp, 1, 4)"/> <!-- The year -->
  <xsl:value-of select="concat('|', $Protocollo, '|', $Comune, '|', $Foglio, '|',
                               $Mappali, '|', $Cognome, ' ', $Nome, '|',
                               $Qualifica, '|', $Provincia, '|')"/>
  <xsl:call-template name="NewLine"/>

<!-- Use the requested mean elevation and mean easting rather than computing the values
  <xsl:variable name="meanElev" select="sum(/JOBFile/Reductions/Point/Grid/Elevation[. != '']) div count(/JOBFile/Reductions/Point/Grid/Elevation[. != ''])"/>
  <xsl:variable name="meanEast" select="sum(/JOBFile/Reductions/Point/Grid/East[. != '']) div count(/JOBFile/Reductions/Point/Grid/East[. != ''])"/>
-->
  <xsl:variable name="tipoStr">
    <xsl:call-template name="GetTipoOutputStr">
      <xsl:with-param name="inStr" select="$tipoAggiomamento"/>
    </xsl:call-template>
  </xsl:variable>
  <xsl:value-of select="concat('9|',
                               format-number($livelloMedioDelMare * $DistConvFactor, $DecPl0, 'Standard'),
                               '|', $linearPrecision, '|', $angularPrecision, '|',
                               format-number($estMedia * $DistConvFactor, $DecPl0, 'Standard'),
                               '|10.00-G,Stda 4.00|', $tipoStr, '|', $Nota, '|')"/>
  <xsl:call-template name="NewLine"/>

  <!-- Select the FieldBook node to process -->
  <xsl:apply-templates select="JOBFile/FieldBook"/>

  <!-- Output details of calibration points -->
  <xsl:if test="$includeCalibPts = 'Sì'">
    <xsl:apply-templates select="JOBFile/Environment/CoordinateSystem/CalibrationPointPairs"/>
  </xsl:if>
</xsl:template>


<!-- **************************************************************** -->
<!-- ***************** FieldBook Node Processing ******************** -->
<!-- **************************************************************** -->
<xsl:template match="FieldBook">
  <!-- Output all the measured GPS points -->
  <xsl:apply-templates select="InitialisationRecord[1]"/>

  <!-- If there are no InitialisationRecord elements but there are Reductions/Point elements that  -->
  <!-- have WGS84 elements then output these points as relative vectors from the first WGS84 point -->
  <xsl:if test="(count(InitialisationRecord) = 0) and (count(/JOBFile/Reductions/Point[WGS84]) != 0)">
    <xsl:call-template name="OutputReducedWGS84Points"/>
  </xsl:if>

  <!-- Output all the conventional points -->
  <xsl:apply-templates select="StationRecord"/>
  
  <!-- Now output all the Cogo computed points -->
  <xsl:if test="$exportOffsetMeasurements = 'Sì'">
    <xsl:for-each select="PointRecord[EnteredData or Polar]">
      <xsl:call-template name="OutputMeasuredData"/>
    </xsl:for-each>
  </xsl:if>

  <!-- Now output all the lines defined in the job -->
  <xsl:call-template name="OutputLineRecords"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******************* InitialisationRecord Output ********************* -->
<!-- **************************************************************** -->
<xsl:template match="InitialisationRecord">
  <!-- This is the first RTK base point initialisation record in the file -->

  <xsl:variable name="pointRecsFollowingFirstInitialisationRecord">
    <xsl:for-each select="following-sibling::*">
      <xsl:if test="(name(.) = 'PointRecord') and (Deleted = 'false') and
                    (((SurveyMethod = 'NetworkFix') or (SurveyMethod = 'NetworkFloat') or (SurveyMethod = 'Fix'))
                     and (ECEF or ECEFDeltas)) or
                    (WGS84 and ((Method = 'Coordinates') or ($exportOffsetMeasurements != 'Sì')))">
        <xsl:if test="position() &gt; 0">
          <xsl:variable name="ptName" select="Name"/>
          <xsl:element name="Point">
            <xsl:attribute name="TimeStamp">
              <xsl:value-of select="@TimeStamp"/>
            </xsl:attribute>
            <xsl:element name="Name">
              <xsl:value-of select="Name"/>
            </xsl:element>
            <xsl:element name="Code">
              <xsl:value-of select="Code"/>
            </xsl:element>
            <xsl:element name="QualityControl1">   <!-- Add the QualityControl1 element -->
              <xsl:copy-of select="QualityControl1/*"/>
            </xsl:element>
            <xsl:if test="QualityControl2">
              <xsl:element name="QualityControl2">   <!-- Add the QualityControl2 element -->
                <xsl:copy-of select="QualityControl2/*"/>
              </xsl:element>
            </xsl:if>
            <!-- Add the point latitude from the Reductions section -->
            <xsl:element name="Latitude">
              <xsl:for-each select="/JOBFile/Reductions/Point[Name = $ptName]">
                <xsl:value-of select="WGS84/Latitude"/>
              </xsl:for-each>
            </xsl:element>
            <!-- Add the point longitude from the Reductions section -->
            <xsl:element name="Longitude">
              <xsl:for-each select="/JOBFile/Reductions/Point[Name = $ptName]">
                <xsl:value-of select="WGS84/Longitude"/>
              </xsl:for-each>
            </xsl:element>
            <!-- Add the point height from the Reductions section -->
            <xsl:element name="Height">
              <xsl:for-each select="/JOBFile/Reductions/Point[Name = $ptName]">
                <xsl:value-of select="WGS84/Height"/>
              </xsl:for-each>
            </xsl:element>
          </xsl:element>
        </xsl:if>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>

  <!-- Get a node set of any points in the FieldBook section that are recorded   -->
  <!-- as reference points so that the first point in this node set is available -->
  <!-- as the default base point if a base point is not specified.               -->
  <xsl:variable name="referencePoints">
    <xsl:variable name="refPts">
      <xsl:for-each select="/JOBFile/FieldBook/ReferenceRecord">
        <xsl:variable name="ptName" select="PointName"/>
        <xsl:for-each select="/JOBFile/Reductions/Point[Name = $ptName]">
          <xsl:copy-of select="."/>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:variable>
    
    <!-- Only record the unique reference points -->
    <xsl:for-each select="msxsl:node-set($refPts)/Point">
      <xsl:variable name="ptName" select="Name"/>
      <xsl:if test="count(preceding-sibling::*[Name = $ptName]) = 0">
        <xsl:copy-of select="."/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>

  <!-- Get the Starting time for this occupation from the first Point record -->
  <xsl:variable name="occupationStartTime">
    <xsl:for-each select="msxsl:node-set($pointRecsFollowingFirstInitialisationRecord)/Point[1]">
      <xsl:value-of select="concat(substring(@TimeStamp, 9, 2),
                                   substring(@TimeStamp, 6, 2),
                                   substring(@TimeStamp, 1, 4), '-',
                                   substring(@TimeStamp, 12, 2), ':',
                                   substring(@TimeStamp, 15, 2))"/>
    </xsl:for-each>
  </xsl:variable>

  <!-- Get the Ending time for this occupation from the last Point record -->
  <xsl:variable name="occupationEndTime">
    <xsl:for-each select="msxsl:node-set($pointRecsFollowingFirstInitialisationRecord)/Point[last()]">
      <xsl:value-of select="concat(substring(@TimeStamp, 9, 2),
                                   substring(@TimeStamp, 6, 2),
                                   substring(@TimeStamp, 1, 4), '-',
                                   substring(@TimeStamp, 12, 2), ':',
                                   substring(@TimeStamp, 15, 2))"/>
    </xsl:for-each>
  </xsl:variable>

  <xsl:variable name="upperCaseBasePtName" select="translate($basePtName,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
  <xsl:variable name="localBase">
    <xsl:choose>
      <xsl:when test="($basePtName = '') or
                      (($basePtName != '')
                       and (count(/JOBFile/Reductions/Point[translate(Name,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') = $upperCaseBasePtName]) = 0))">
        <!-- There was no base point name specified or the specified base point name doesn't exist -->
        <!-- If there is at least one point in the $fromBasePoints node set then use the first     -->
        <!-- point from it as the base point otherwise use the first point in the                  -->
        <!-- $pointRecsFollowingFirstInitialisationRecord node set as the referenced base point    -->
        <!-- for the purposes of the file output.                                                  -->
        <xsl:choose>
          <xsl:when test="count(msxsl:node-set($referencePoints)/Point) != 0">
            <xsl:element name="name">
              <xsl:value-of select="msxsl:node-set($referencePoints)/Point[1]/Name"/>
            </xsl:element>
          </xsl:when>
          <xsl:otherwise>
            <xsl:element name="name">
              <xsl:value-of select="msxsl:node-set($pointRecsFollowingFirstInitialisationRecord)/Point[1]/Name"/>
            </xsl:element>
          </xsl:otherwise>
        </xsl:choose>

        <xsl:variable name="baseLat">
          <xsl:choose>
            <xsl:when test="count(msxsl:node-set($referencePoints)/Point) != 0">
              <xsl:value-of select="msxsl:node-set($referencePoints)/Point[1]/WGS84/Latitude"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="msxsl:node-set($pointRecsFollowingFirstInitialisationRecord)/Point[1]/Latitude"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:variable name="baseLong">
          <xsl:choose>
            <xsl:when test="count(msxsl:node-set($referencePoints)/Point) != 0">
              <xsl:value-of select="msxsl:node-set($referencePoints)/Point[1]/WGS84/Longitude"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="msxsl:node-set($pointRecsFollowingFirstInitialisationRecord)/Point[1]/Longitude"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:variable name="baseHeight">
          <xsl:choose>
            <xsl:when test="count(msxsl:node-set($referencePoints)/Point) != 0">
              <xsl:value-of select="msxsl:node-set($referencePoints)/Point[1]/WGS84/Height"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="msxsl:node-set($pointRecsFollowingFirstInitialisationRecord)/Point[1]/Height"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:element name="X">
          <xsl:call-template name="ecefX">
            <xsl:with-param name="latitude" select="$baseLat"/>
            <xsl:with-param name="longitude" select="$baseLong"/>
            <xsl:with-param name="height" select="$baseHeight"/>
          </xsl:call-template>
        </xsl:element>

        <xsl:element name="Y">
          <xsl:call-template name="ecefY">
            <xsl:with-param name="latitude" select="$baseLat"/>
            <xsl:with-param name="longitude" select="$baseLong"/>
            <xsl:with-param name="height" select="$baseHeight"/>
          </xsl:call-template>
        </xsl:element>

        <xsl:element name="Z">
          <xsl:call-template name="ecefZ">
            <xsl:with-param name="latitude" select="$baseLat"/>
            <xsl:with-param name="height" select="$baseHeight"/>
          </xsl:call-template>
        </xsl:element>
      </xsl:when>

      <xsl:otherwise>  <!-- We have a referenced base point so use it -->
        <xsl:element name="name">
          <xsl:value-of select="$basePtName"/>
        </xsl:element>

        <xsl:variable name="baseLat" select="/JOBFile/Reductions/Point[Name = $basePtName]/WGS84/Latitude"/>
        <xsl:variable name="baseLong" select="/JOBFile/Reductions/Point[Name = $basePtName]/WGS84/Longitude"/>
        <xsl:variable name="baseHeight" select="/JOBFile/Reductions/Point[Name = $basePtName]/WGS84/Height"/>

        <xsl:element name="X">
          <xsl:call-template name="ecefX">
            <xsl:with-param name="latitude" select="$baseLat"/>
            <xsl:with-param name="longitude" select="$baseLong"/>
            <xsl:with-param name="height" select="$baseHeight"/>
          </xsl:call-template>
        </xsl:element>

        <xsl:element name="Y">
          <xsl:call-template name="ecefY">
            <xsl:with-param name="latitude" select="$baseLat"/>
            <xsl:with-param name="longitude" select="$baseLong"/>
            <xsl:with-param name="height" select="$baseHeight"/>
          </xsl:call-template>
        </xsl:element>

        <xsl:element name="Z">
          <xsl:call-template name="ecefZ">
            <xsl:with-param name="latitude" select="$baseLat"/>
            <xsl:with-param name="height" select="$baseHeight"/>
          </xsl:call-template>
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Output the specified or first point after the InitialisationRecord as a 'Local' base -->
  <xsl:call-template name="BasePoint">
    <xsl:with-param name="ptName" select="msxsl:node-set($localBase)/name"/>
    <xsl:with-param name="antennaHt" select="0"/>  <!-- We are working with ground positions so fix antenna ht to zero -->
    <xsl:with-param name="startTime" select="$occupationStartTime"/>
    <xsl:with-param name="endTime" select="$occupationEndTime"/>
    <xsl:with-param name="PDOP" select="msxsl:node-set($pointRecsFollowingFirstInitialisationRecord)/Point[1]/QualityControl1/PDOP"/>
    <xsl:with-param name="baseX" select="msxsl:node-set($localBase)/X"/>
    <xsl:with-param name="baseY" select="msxsl:node-set($localBase)/Y"/>
    <xsl:with-param name="baseZ" select="msxsl:node-set($localBase)/Z"/>
    <xsl:with-param name="code" select="msxsl:node-set($pointRecsFollowingFirstInitialisationRecord)/Point[1]/Code"/>
  </xsl:call-template>

  <!-- Now output all the points following the InitialisationRecord as vectors from -->
  <!-- first point measured.                                                   -->
  <xsl:for-each select="msxsl:node-set($pointRecsFollowingFirstInitialisationRecord)/Point">
    <!-- Output all the points as long as they have lat, long and height values -->
    <xsl:if test="(string(number(Latitude)) != 'NaN') and
                  (string(number(Longitude)) != 'NaN') and
                  (string(number(Height)) != 'NaN')">
      <!-- Compute the X, Y, Z for this point from its reduced lat, long and height -->
      <xsl:variable name="pointX">
        <xsl:call-template name="ecefX">
          <xsl:with-param name="latitude" select="Latitude"/>
          <xsl:with-param name="longitude" select="Longitude"/>
          <xsl:with-param name="height" select="Height"/>
        </xsl:call-template>
      </xsl:variable>

      <xsl:variable name="pointY">
        <xsl:call-template name="ecefY">
          <xsl:with-param name="latitude" select="Latitude"/>
          <xsl:with-param name="longitude" select="Longitude"/>
          <xsl:with-param name="height" select="Height"/>
        </xsl:call-template>
      </xsl:variable>

      <xsl:variable name="pointZ">
        <xsl:call-template name="ecefZ">
          <xsl:with-param name="latitude" select="Latitude"/>
          <xsl:with-param name="height" select="Height"/>
        </xsl:call-template>
      </xsl:variable>

      <!-- Now compute the deltas from the 'Local' base to this point -->
      <xsl:variable name="deltaX" select="$pointX - msxsl:node-set($localBase)/X"/>
      <xsl:variable name="deltaY" select="$pointY - msxsl:node-set($localBase)/Y"/>
      <xsl:variable name="deltaZ" select="$pointZ - msxsl:node-set($localBase)/Z"/>

      <xsl:variable name="zeroDeltas">
        <xsl:call-template name="ZeroDeltasTest">
          <xsl:with-param name="deltaX" select="$deltaX"/>
          <xsl:with-param name="deltaY" select="$deltaY"/>
          <xsl:with-param name="deltaZ" select="$deltaZ"/>
        </xsl:call-template>
      </xsl:variable>

      <xsl:if test="$zeroDeltas = 'false'">
        <xsl:call-template name="GPSDeltas">
          <xsl:with-param name="deltaX" select="$deltaX"/>
          <xsl:with-param name="deltaY" select="$deltaY"/>
          <xsl:with-param name="deltaZ" select="$deltaZ"/>
          <xsl:with-param name="antennaHt" select="0"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:if>
  </xsl:for-each>

</xsl:template>


<!-- **************************************************************** -->
<!-- ****** Output the WGS84 points from the Reductions Section ***** -->
<!-- **************************************************************** -->
<xsl:template name="OutputReducedWGS84Points">

  <!-- Get the ECEF X,Y,Z coords for the first WGS-84 point to use as the 'base' point -->
  <xsl:variable name="baseX">
    <xsl:call-template name="ecefX">
      <xsl:with-param name="latitude" select="/JOBFile/Reductions/Point[WGS84][1]/WGS84/Latitude"/>
      <xsl:with-param name="longitude" select="/JOBFile/Reductions/Point[WGS84][1]/WGS84/Longitude"/>
      <xsl:with-param name="height" select="/JOBFile/Reductions/Point[WGS84][1]/WGS84/Height"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="baseY">
    <xsl:call-template name="ecefY">
      <xsl:with-param name="latitude" select="/JOBFile/Reductions/Point[WGS84][1]/WGS84/Latitude"/>
      <xsl:with-param name="longitude" select="/JOBFile/Reductions/Point[WGS84][1]/WGS84/Longitude"/>
      <xsl:with-param name="height" select="/JOBFile/Reductions/Point[WGS84][1]/WGS84/Height"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="baseZ">
    <xsl:call-template name="ecefZ">
      <xsl:with-param name="latitude" select="/JOBFile/Reductions/Point[WGS84][1]/WGS84/Latitude"/>
      <xsl:with-param name="height" select="/JOBFile/Reductions/Point[WGS84][1]/WGS84/Height"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:for-each select="/JOBFile/Reductions/Point[WGS84]">
    <xsl:choose>
      <xsl:when test="position() = 1">  <!-- This is the first WGS84 point - use as base point -->
        <xsl:call-template name="BasePoint">
          <xsl:with-param name="ptName" select="Name"/>
          <xsl:with-param name="antennaHt" select="0"/>
          <xsl:with-param name="startTime" select="''"/>
          <xsl:with-param name="endTime" select="''"/>
          <xsl:with-param name="PDOP" select="0"/>
          <xsl:with-param name="baseX" select="$baseX"/>
          <xsl:with-param name="baseY" select="$baseY"/>
          <xsl:with-param name="baseZ" select="$baseZ"/>
          <xsl:with-param name="code" select="Code"/>
        </xsl:call-template>
      </xsl:when>
      
      <xsl:otherwise>  <!-- Output point as a 'vector' from the 'base' point -->
        <xsl:variable name="pointX">
          <xsl:call-template name="ecefX">
            <xsl:with-param name="latitude" select="WGS84/Latitude"/>
            <xsl:with-param name="longitude" select="WGS84/Longitude"/>
            <xsl:with-param name="height" select="WGS84/Height"/>
          </xsl:call-template>
        </xsl:variable>

        <xsl:variable name="pointY">
          <xsl:call-template name="ecefY">
            <xsl:with-param name="latitude" select="WGS84/Latitude"/>
            <xsl:with-param name="longitude" select="WGS84/Longitude"/>
            <xsl:with-param name="height" select="WGS84/Height"/>
          </xsl:call-template>
        </xsl:variable>

        <xsl:variable name="pointZ">
          <xsl:call-template name="ecefZ">
            <xsl:with-param name="latitude" select="WGS84/Latitude"/>
            <xsl:with-param name="height" select="WGS84/Height"/>
          </xsl:call-template>
        </xsl:variable>

        <!-- Now compute the deltas from the 'Local' base to this point -->
        <xsl:variable name="deltaX" select="$pointX - $baseX"/>
        <xsl:variable name="deltaY" select="$pointY - $baseY"/>
        <xsl:variable name="deltaZ" select="$pointZ - $baseZ"/>

        <xsl:variable name="zeroDeltas">
          <xsl:call-template name="ZeroDeltasTest">
            <xsl:with-param name="deltaX" select="$deltaX"/>
            <xsl:with-param name="deltaY" select="$deltaY"/>
            <xsl:with-param name="deltaZ" select="$deltaZ"/>
          </xsl:call-template>
        </xsl:variable>

        <xsl:if test="$zeroDeltas = 'false'">
          <xsl:call-template name="GPSDeltas">
            <xsl:with-param name="deltaX" select="$deltaX"/>
            <xsl:with-param name="deltaY" select="$deltaY"/>
            <xsl:with-param name="deltaZ" select="$deltaZ"/>
            <xsl:with-param name="antennaHt" select="0"/>
          </xsl:call-template>
        </xsl:if>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******************** RTK Base Point Output ********************* -->
<!-- **************************************************************** -->
<xsl:template name="BasePoint">
  <xsl:param name="ptName"/>
  <xsl:param name="antennaHt"/>
  <xsl:param name="startTime"/>
  <xsl:param name="endTime"/>
  <xsl:param name="PDOP"/>
  <xsl:param name="baseX"/>
  <xsl:param name="baseY"/>
  <xsl:param name="baseZ"/>
  <xsl:param name="code" select="''"/>

  <xsl:variable name="upperCaseBasePtName" select="translate($ptName,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>

  <xsl:value-of select="concat('1|', $upperCaseBasePtName, '|',
                               format-number($baseX * $DistConvFactor, $DecPl2, 'Standard'),
                               ',',
                               format-number($baseY * $DistConvFactor, $DecPl2, 'Standard'),
                               ',',
                               format-number($baseZ * $DistConvFactor, $DecPl2, 'Standard'),
                               '|')"/>
  
  <xsl:value-of select="concat(format-number($antennaHt, $DecPl3, 'Standard'), '|')"/>

  <!-- Output the point code if available otherwise set to 'Punto Iniziale Baseline' -->
  <xsl:choose>
    <xsl:when test="$code != ''">
      <xsl:value-of select="concat($code, '|')"/>
    </xsl:when>
    <xsl:otherwise>Punto Iniziale Baseline|</xsl:otherwise>
  </xsl:choose>

  <xsl:call-template name="NewLine"/>

  <!-- Now output the '6' line that records the occupation time for the base point -->
  <xsl:value-of select="concat('6|L2|', $startTime, '|', $endTime)"/>

  <xsl:value-of select="concat('|RTK|PDOP=', format-number($PDOP, $DecPl0, 'Standard'), '|')"/>
  <xsl:call-template name="NewLine"/>

</xsl:template>


<!-- **************************************************************** -->
<!-- ********************** GPS Deltas Output *********************** -->
<!-- **************************************************************** -->
<xsl:template name="GPSDeltas">
  <xsl:param name="deltaX"/>
  <xsl:param name="deltaY"/>
  <xsl:param name="deltaZ"/>
  <xsl:param name="antennaHt" select="'0'"/>

  <xsl:variable name="PDOP">
    <xsl:choose>
      <xsl:when test="QualityControl1/PDOP != ''">
        <xsl:value-of select="format-number(QualityControl1/PDOP, $DecPl0, 'Standard')"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="1"/>   <!-- Default to a PDOP of 1 if not available -->
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="upperCaseName" select="translate(Name,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>

  <xsl:value-of select="concat('2|', $upperCaseName, '|',
                        format-number($deltaX * $DistConvFactor, $DecPl3, 'Standard'), ',',
                        format-number($deltaY * $DistConvFactor, $DecPl3, 'Standard'), ',',
                        format-number($deltaZ * $DistConvFactor, $DecPl3, 'Standard'), '|')"/>

  <!-- Get the variance-covariance values if available -->
  <xsl:choose>
    <xsl:when test="QualityControl2">
      <xsl:value-of select="concat(format-number(QualityControl2/VCVxx, $DecPl8, 'Standard'), ',',
                                   format-number(QualityControl2/VCVxy, $DecPl8, 'Standard'), ',',
                                   format-number(QualityControl2/VCVxz, $DecPl8, 'Standard'), ',',
                                   format-number(QualityControl2/VCVyy, $DecPl8, 'Standard'), ',',
                                   format-number(QualityControl2/VCVyz, $DecPl8, 'Standard'), ',',
                                   format-number(QualityControl2/VCVzz, $DecPl8, 'Standard'))"/>
    </xsl:when>
    <xsl:otherwise>   <!-- No QC2 record so output default zero values -->
      <xsl:value-of select="'0,0,0,0,0,0'"/>
    </xsl:otherwise>
  </xsl:choose>

  <!-- Output the PDOP details -->
  <xsl:value-of select="concat('|PDOP=', $PDOP, '|')"/>

  <!-- Add the antenna height -->
  <xsl:value-of select="concat(format-number($antennaHt, $DecPl3, 'Standard'), '|')"/>

  <!-- Output the point code if available -->
  <xsl:if test="Code != ''">
    <xsl:value-of select="concat(Code, '|')"/>
  </xsl:if>

  <xsl:call-template name="NewLine"/>

</xsl:template>


<!-- **************************************************************** -->
<!-- ******* Output the measured details for fixing this point ****** -->
<!-- **************************************************************** -->
<xsl:template name="OutputMeasuredData">

  <xsl:choose>
    <xsl:when test="EnteredData/Method = 'DistanceDistanceIntersection'">
      <xsl:call-template name="OutputDistDistIntersectCalc"/>
    </xsl:when>

    <xsl:when test="EnteredData/Method = 'FromABaseline'">
      <xsl:call-template name="OutputBaselineOffset"/>
    </xsl:when>

  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******* Output the measured details for an intersect calc ****** -->
<!-- **************************************************************** -->
<xsl:template name="OutputDistDistIntersectCalc">

  <!-- Need to determine which side of the line between the 2 points the computed point -->
  <!-- is on.  If there are grid coordinates then use them in the cross product calc    -->
  <!-- otherwise simply use the WGS-84 lat and long as if they are grid values.         -->
  <xsl:variable name="startPt">
    <xsl:variable name="startPtName" select="EnteredData/PointOne"/>
    <xsl:for-each select="/JOBFile/Reductions/Point[Name = $startPtName]">
      <xsl:choose>
        <xsl:when test="(string(number(Grid/North)) != 'NaN') and (string(number(Grid/East)) != 'NaN')">
          <xsl:element name="north">
            <xsl:value-of select="Grid/North"/>
          </xsl:element>
          <xsl:element name="east">
            <xsl:value-of select="Grid/East"/>
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:element name="north">
            <xsl:value-of select="WGS84/Latitude"/>
          </xsl:element>
          <xsl:element name="east">
            <xsl:value-of select="WGS84/Longitude"/>
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:variable>

  <xsl:variable name="endPt">
    <xsl:variable name="endPtName" select="EnteredData/PointTwo"/>
    <xsl:for-each select="/JOBFile/Reductions/Point[Name = $endPtName]">
      <xsl:choose>
        <xsl:when test="(string(number(Grid/North)) != 'NaN') and (string(number(Grid/East)) != 'NaN')">
          <xsl:element name="north">
            <xsl:value-of select="Grid/North"/>
          </xsl:element>
          <xsl:element name="east">
            <xsl:value-of select="Grid/East"/>
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:element name="north">
            <xsl:value-of select="WGS84/Latitude"/>
          </xsl:element>
          <xsl:element name="east">
            <xsl:value-of select="WGS84/Longitude"/>
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:variable>

  <xsl:variable name="ptGridPos">  <!-- Coords could be in Grid element if saved as grid point or -->
    <xsl:choose>                   <!-- in ComputedGrid element if stored as a WGS-84 position    -->
      <xsl:when test="Grid">
        <xsl:element name="north">
          <xsl:value-of select="Grid/North"/>
        </xsl:element>
        <xsl:element name="east">
          <xsl:value-of select="Grid/East"/>
        </xsl:element>
      </xsl:when>
      <xsl:when test="ComputedGrid">
        <xsl:element name="north">
          <xsl:value-of select="ComputedGrid/North"/>
        </xsl:element>
        <xsl:element name="east">
          <xsl:value-of select="ComputedGrid/East"/>
        </xsl:element>
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="north">
          <xsl:value-of select="WGS84/Latitude"/>
        </xsl:element>
        <xsl:element name="east">
          <xsl:value-of select="WGS84/Longitude"/>
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="crossProd">
    <xsl:call-template name="CrossProduct">
      <xsl:with-param name="pointX" select="msxsl:node-set($ptGridPos)/east"/>
      <xsl:with-param name="pointY" select="msxsl:node-set($ptGridPos)/north"/>
      <xsl:with-param name="startX" select="msxsl:node-set($startPt)/east"/>
      <xsl:with-param name="startY" select="msxsl:node-set($startPt)/north"/>
      <xsl:with-param name="endX" select="msxsl:node-set($endPt)/east"/>
      <xsl:with-param name="endY" select="msxsl:node-set($endPt)/north"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="ptOnRight">
    <xsl:choose>
      <xsl:when test="$crossProd &lt; 0">false</xsl:when>
      <xsl:otherwise>true</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="upperCasePtName" select="translate(Name,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
  <xsl:variable name="upperCasePt1Name" select="translate(EnteredData/PointOne,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
  <xsl:variable name="upperCasePt2Name" select="translate(EnteredData/PointTwo,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>

  <!-- Now output the actual file records (types 4 and 5) -->
  <!-- Output the base line (point 1 to point 2) and 30 (if point to right) or -30 (if point to left) -->
  <xsl:text>4|</xsl:text>
  <xsl:value-of select="$upperCasePt1Name"/>
  <xsl:text>|</xsl:text>
  <xsl:value-of select="$upperCasePt2Name"/>
  <xsl:choose>
    <xsl:when test="$ptOnRight = 'true'">|30|</xsl:when>
    <xsl:otherwise>|-30|</xsl:otherwise>
  </xsl:choose>
  <xsl:call-template name="NewLine"/>

  <!-- Output the distance from point 1 to the point -->
  <xsl:text>5|</xsl:text>
  <xsl:value-of select="$upperCasePtName"/>
  <xsl:text>|</xsl:text>
  <xsl:value-of select="format-number(EnteredData/DistanceOne * $DistConvFactor, $DecPl2, 'Standard')"/>
  <xsl:text>|0|</xsl:text>
  <xsl:if test="Code != ''">
    <xsl:value-of select="Code"/>
    <xsl:text>|</xsl:text>
  </xsl:if>
  <xsl:call-template name="NewLine"/>

  <!-- Output the base line referenced in reverse -->
  <xsl:text>4|</xsl:text>
  <xsl:value-of select="$upperCasePt2Name"/>
  <xsl:text>|</xsl:text>
  <xsl:value-of select="$upperCasePtName"/>
  <xsl:text>|0|</xsl:text>
  <xsl:call-template name="NewLine"/>

  <!-- Output the distance from point 2 to the point -->
  <xsl:text>5|</xsl:text>
  <xsl:value-of select="$upperCasePtName"/>
  <xsl:text>|</xsl:text>
  <xsl:value-of select="format-number(EnteredData/DistanceTwo * $DistConvFactor, $DecPl2, 'Standard')"/>
  <xsl:text>|0|</xsl:text>
  <xsl:if test="Code != ''">
    <xsl:value-of select="Code"/>
    <xsl:text>|</xsl:text>
  </xsl:if>
  <xsl:call-template name="NewLine"/>

  <xsl:variable name="ptElev">
    <xsl:choose>
      <xsl:when test="Grid">
        <xsl:value-of select="Grid/Elevation"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="ComputedGrid/Elevation"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Now output the delta elevation from the first point to the computed point if possible -->
  <xsl:if test="string(number(msxsl:node-set($startPt)/elev - $ptElev)) != 'NaN'">
    <xsl:text>4|</xsl:text>
    <xsl:value-of select="$upperCasePt1Name"/>
    <xsl:text>|1.50|</xsl:text>   <!-- Use nominal 'reading' of 1.50 -->
    <xsl:call-template name="NewLine"/>

    <xsl:text>5|</xsl:text>
    <xsl:value-of select="$upperCasePtName"/>
    <xsl:text>|</xsl:text>
    <xsl:variable name="deltaElev" select="(msxsl:node-set($startPt)/elev - $ptElev) * $DistConvFactor"/>
    <xsl:value-of select="format-number(1.50 + $deltaElev, $DecPl2, 'Standard')"/>
    <xsl:text>|</xsl:text>
    <xsl:call-template name="NewLine"/>
  </xsl:if>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******* Output the measured details for a baseline offset ****** -->
<!-- **************************************************************** -->
<xsl:template name="OutputBaselineOffset">

  <xsl:variable name="upperCasePtName" select="translate(Name,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
  <xsl:variable name="upperCasePt1Name" select="translate(EnteredData/PointOne,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
  <xsl:variable name="upperCasePt2Name" select="translate(EnteredData/PointTwo,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>

  <xsl:variable name="startPt">
    <xsl:variable name="startPtName" select="EnteredData/PointOne"/>
    <xsl:for-each select="/JOBFile/Reductions/Point[Name = $startPtName]">
      <xsl:element name="north">
        <xsl:value-of select="Grid/North"/>
      </xsl:element>
      <xsl:element name="east">
        <xsl:value-of select="Grid/East"/>
      </xsl:element>
      <xsl:element name="elev">
        <xsl:value-of select="Grid/Elevation"/>
      </xsl:element>
    </xsl:for-each>
  </xsl:variable>

  <xsl:variable name="endPt">
    <xsl:variable name="endPtName" select="EnteredData/PointTwo"/>
    <xsl:for-each select="/JOBFile/Reductions/Point[Name = $endPtName]">
      <xsl:element name="north">
        <xsl:value-of select="Grid/North"/>
      </xsl:element>
      <xsl:element name="east">
        <xsl:value-of select="Grid/East"/>
      </xsl:element>
    </xsl:for-each>
  </xsl:variable>

  <xsl:variable name="baseLineLength">
    <xsl:call-template name="InverseDistance">
      <xsl:with-param name="deltaN" select="msxsl:node-set($endPt)/north - msxsl:node-set($startPt)/north"/>
      <xsl:with-param name="deltaE" select="msxsl:node-set($endPt)/east - msxsl:node-set($startPt)/east"/>
    </xsl:call-template>
  </xsl:variable>

  <!-- Output the baseline offset measurements using type 4 and 5 records -->
  <xsl:text>4|</xsl:text>
  <xsl:value-of select="$upperCasePt1Name"/>
  <xsl:text>|</xsl:text>
  <xsl:value-of select="$upperCasePt2Name"/>
  <xsl:text>|0|*S*|</xsl:text>
  <xsl:call-template name="NewLine"/>

  <xsl:variable name="alongVal">
    <xsl:choose>
      <xsl:when test="EnteredData/DirectionAlongLine = 'InFromStart'">
        <xsl:value-of select="EnteredData/DistanceOne"/>
      </xsl:when>
      <xsl:when test="EnteredData/DirectionAlongLine = 'OutFromStart'">
        <xsl:value-of select="EnteredData/DistanceOne * -1"/>
      </xsl:when>
      <xsl:when test="EnteredData/DirectionAlongLine = 'InFromEnd'">
        <xsl:value-of select="$baseLineLength - EnteredData/DistanceOne"/>
      </xsl:when>
      <xsl:when test="EnteredData/DirectionAlongLine = 'OutFromEnd'">
        <xsl:value-of select="$baseLineLength + EnteredData/DistanceOne"/>
      </xsl:when>
    </xsl:choose>
  </xsl:variable>

  <xsl:text>5|</xsl:text>
  <xsl:value-of select="$upperCasePtName"/>
  <xsl:text>|</xsl:text>
  <xsl:value-of select="format-number($alongVal * $DistConvFactor, $DecPl2, 'Standard')"/>
  <xsl:text>|</xsl:text>
  <xsl:value-of select="format-number(EnteredData/DistanceTwo * $DistConvFactor, $DecPl2, 'Standard')"/>
  <xsl:text>|</xsl:text>
  <xsl:if test="Code != ''">
    <xsl:value-of select="Code"/>
    <xsl:text>|</xsl:text>
  </xsl:if>
  <xsl:call-template name="NewLine"/>

  <xsl:variable name="ptElev">
    <xsl:choose>
      <xsl:when test="Grid">
        <xsl:value-of select="Grid/Elevation"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="ComputedGrid/Elevation"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Output delta elevation to the offset point if possible -->
  <xsl:if test="string(number(msxsl:node-set($startPt)/elev - $ptElev)) != 'NaN'">
    <xsl:text>4|</xsl:text>
    <xsl:value-of select="$upperCasePt1Name"/>
    <xsl:text>|1.50|</xsl:text>   <!-- Use nominal 'reading' of 1.50 -->
    <xsl:call-template name="NewLine"/>

    <xsl:text>5|</xsl:text>
    <xsl:value-of select="$upperCasePtName"/>
    <xsl:text>|</xsl:text>
    <xsl:variable name="deltaElev" select="(msxsl:node-set($startPt)/elev - $ptElev) * $DistConvFactor"/>
    <xsl:value-of select="format-number(1.50 + $deltaElev, $DecPl2, 'Standard')"/>
    <xsl:text>|</xsl:text>
    <xsl:call-template name="NewLine"/>
  </xsl:if>
</xsl:template>


<!-- **************************************************************** -->
<!-- ********************** Output line definition ****************** -->
<!-- **************************************************************** -->
<xsl:template name="OutputLineRecords">

  <xsl:variable name="lines">
    <xsl:for-each select="LineRecord[Method = 'TwoPoints']">
      <xsl:choose>
        <xsl:when test="(position() = 1) or (StartPoint != preceding-sibling::LineRecord[Method = 'TwoPoints'][1]/EndPoint)">
          <xsl:element name="newSequence">
            <xsl:attribute name="code">
              <xsl:value-of select="Code"/>
            </xsl:attribute>
          </xsl:element>
          <xsl:element name="point">
            <xsl:value-of select="StartPoint"/>
          </xsl:element>
          <xsl:element name="point">
            <xsl:value-of select="EndPoint"/>
          </xsl:element>
        </xsl:when>

        <xsl:otherwise>
          <xsl:element name="point">
            <xsl:value-of select="EndPoint"/>
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:variable>

  <xsl:for-each select="msxsl:node-set($lines)/*">
    <xsl:choose>
      <xsl:when test="name(.) = 'newSequence'">
        <xsl:if test="position() != 1">
          <!-- End the previous line output -->
          <xsl:text>RC|</xsl:text>
          <xsl:call-template name="NewLine"/>
        </xsl:if>

        <!-- If the line has been assigned a code output it as a 6 record -->
        <xsl:if test="@code != ''">
          <xsl:text>6|</xsl:text>
          <xsl:value-of select="@code"/>
          <xsl:text>|</xsl:text>
          <xsl:call-template name="NewLine"/>
        </xsl:if>

        <!-- Output the start of a new line definition as a 7 record -->
        <xsl:text>7|</xsl:text>
        <!-- Need to determine how many points in this sequence -->
        <xsl:variable name="sequenceStr">
          <xsl:for-each select="following-sibling::*">
            <xsl:choose>
              <xsl:when test="name(.) = 'point'">x</xsl:when>
              <xsl:otherwise>-</xsl:otherwise>
            </xsl:choose>
          </xsl:for-each>
        </xsl:variable>
        <xsl:variable name="ptCount">
          <xsl:choose>
            <xsl:when test="contains($sequenceStr, '-')">
              <!-- We need to get the portion of the string before the first '-' char -->
              <xsl:variable name="tempStr" select="substring-before($sequenceStr, '-')"/>
              <!-- Return the length of this portion of the string -->
              <xsl:value-of select="string-length($tempStr)"/>
            </xsl:when>
            <xsl:otherwise>  <!-- This must be the last line sequence - just return string length -->
              <xsl:value-of select="string-length($sequenceStr)"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>
        <xsl:value-of select="$ptCount"/>  <!-- Output the number of points in sequence -->
        <xsl:text>|</xsl:text>
      </xsl:when>

      <xsl:otherwise>   <!-- Must be a point element -->
        <xsl:variable name="upperCasePtName" select="translate(.,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
        <xsl:value-of select="$upperCasePtName"/>
        <xsl:text>|</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each>

  <xsl:if test="count(msxsl:node-set($lines)/*) != 0">
    <!-- End the final line sequence -->
    <xsl:text>RC|</xsl:text>
    <xsl:call-template name="NewLine"/>
  </xsl:if>

</xsl:template>


<!-- **************************************************************** -->
<!-- **************** Output calibration point details ************** -->
<!-- **************************************************************** -->
<xsl:template match="CalibrationPointPairs">

  <xsl:for-each select="CalibrationPointPair">
    <xsl:variable name="ptName" select="WGS84PointName"/>
    <xsl:variable name="upperCasePtName" select="translate(WGS84PointName,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>

    <xsl:if test="(Dimension = '2D') or (Dimension = '3D')">
      <!-- Output horizontal details -->
      <xsl:text>8|</xsl:text>
      <xsl:value-of select="$upperCasePtName"/>
      <xsl:text>|</xsl:text>
      <xsl:for-each select="/JOBFile/Reductions/Point[Name = $ptName]">
        <xsl:value-of select="format-number(Grid/North * $DistConvFactor, $DecPl6, 'Standard')"/>
        <xsl:text>|</xsl:text>
        <xsl:value-of select="format-number(Grid/East * $DistConvFactor, $DecPl6, 'Standard')"/>
        <xsl:text>|[P.A.]|</xsl:text>
        <xsl:if test="Code != ''">
          <xsl:value-of select="Code"/>
          <xsl:text>|</xsl:text>
        </xsl:if>
      </xsl:for-each>
      <xsl:call-template name="NewLine"/>
    </xsl:if>

    <!-- Output vertical details -->
    <xsl:if test="(Dimension = '1D') or (Dimension = '3D')">
      <xsl:text>8|</xsl:text>
      <xsl:value-of select="$upperCasePtName"/>
      <xsl:text>|</xsl:text>
      <xsl:for-each select="/JOBFile/Reductions/Point[Name = $ptName]">
        <xsl:value-of select="format-number(Grid/Elevation * $DistConvFactor, $DecPl6, 'Standard')"/>
        <xsl:text>|04|</xsl:text>
        <xsl:if test="Code != ''">
          <xsl:value-of select="Code"/>
          <xsl:text>|</xsl:text>
        </xsl:if>
      </xsl:for-each>
      <xsl:call-template name="NewLine"/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******** Tests to make sure the deltas are not all zero ******** -->
<!-- **************************************************************** -->
<xsl:template name="ZeroDeltasTest">
  <xsl:param name="deltaX"/>
  <xsl:param name="deltaY"/>
  <xsl:param name="deltaZ"/>
  
  <!-- Check that the passed in delta values are not all very close to zero -->
  <!-- Return true if thay are all very near zero otherwise return false    -->
  <xsl:variable name="absDeltaX" select="concat(substring('-',2 - ($deltaX &lt; 0)), '1') * $deltaX"/>
  <xsl:variable name="absDeltaY" select="concat(substring('-',2 - ($deltaY &lt; 0)), '1') * $deltaY"/>
  <xsl:variable name="absDeltaZ" select="concat(substring('-',2 - ($deltaZ &lt; 0)), '1') * $deltaZ"/>
  
  <xsl:choose>
    <xsl:when test="($absDeltaX &lt; 0.0001) and ($absDeltaX &lt; 0.0001) and ($absDeltaX &lt; 0.0001)">true</xsl:when>
    <xsl:otherwise>false</xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******************** StationRecord Output ********************** -->
<!-- **************************************************************** -->
<xsl:template match="StationRecord">

  <xsl:variable name="stnID" select="@ID"/>
  <!-- Output the station details if at least 1 point has been observed from the station -->
  <xsl:if test="count(following-sibling::PointRecord[StationID = $stnID]) != 0">
    <xsl:value-of select="concat('1|', StationName, '|')"/>

    <!-- Add the instrument height -->
    <xsl:variable name="instHt">
      <xsl:choose>
        <xsl:when test="TheodoliteHeight != ''">
          <xsl:value-of select="format-number(TheodoliteHeight * $DistConvFactor, $DecPl3, 'Standard')"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="'0.000'"/>  <!-- Default to 0.000 if null just in case -->
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:value-of select="concat($instHt, '|')"/>

    <!-- Get the code for the station point from the Reductions section if possible -->
    <xsl:variable name="stnCode">
      <xsl:for-each select="key('reducedPtName-search', StationName)">
        <xsl:value-of select="Code"/>
      </xsl:for-each>
    </xsl:variable>


    <xsl:if test="$stnCode != ''">   <!-- There is a code -->
      <xsl:value-of select="concat($stnCode, '|')"/>
    </xsl:if>

    <xsl:call-template name="NewLine"/>

    <xsl:for-each select="following-sibling::PointRecord[StationID = $stnID]">
      <xsl:call-template name="Observation"/>
    </xsl:for-each>
  </xsl:if>
</xsl:template>


<!-- **************************************************************** -->
<!-- **************** Observation Details Output ******************** -->
<!-- **************************************************************** -->
<xsl:template name="Observation">

  <!-- Get the orientation correction from the referenced backsight record -->
  <xsl:variable name="orientation">
    <xsl:variable name="temp">
      <xsl:for-each select="key('BSPt-search', BackBearingID)">
        <xsl:value-of select="OrientationCorrection"/>
      </xsl:for-each>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="string(number($temp)) != 'NaN'">
        <xsl:value-of select="$temp"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="0"/>  <!-- If no orientation correction value found set to 0 -->
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="azimuth">
    <xsl:call-template name="FormatAngle">
      <xsl:with-param name="theAngle" select="Circle/HorizontalCircle + $orientation"/>
      <xsl:with-param name="useSymbols">false</xsl:with-param>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="tgtHt">
    <xsl:for-each select="key('tgtID-search', TargetID)[1]">
      <xsl:value-of select="TargetHeight"/>
    </xsl:for-each>
  </xsl:variable>

  <xsl:variable name="vtObs">
    <xsl:call-template name="FormatAngle">
      <xsl:with-param name="theAngle" select="Circle/VerticalCircle"/>
      <xsl:with-param name="useSymbols">false</xsl:with-param>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="corrDist">
    <xsl:call-template name="CorrectedDist">
      <xsl:with-param name="dist" select="Circle/EDMDistance"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="concat('2|', Name, '|', $azimuth, '|', $vtObs, '|',
                               format-number($corrDist * $DistConvFactor, $DecPl3, 'Standard'), '|',
                               format-number($tgtHt * $DistConvFactor, $DecPl3, 'Standard'), '|')"/>

  <xsl:if test="Code != ''">  <!-- There is a code -->
    <xsl:value-of select="concat(Code, '|')"/>
  </xsl:if>

  <xsl:call-template name="NewLine"/>

</xsl:template>


<!-- **************************************************************** -->
<!-- ***************** Apply Corrections To Distance **************** -->
<!-- **************************************************************** -->
<xsl:template name="CorrectedDist">
  <xsl:param name="dist"/>
  <!-- There is no record available for outputting the prism constant or atmospheric -->
  <!-- ppm in the Pregeo format file so the implication is that this format must     -->
  <!-- contain distances with the prism constant and atmospheric correction already  -->
  <!-- applied.  All the distances in the JobXML file are raw distances so apply the -->
  <!-- current prism constant and atmospheric correction to the distance.            -->

  <xsl:variable name="currPrismConst">
    <xsl:variable name="prismConst">
      <xsl:for-each select="key('tgtID-search', TargetID)[1]">
        <xsl:value-of select="PrismConstant"/>
      </xsl:for-each>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="string(number($prismConst)) = 'NaN'">
        <xsl:value-of select="0"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$prismConst"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="atmosPPM">
    <xsl:variable name="ppm">
      <xsl:for-each select="key('stnID-search', StationID)">
        <xsl:for-each select="key('atmosID-search', AtmosphereID)">
          <xsl:value-of select="PPM"/>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="string(number($ppm)) = 'NaN'">
        <xsl:value-of select="0"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$ppm"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Apply the distance corrections -->
  <xsl:value-of select="$dist + $currPrismConst + ($atmosPPM div 1000000.0 * $dist)"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************ Return the Abbreviated Tipo String **************** -->
<!-- **************************************************************** -->
<xsl:template name="GetTipoOutputStr">
  <xsl:param name="inStr"/>
  
  <xsl:choose>
    <xsl:when test="contains($inStr, '(FR)')">
      <xsl:value-of select="'FR'"/>
    </xsl:when>
    <xsl:when test="contains($inStr, '(MC)')">
      <xsl:value-of select="'MC'"/>
    </xsl:when>
    <xsl:when test="contains($inStr, '(MA)')">
      <xsl:value-of select="'MA'"/>
    </xsl:when>
    <xsl:when test="contains($inStr, '(26)')">
      <xsl:value-of select="'26'"/>
    </xsl:when>
    <xsl:when test="contains($inStr, '(PA)')">
      <xsl:value-of select="'PA'"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="'FR'"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ********************** New Line Output ************************* -->
<!-- **************************************************************** -->
<xsl:template name="NewLine">
<xsl:text>&#10;</xsl:text>
</xsl:template>


<!-- **************************************************************** -->
<!-- ****************** Return the ECEF X value ********************* -->
<!-- **************************************************************** -->
<xsl:template name="ecefX">
  <xsl:param name="latitude"/>
  <xsl:param name="longitude"/>
  <xsl:param name="height"/>

  <!-- Get the latitude in radians -->
  <xsl:variable name="radLat">
    <xsl:call-template name="AngleInRadians">
      <xsl:with-param name="theAngle" select="$latitude"/>
    </xsl:call-template>
  </xsl:variable>

  <!-- Get the longitude in radians -->
  <xsl:variable name="radLong">
    <xsl:call-template name="AngleInRadians">
      <xsl:with-param name="theAngle" select="$longitude"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="N">
    <xsl:call-template name="RadiusOfCurvature">
      <xsl:with-param name="latitude" select="$radLat"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="cosLat">
    <!-- Cosine of latitude = sin(Pi / 2 - latitude) -->
    <xsl:call-template name="Sine">
      <xsl:with-param name="theAngle" select="$Pi div 2.0 - $radLat"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="cosLong">
    <!-- Cosine of longitude = sin(Pi / 2 - longitude) -->
    <xsl:call-template name="Sine">
      <xsl:with-param name="theAngle" select="$Pi div 2.0 - $radLong"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="($N + $height) * $cosLat * $cosLong"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ****************** Return the ECEF Y value ********************* -->
<!-- **************************************************************** -->
<xsl:template name="ecefY">
  <xsl:param name="latitude"/>
  <xsl:param name="longitude"/>
  <xsl:param name="height"/>

  <!-- Get the latitude in radians -->
  <xsl:variable name="radLat">
    <xsl:call-template name="AngleInRadians">
      <xsl:with-param name="theAngle" select="$latitude"/>
    </xsl:call-template>
  </xsl:variable>

  <!-- Get the longitude in radians -->
  <xsl:variable name="radLong">
    <xsl:call-template name="AngleInRadians">
      <xsl:with-param name="theAngle" select="$longitude"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="N">
    <xsl:call-template name="RadiusOfCurvature">
      <xsl:with-param name="latitude" select="$radLat"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="cosLat">
    <!-- Cosine of latitude = sin(Pi / 2 - latitude) -->
    <xsl:call-template name="Sine">
      <xsl:with-param name="theAngle" select="$Pi div 2.0 - $radLat"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="sinLong">
    <xsl:call-template name="Sine">
      <xsl:with-param name="theAngle" select="$radLong"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="($N + $height) * $cosLat * $sinLong"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ****************** Return the ECEF Z value ********************* -->
<!-- **************************************************************** -->
<xsl:template name="ecefZ">
  <xsl:param name="latitude"/>
  <xsl:param name="height"/>

  <!-- Get the latitude in radians -->
  <xsl:variable name="radLat">
    <xsl:call-template name="AngleInRadians">
      <xsl:with-param name="theAngle" select="$latitude"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="N">
    <xsl:call-template name="RadiusOfCurvature">
      <xsl:with-param name="latitude" select="$radLat"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="sinLat">
    <xsl:call-template name="Sine">
      <xsl:with-param name="theAngle" select="$radLat"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="($N * (1.0 - $WGS84EccentricitySquared) + $height) * $sinLat"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- **** Compute the dot product for the supplied point and line *** -->
<!-- **************************************************************** -->
<xsl:template name="CrossProduct">
  <xsl:param name="pointX"/>
  <xsl:param name="pointY"/>
  <xsl:param name="startX"/>
  <xsl:param name="startY"/>
  <xsl:param name="endX"/>
  <xsl:param name="endY"/>

  <!-- Use the cross product to determine if the point is left of, right of or on    -->
  <!-- the line:                                                                     -->
  <!-- Less than 0 indicates a point on the left (of line start to end)              -->
  <!-- Greater than 0 indicates a point on the right (of line start to end)          -->
  <!-- Equal to 0 indicates a point on the line                                      -->

  <xsl:value-of select="($endY - $startY) * ($pointX - $startX) - ($endX - $startX) * ($pointY - $startY)"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ****************** Compute Inverse Distance ******************** -->
<!-- **************************************************************** -->
<xsl:template name="InverseDistance">
  <xsl:param name="deltaN"/>
  <xsl:param name="deltaE"/>

  <!-- Compute the inverse distance from the deltas -->
  <xsl:choose>  <!-- If delta values are both effectively 0 return 0 -->
    <xsl:when test="((concat(substring('-',2 - ($deltaN &lt; 0)), '1') * $deltaN) &lt; 0.000001) and
                    ((concat(substring('-',2 - ($deltaE &lt; 0)), '1') * $deltaE) &lt; 0.000001)">0</xsl:when>
    <xsl:otherwise>
      <!-- Return hypotenuse distance -->
      <xsl:call-template name="Sqrt">
        <xsl:with-param name="num" select="$deltaN * $deltaN + $deltaE * $deltaE"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************ Output Angle in Appropriate Format **************** -->
<!-- **************************************************************** -->
<xsl:template name="FormatAngle">
  <xsl:param name="theAngle"/>
  <xsl:param name="secDecPlaces" select="0"/>
  <xsl:param name="DMSOutput" select="'false'"/>  <!-- Can be used to force DMS output -->
  <xsl:param name="useSymbols" select="'true'"/>
  <xsl:param name="impliedDecimalPt" select="'false'"/>
  <xsl:param name="gonsDecPlaces" select="5"/>    <!-- Decimal places for gons output -->
  <xsl:param name="decDegDecPlaces" select="5"/>  <!-- Decimal places for decimal degrees output -->

  <xsl:variable name="gonsDecPl">
    <xsl:choose>
      <xsl:when test="$gonsDecPlaces = 1"><xsl:value-of select="$DecPl1"/></xsl:when>
      <xsl:when test="$gonsDecPlaces = 2"><xsl:value-of select="$DecPl2"/></xsl:when>
      <xsl:when test="$gonsDecPlaces = 3"><xsl:value-of select="$DecPl3"/></xsl:when>
      <xsl:when test="$gonsDecPlaces = 4"><xsl:value-of select="$DecPl4"/></xsl:when>
      <xsl:when test="$gonsDecPlaces = 5"><xsl:value-of select="$DecPl5"/></xsl:when>
      <xsl:when test="$gonsDecPlaces = 6"><xsl:value-of select="$DecPl6"/></xsl:when>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="decDegDecPl">
    <xsl:choose>
      <xsl:when test="$decDegDecPlaces = 1"><xsl:value-of select="$DecPl1"/></xsl:when>
      <xsl:when test="$decDegDecPlaces = 2"><xsl:value-of select="$DecPl2"/></xsl:when>
      <xsl:when test="$decDegDecPlaces = 3"><xsl:value-of select="$DecPl3"/></xsl:when>
      <xsl:when test="$decDegDecPlaces = 4"><xsl:value-of select="$DecPl4"/></xsl:when>
      <xsl:when test="$decDegDecPlaces = 5"><xsl:value-of select="$DecPl5"/></xsl:when>
      <xsl:when test="$decDegDecPlaces = 6"><xsl:value-of select="$DecPl6"/></xsl:when>
    </xsl:choose>
  </xsl:variable>

  <xsl:choose>
    <!-- Null angle value -->
    <xsl:when test="string(number($theAngle))='NaN'">
      <xsl:value-of select="format-number($theAngle, $DecPl3, 'Standard')"/> <!-- Use the defined null format output -->
    </xsl:when>
    <!-- There is an angle value -->
    <xsl:otherwise>
      <xsl:choose>
        <xsl:when test="($AngleUnit = 'DMSDegrees') or not($DMSOutput = 'false')">
          <xsl:call-template name="FormatDMSAngle">
            <xsl:with-param name="decimalAngle" select="$theAngle"/>
            <xsl:with-param name="secDecPlaces" select="$secDecPlaces"/>
            <xsl:with-param name="useSymbols" select="$useSymbols"/>
            <xsl:with-param name="impliedDecimalPt" select="$impliedDecimalPt"/>
          </xsl:call-template>
        </xsl:when>

        <xsl:otherwise>
          <xsl:variable name="fmtAngle">
            <xsl:choose>
              <xsl:when test="($AngleUnit = 'Gons') and ($DMSOutput = 'false')">
                <xsl:choose>
                  <xsl:when test="$secDecPlaces &gt; 0">  <!-- More accurate angle output required -->
                    <xsl:value-of select="format-number($theAngle * $AngleConvFactor, $DecPl8, 'Standard')"/>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:value-of select="format-number($theAngle * $AngleConvFactor, $gonsDecPl, 'Standard')"/>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:when>

              <xsl:when test="($AngleUnit = 'Mils') and ($DMSOutput = 'false')">
                <xsl:choose>
                  <xsl:when test="$secDecPlaces &gt; 0">  <!-- More accurate angle output required -->
                    <xsl:value-of select="format-number($theAngle * $AngleConvFactor, $DecPl6, 'Standard')"/>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:value-of select="format-number($theAngle * $AngleConvFactor, $DecPl4, 'Standard')"/>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:when>

              <xsl:when test="($AngleUnit = 'DecimalDegrees') and ($DMSOutput = 'false')">
                <xsl:choose>
                  <xsl:when test="$secDecPlaces &gt; 0">  <!-- More accurate angle output required -->
                    <xsl:value-of select="format-number($theAngle * $AngleConvFactor, $DecPl8, 'Standard')"/>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:value-of select="format-number($theAngle * $AngleConvFactor, $decDegDecPl, 'Standard')"/>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:when>
            </xsl:choose>
          </xsl:variable>
          
          <xsl:choose>
            <xsl:when test="$impliedDecimalPt != 'true'">
              <xsl:value-of select="$fmtAngle"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="translate($fmtAngle, '.', '')"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ********************** Angle in Radians ************************ -->
<!-- **************************************************************** -->
<xsl:template name="AngleInRadians">
  <xsl:param name="theAngle"/>
  <xsl:param name="normalise" select="'false'"/>
  <xsl:choose>
    <!-- Null angle value -->
    <xsl:when test="string(number($theAngle)) = 'NaN'">
      <xsl:value-of select="''"/>
    </xsl:when>
    <!-- There is an angle value -->
    <xsl:otherwise>
      <xsl:variable name="radiansAngle">
        <xsl:value-of select="$theAngle * $Pi div 180.0"/>
      </xsl:variable>

      <xsl:variable name="outAngle">
        <xsl:choose>
          <xsl:when test="$normalise = 'false'">
            <xsl:value-of select="$radiansAngle"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:call-template name="RadianAngleBetweenLimits">
              <xsl:with-param name="anAngle" select="$radiansAngle"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <xsl:value-of select="$outAngle"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******* Return the Radius of Curvature in Prime Vertical ******* -->
<!-- **************************************************************** -->
<xsl:template name="RadiusOfCurvature">
  <xsl:param name="latitude"/>   <!-- Already converted to radians -->

  <xsl:variable name="sinLat">
    <xsl:call-template name="Sine">
      <xsl:with-param name="theAngle" select="$latitude"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="sinLatSquared">
    <xsl:value-of select="$sinLat * $sinLat"/>
  </xsl:variable>

  <xsl:variable name="tempVal">
    <xsl:call-template name="Sqrt">
      <xsl:with-param name="num" select="1.0 - $WGS84EccentricitySquared * $sinLatSquared"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="$WGS84SemiMajorAxis div $tempVal"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************ Return the sine of an angle in radians ************ -->
<!-- **************************************************************** -->
<xsl:template name="Sine">
  <xsl:param name="theAngle"/>
  <xsl:variable name="normalisedAngle">
    <xsl:call-template name="RadianAngleBetweenLimits">
      <xsl:with-param name="anAngle" select="$theAngle"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="theSine">
    <xsl:call-template name="sineIter">
      <xsl:with-param name="pX2" select="$normalisedAngle * $normalisedAngle"/>
      <xsl:with-param name="pRslt" select="$normalisedAngle"/>
      <xsl:with-param name="pElem" select="$normalisedAngle"/>
      <xsl:with-param name="pN" select="1"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="number($theSine)"/>
</xsl:template>

<xsl:template name="sineIter">
  <xsl:param name="pX2"/>
  <xsl:param name="pRslt"/>
  <xsl:param name="pElem"/>
  <xsl:param name="pN"/>
  <xsl:param name="pEps" select="0.00000001"/>
  <xsl:variable name="vnextN" select="$pN+2"/>
  <xsl:variable name="vnewElem"  select="-$pElem*$pX2 div ($vnextN*($vnextN - 1))"/>
  <xsl:variable name="vnewResult" select="$pRslt + $vnewElem"/>
  <xsl:variable name="vdiffResult" select="$vnewResult - $pRslt"/>
  <xsl:choose>
    <xsl:when test="$vdiffResult > $pEps or $vdiffResult &lt; -$pEps">
      <xsl:call-template name="sineIter">
        <xsl:with-param name="pX2" select="$pX2"/>
        <xsl:with-param name="pRslt" select="$vnewResult"/>
        <xsl:with-param name="pElem" select="$vnewElem"/>
        <xsl:with-param name="pN" select="$vnextN"/>
        <xsl:with-param name="pEps" select="$pEps"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$vnewResult"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- *************** Return the square root of a value ************** -->
<!-- **************************************************************** -->
<xsl:template name="Sqrt">
  <xsl:param name="num" select="0"/>       <!-- The number you want to find the square root of -->
  <xsl:param name="try" select="1"/>       <!-- The current 'try'.  This is used internally. -->
  <xsl:param name="iter" select="1"/>      <!-- The current iteration, checked against maxiter to limit loop count - used internally -->
  <xsl:param name="maxiter" select="40"/>  <!-- Set this up to insure against infinite loops - used internally -->

  <!-- This template uses Sir Isaac Newton's method of finding roots -->

  <xsl:choose>
    <xsl:when test="$try * $try = $num or $iter &gt; $maxiter">
      <xsl:value-of select="$try"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="Sqrt">
        <xsl:with-param name="num" select="$num"/>
        <xsl:with-param name="try" select="$try - (($try * $try - $num) div (2 * $try))"/>
        <xsl:with-param name="iter" select="$iter + 1"/>
        <xsl:with-param name="maxiter" select="$maxiter"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ********************** Format a DMS Angle ********************** -->
<!-- **************************************************************** -->
<xsl:template name="FormatDMSAngle">
  <xsl:param name="decimalAngle"/>
  <xsl:param name="secDecPlaces" select="0"/>
  <xsl:param name="useSymbols" select="'true'"/>
  <xsl:param name="impliedDecimalPt" select="'false'"/>

  <xsl:variable name="degreesSymbol">
    <xsl:choose>
      <xsl:when test="$useSymbols = 'true'">&#0176;</xsl:when>  <!-- Degrees symbol ° -->
      <xsl:otherwise>
        <xsl:if test="$impliedDecimalPt != 'true'">.</xsl:if>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="minutesSymbol">
    <xsl:choose>
      <xsl:when test="$useSymbols = 'true'">'</xsl:when>
      <xsl:otherwise></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="secondsSymbol">
    <xsl:choose>
      <xsl:when test="$useSymbols = 'true'">&quot;</xsl:when>
      <xsl:otherwise></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="sign">
    <xsl:if test="$decimalAngle &lt; '0.0'">-1</xsl:if>
    <xsl:if test="$decimalAngle &gt;= '0.0'">1</xsl:if>
  </xsl:variable>

  <xsl:variable name="posDecimalDegrees" select="number($decimalAngle * $sign)"/>

  <xsl:variable name="positiveDecimalDegrees">  <!-- Ensure an angle very close to 360° is treated as 0° -->
    <xsl:choose>
      <xsl:when test="(360.0 - $posDecimalDegrees) &lt; 0.00001">
        <xsl:value-of select="0"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$posDecimalDegrees"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="decPlFmt">
    <xsl:choose>
      <xsl:when test="$secDecPlaces = 0"><xsl:value-of select="''"/></xsl:when>
      <xsl:when test="$secDecPlaces = 1"><xsl:value-of select="'.0'"/></xsl:when>
      <xsl:when test="$secDecPlaces = 2"><xsl:value-of select="'.00'"/></xsl:when>
      <xsl:when test="$secDecPlaces = 3"><xsl:value-of select="'.000'"/></xsl:when>
      <xsl:when test="$secDecPlaces = 4"><xsl:value-of select="'.0000'"/></xsl:when>
      <xsl:when test="$secDecPlaces = 5"><xsl:value-of select="'.00000'"/></xsl:when>
      <xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="degrees" select="floor($positiveDecimalDegrees)"/>
  <xsl:variable name="decimalMinutes" select="number(number($positiveDecimalDegrees - $degrees) * 60 )"/>
  <xsl:variable name="minutes" select="floor($decimalMinutes)"/>
  <xsl:variable name="seconds" select="number(number($decimalMinutes - $minutes)*60)"/>

  <xsl:variable name="partiallyNormalisedMinutes">
    <xsl:if test="number(format-number($seconds, concat('00', $decPlFmt))) = 60"><xsl:value-of select="number($minutes + 1)"/></xsl:if>
    <xsl:if test="not(number(format-number($seconds, concat('00', $decPlFmt))) = 60)"><xsl:value-of select="$minutes"/></xsl:if>
  </xsl:variable>

  <xsl:variable name="normalisedSeconds">
    <xsl:if test="number(format-number($seconds, concat('00', $decPlFmt))) = 60"><xsl:value-of select="0"/></xsl:if>
    <xsl:if test="not(number(format-number($seconds, concat('00', $decPlFmt))) = 60)"><xsl:value-of select="$seconds"/></xsl:if>
  </xsl:variable>

  <xsl:variable name="partiallyNormalisedDegrees">
    <xsl:if test="format-number($partiallyNormalisedMinutes, '0') = '60'"><xsl:value-of select="number($degrees + 1)"/></xsl:if>
    <xsl:if test="not(format-number($partiallyNormalisedMinutes, '0') = '60')"><xsl:value-of select="$degrees"/></xsl:if>
  </xsl:variable>

  <xsl:variable name="normalisedDegrees">
    <xsl:if test="format-number($partiallyNormalisedDegrees, '0') = '360'"><xsl:value-of select="0"/></xsl:if>
    <xsl:if test="not(format-number($partiallyNormalisedDegrees, '0') = '360')"><xsl:value-of select="$partiallyNormalisedDegrees"/></xsl:if>
  </xsl:variable>

  <xsl:variable name="normalisedMinutes">
    <xsl:if test="format-number($partiallyNormalisedMinutes, '00') = '60'"><xsl:value-of select="0"/></xsl:if>
    <xsl:if test="not(format-number($partiallyNormalisedMinutes, '00') = '60')"><xsl:value-of select="$partiallyNormalisedMinutes"/></xsl:if>
  </xsl:variable>

  <xsl:if test="$sign = -1">-</xsl:if>
  <xsl:value-of select="format-number($normalisedDegrees, '0')"/>
  <xsl:value-of select="$degreesSymbol"/>
  <xsl:value-of select="format-number($normalisedMinutes, '00')"/>
  <xsl:value-of select="$minutesSymbol"/>
  <xsl:choose>
    <xsl:when test="$useSymbols = 'true'">
      <xsl:value-of select="format-number($normalisedSeconds, concat('00', $decPlFmt))"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="translate(format-number($normalisedSeconds, concat('00', $decPlFmt)), '.', '')"/>
    </xsl:otherwise>
  </xsl:choose>
  <xsl:value-of select="$secondsSymbol"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ********* Return radians angle between Specified Limits ******** -->
<!-- **************************************************************** -->
<xsl:template name="RadianAngleBetweenLimits">
  <xsl:param name="anAngle"/>
  <xsl:param name="minVal" select="0.0"/>
  <xsl:param name="maxVal" select="$Pi * 2.0"/>
  <xsl:param name="incVal" select="$Pi * 2.0"/>

  <xsl:variable name="angle1">
    <xsl:call-template name="AngleValueLessThanMax">
      <xsl:with-param name="inAngle" select="$anAngle"/>
      <xsl:with-param name="maxVal" select="$maxVal"/>
      <xsl:with-param name="incVal" select="$incVal"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="angle2">
    <xsl:call-template name="AngleValueGreaterThanMin">
      <xsl:with-param name="inAngle" select="$angle1"/>
      <xsl:with-param name="minVal" select="$minVal"/>
      <xsl:with-param name="incVal" select="$incVal"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="$angle2"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******* Return radians angle less than Specificed Maximum ****** -->
<!-- **************************************************************** -->
<xsl:template name="AngleValueLessThanMax">
  <xsl:param name="inAngle"/>
  <xsl:param name="maxVal"/>
  <xsl:param name="incVal"/>

  <xsl:choose>
    <xsl:when test="$inAngle &gt; $maxVal">
      <xsl:variable name="newAngle">
        <xsl:value-of select="$inAngle - $incVal"/>
      </xsl:variable>
      <xsl:call-template name="AngleValueLessThanMax">
        <xsl:with-param name="inAngle" select="$newAngle"/>
      </xsl:call-template>
    </xsl:when>

    <xsl:otherwise>
      <xsl:value-of select="$inAngle"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************* Return radians angle greater than Zero *********** -->
<!-- **************************************************************** -->
<xsl:template name="AngleValueGreaterThanMin">
  <xsl:param name="inAngle"/>
  <xsl:param name="minVal"/>
  <xsl:param name="incVal"/>

  <xsl:choose>
    <xsl:when test="$inAngle &lt; $minVal">
      <xsl:variable name="newAngle">
        <xsl:value-of select="$inAngle + $incVal"/>
      </xsl:variable>
      <xsl:call-template name="AngleValueGreaterThanMin">
        <xsl:with-param name="inAngle" select="$newAngle"/>
      </xsl:call-template>
    </xsl:when>

    <xsl:otherwise>
      <xsl:value-of select="$inAngle"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


</xsl:stylesheet>

