2010-10-07 126 views
8

¿Es posible con XSLT para tener un campo de fecha y restar N número de días de ella? Si es así, ¿puedes darme un ejemplo?XSLT - restando días

+0

¿Qué procesador XSLT estás utilizando? –

+0

XSLT 1.0 o XSLT 2.0? ¿Cuál es el formato de fecha? –

+0

Buena pregunta, +1. Vea mi respuesta para una solución completa XSLT 2.0. –

Respuesta

13

Aquí es una demostración de cómo hacer esto en 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="text"/> 

<xsl:template match="/"> 
    <xsl:variable name="vToday" select="current-date()"/> 

    Today is: <xsl:sequence select="$vToday"/> 
    30 days ago it was: <xsl:sequence select= 
    "$vToday -30*xs:dayTimeDuration('P1D')"/> 
    365 days ago it was: <xsl:sequence select= 
    "$vToday -365*xs:dayTimeDuration('P1D')"/> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica esta transformación en cualquier documento XML (no se utiliza), el, resultado correcto querido se produce:

Today is: 2010-10-07-07:00 
    30 days ago it was: 2010-09-07-07:00 
    365 days ago it was: 2009-10-07-07:00 
+0

+1 ¡Buena respuesta! –

+0

FYI ... '' hace que una página en blanco en Firefox y Chrome 25 30. Firefox da un error de la consola de 'Componente devolvió el código de fallo: 0x80600005 [nsIXSLTProcessor.importStylesheet] '. Ooops, aparentemente tienes que especificar 'version =" 2.0 "' en 'xsl: stylesheet'. Estaba usando la versión 1.0. – doubleJ

+0

FYI2 ... Incluso con 'version = 2.0' especificado, Chrome 30 produce una página en blanco. Firefox 25 no muestra resultados, sin embargo. – doubleJ

1

Bueno, XSLT puede dividir cadenas y analizar los números, así que sí, que sería "posible".

Sin embargo, sería mucho más fácil y eficiente si se pudiese utilizar las funciones de extensión y poner en práctica que en otro idioma. Sin embargo, si y cómo funciona eso depende del motor XSLT utilizado.

EXSLT puede tener todo lo que necesita: http://www.exslt.org/date/functions/add/index.html

5

Sí, con XSLT 2.0 es posible, y muy fácil de hacer.

Hay un montón de Date/Time/Duration functions in XPATH 2.0, que son parte de XSLT 2.0.

En este ejemplo se resta 1 día desde la fecha de 2010-01-01 a 2009-12-31 producir:

<?xml version="1.0"?> 
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
<xsl:template match="/"> 
    <xsl:value-of select="xs:date('2010-01-01') - xs:dayTimeDuration('P1D')" /> 
</xsl:template> 
</xsl:stylesheet> 
-2
<xsl:template name="dim" > 

    <xsl:param name="y" /> 
    <xsl:param name="m"/> 

    <xsl:choose> 
    <xsl:when test="($m=1 or $m=3 or $m=5 or $m=7 or $m=8 or $m=10 or $m=12)" > 
      31 
    </xsl:when> 
    <xsl:when test="$m&gt;2"> 
     30 
    </xsl:when> 
    <xsl:when test="($m=2) and (not($y mod 4=0)) or ($y mod 100=0) and (not($y mod 400=0))"> 
     28 
    </xsl:when> 
    <xsl:otherwise> 
     29 
    </xsl:otherwise> 
    </xsl:choose> 

</xsl:template> 


<xsl:template name="minusdays"> 
<xsl:param name="year" /> 
<xsl:param name="month" /> 
<xsl:param name="day"/> 
<xsl:param name="days"/> 
<xsl:variable name="lm" select="number($month)-1+number($month=1)*12"/> 

<xsl:variable name="lmdays"> 
    <xsl:call-template name="dim"> 
     <xsl:with-param name="y" select="$year"/> 
     <xsl:with-param name="m" select="$lm"/> 
    </xsl:call-template> 
</xsl:variable> 

<xsl:choose> 
    <xsl:when test="$days&lt;$day"> 
     <xsl:value-of select="$year"/> 
     <xsl:if test="number($month)&lt;10">0</xsl:if> 
     <xsl:value-of select="$month"/> 
     <xsl:if test="($day - $days)&lt;10">0</xsl:if> 
     <xsl:value-of select="$day - $days"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:call-template name="minusdays"> 
      <xsl:with-param name="year" 
      select="number($year)-number($month=1)"/> 
     <xsl:with-param name="month" select="$lm" /> 
     <xsl:with-param name="day" select="$lmdays"/> 
     <xsl:with-param name="days" select="$days - $day" />  
     </xsl:call-template> 
    </xsl:otherwise> 
</xsl:choose> 

</xsl:template> 
0

I puede ver que todas las soluciones mencionadas son para XSLT 2.0. Tengo solución similar para XSLT 1.0 utilizando EXSLT fecha: añadir

Ejemplo: Considere que el número de días que se restará es de 365 y lo necesitamos como la fecha de inicio predeterminada. En este caso, debemos proporcionar la duración 365 días en formato xs: dayTimeDuration, es decir, '-P365D'.

A continuación el código.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:date="http://exslt.org/dates-and-times" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
extension-element-prefixes="date xs" 
exclude-result-prefixes="date xs" version="1.0"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" /> 

    <xsl:template match="/"> 
     <xsl:variable name="vCurrDate" select="date:date-time()"/> 
     <xsl:variable name="vDefaultStDate" select="(date:add($vCurrDate, '-P365D'))"/> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Desafortunadamente, muy pocos procesadores XSLT 1.0 son compatibles con EXSLT 'date: add()'. Para una solución puramente XSLT 1.0, sin extensiones, consulte: https://stackoverflow.com/questions/23566734/date-operations-on-xsl-1-0/23569278#23569278 –