如何将十进制值转换为度、分和秒 (DMS)

How to convert decimal value in Degree, Minute and Second(DMS)

这里我们尝试将十进制值转换为度、分、秒。有什么可以帮助我们的吗?请看下面的例子:

注意:我们这里遵循的规则是:

输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<POSITION>
<LATITUDE>36.812600015S</LATITUDE>
<LONGITUDE>175.430266714E</LONGITUDE>
</POSITION>

预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<POSITION>
<LATITUDE>36&deg; 48' 76''S</LATITUDE>
<LONGITUDE>175&deg; 25' 82''E</LONGITUDE>
</POSITION>

XSLT 代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">

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

<xsl:template match="LATITUDE">
    <LATITUDE>
    <xsl:variable name="LATITUDE" select="."/>
    <xsl:variable name="DEGREE" select="substring-before($LATITUDE,'.')"/>
    <xsl:variable name="MINUTE" select="substring-before(substring-after($LATITUDE,$DEGREE),'S')"/>
    <xsl:value-of select="."/>
    </LATITUDE>
</xsl:template>

<xsl:template match="LONGITUDE">
    <LONGITUDE>
    <xsl:variable name="LONGITUDE" select="."/>
    <xsl:variable name="DEGREE" select="substring-before($LONGITUDE,'.')"/>
    <xsl:variable name="MINUTE" select="substring-before(substring-after($LONGITUDE,$DEGREE),'E')"/>
    <xsl:value-of select="."/>
    </LONGITUDE>
</xsl:template>

</xsl:stylesheet>

参考 Link : https://xsltfiddle.liberty-development.net/nb9PtDy/1

由于您使用的是 XSLT 2.0,因此您可以使用 xsl:analyze-string 来获取片段以使用正则表达式进行处理。

您必须将一些字符串转换为 xs:decimal,但这不会太复杂...

XML 输入(从屏幕截图添加示例)

<POSITION>
    <EXAMPLE>156.742</EXAMPLE>
    <LATITUDE>36.812600015S</LATITUDE>
    <LONGITUDE>175.430266714E</LONGITUDE>
</POSITION>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:so="urn:SO" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:function name="so:convert">
    <xsl:param name="degrees"/>
    <xsl:analyze-string select="normalize-space($degrees)" regex="^(\d+)(\.\d+)([NSEW]?)$">
      <xsl:matching-substring>
        <xsl:variable name="minsec" select="xs:decimal(regex-group(2)) * 60"/>
        <xsl:value-of select="concat(regex-group(1),'&#xB0; ',
          substring-before(string($minsec),'.'),''' ',
          round(xs:decimal(concat('.',substring-after(string($minsec),'.'))) * 60),'&quot;',
          regex-group(3))"/>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
        <xsl:value-of select="$degrees"/>
      </xsl:non-matching-substring>
    </xsl:analyze-string>
  </xsl:function>

  <xsl:template match="LATITUDE|LONGITUDE|EXAMPLE">
    <xsl:copy>
      <xsl:value-of select="so:convert(.)"/>
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

输出

<POSITION>
   <EXAMPLE>156° 44' 31"</EXAMPLE>
   <LATITUDE>36° 48' 45"S</LATITUDE>
   <LONGITUDE>175° 25' 49"E</LONGITUDE>
</POSITION>

已更新 fiddle:https://xsltfiddle.liberty-development.net/nb9PtDy/2

我会采取完全不同的方法:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

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

<xsl:template match="LATITUDE | LONGITUDE">
    <xsl:variable name="dec" select="xs:decimal(replace(., '[NSWE]', ''))" />
    <xsl:variable name="dur" select="$dec * xs:dayTimeDuration('PT1H')" />
    <xsl:copy>
        <!-- degrees -->
        <xsl:value-of select="24 * days-from-duration($dur) + hours-from-duration($dur)"/>
        <xsl:text>° </xsl:text>
        <!-- minutes -->
        <xsl:value-of select="minutes-from-duration($dur)"/>
        <xsl:text>' </xsl:text>
        <!-- seconds -->
        <xsl:value-of select="round(seconds-from-duration($dur))"/>
        <xsl:text>"</xsl:text>
        <!-- hemisphere -->
        <xsl:value-of select="replace(., '[^NSWE]', '')"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>