将日期时间转换为Epoch时间戳及其反向转换(XSLT)

4

我一直在尝试将给定的日期时间转换为纪元时间,以及将给定的纪元时间转换为日期时间。我对xslt还很陌生,已经苦苦挣扎了一段时间,但是它没有返回任何结果。以下是我的xslt代码:

    <xsl:stylesheet version="1.0"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:ns0="http://www.NoPreAuth.org"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                exclude-result-prefixes="xsi xsl ns0 xsd">
<xsl:template match="/">
<xsl:variable name="date1">
        <xsl:value-of select="/ns0:NoAuthInput/ns0:StartDate"/>
</xsl:variable>
<xsl:variable name="date2">
        <xsl:value-of select="/ns0:NoAuthInput/ns0:EndDate"/>
</xsl:variable>
<ns0:NoPreAuthInput>
<ns0:Product>
        <xsl:value-of select="/ns0:NoAuthInput/ns0:Product"/>
</ns0:Product>
<!-- datTime to epoch -->
<ns0:END_T> 
  <xsl:value-of select= "(('$date1')  - xsd:dateTime('1970-01-01T00:00:00') )  div  xsd:dayTimeDuration('PT1S') "/>
</ns0:END_T>
<!-- epoch To datTime -->
<ns0:Closed_T> 
  <xsl:value-of select= "(('$date2')  + xsd:dateTime('1970-01-01T00:00:00') )  *  xsd:dayTimeDuration('PT1S') "/>
</ns0:Closed_T>
</ns0:NoPreAuthInput>
</xsl:template>
</xsl:stylesheet>

我正在尝试转换的XML内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<NoAuthInput xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.NoAuth.org 

 xmlns="http://www.NoAuth.org">
   <Product>ABC</Product>
   <StartDate>2015-10-05T15:52:40.782</StartDate>
   <EndDate>1444150760</EndDate>
</NoAuthInput> 

非常感谢您能提供任何关于此的帮助。谢谢。


你需要使用像Saxon 9、XmlPrime或AltovaXML这样的XSLT 2.0处理器来支持dateTime数据类型以及持续时间和计算。你正在使用XSLT 2.0处理器吗?而且XSLT片段没有声明xsd前缀,所以我认为你的代码不会编译。要将输入转换为dateTime,请使用<xsl:variable name="date1" select="xsd:dateTime(/ns0:NoAuthInput/ns0:StartDate)"/>,然后您可以使用$date进行计算。 - Martin Honnen
谢谢Martin,实际上模式位置是项目目录中的一些本地文件,是的,我正在使用xslt 2.0。 我按照建议修改了代码,但它说“错误:算术运算符未为类型(xs:double,xs:dateTime)的参数定义”。你能否对此提出更多建议? - Novice
2个回答

8

Unix时间戳转换为ISO 8601日期时间:

<xsl:value-of select="xs:dateTime('1970-01-01T00:00:00') + xs:dayTimeDuration(concat('PT', UnixTime, 'S'))"/>

ISO 8601日期时间转换为Unix时间;

<xsl:value-of select="floor((xs:dateTime(ISODateTime) - xs:dateTime('1970-01-01T00:00:00')) div xs:dayTimeDuration('PT1S')) "/>

需要使用XSLT 2.0版本。

示例演示:http://xsltransform.net/94rmq5L


1
如果您正在尝试在MSXML上使用XSLT 1.0实现此操作(我知道原始提问者不是):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:ms="urn:schemas-microsoft-com:xslt" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:userCSharp="http://stackoverflow.com/xsltexample">
  <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />
  <xsl:template match="/">
    <xsl:value-of select="userCSharp:DateToEpoch('1970-01-02')" />
  </xsl:template>
  <msxsl:script language="CSharp" implements-prefix="userCSharp"><![CDATA[
     public string DateToEpoch(string s)
     {
         DateTime dt = DateTime.Parse(s);  
         DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

         return (dt - epoch).TotalSeconds.ToString();
     }
   ]]></msxsl:script>
</xsl:stylesheet>

'1970-01-02'替换为任何你想要的文本节点,只要这个节点是一个有效的日期时间就可以工作。如果不是,很容易编写另一个简单的方法使用DateTime.Parse/TryParse来实现。此模板(针对任何有效的XML)的输出将为86400。请注意,在CDATA节点中定义方法最好,以避免需要转义引号或尖括号(此代码没有使用任何引号或尖括号,但可能会因某种原因而扩展)。


虽然我要的是XSLT 2.0,但还是感谢你的努力! - Novice
很酷的例子,真的需要这个 :) - Frank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接