Reputation: 347
Need to get the day before date for certain attribute value and replace with mentioned date from the input xml
Input XML I'm having, the <Date>
need to change the before day when Cost:Date:date4
<section>
<Plans>
<Date>5/1/2021</Date>
</Plans>
<p>date: <keyword keyref="Cost:Date:date4"/></p>
</section>
XSL I have tried for the above xml:
<xsl:template match="keyword[contains(@keyref, 'Cost:Date:date4')]">
<xsl:param name="section" as="element()" tunnel="yes">
<empty/>
</xsl:param>
<keyword keyref="Cost:Date:date4">
<xsl:call-template name="format_variable">
<xsl:with-param name="cur_keyref" select="@keyref"/>
<xsl:with-param name="cur_value"
select="$section//Plans/Date"/>
<xsl:with-param name="cur_format" select="'date4'"/>
</xsl:call-template>
</keyword>
</xsl:template>
<xsl:template name="format_variable">
<xsl:param name="cur_keyref" as="xs:string">MISSING</xsl:param>
<xsl:param name="cur_value" as="xs:string">MISSING</xsl:param>
<xsl:param name="cur_format" as="xs:string">MISSING</xsl:param>
<xsl:choose>
<xsl:when test="$cur_format = 'date4'">
<xsl:variable name="date_pieces" select="tokenize($cur_value, '/')"/>
<xsl:variable name="month" select="$date_pieces[1]"/>
<xsl:variable name="day" select="$date_pieces[2]"/>
<xsl:variable name="year" select="$date_pieces[3]"/>
<xsl:choose>
<xsl:when test="$month = '1'">
<xsl:text>January</xsl:text>
</xsl:when>
<xsl:when test="$month = '2'">
<xsl:text>February</xsl:text>
</xsl:when>
<xsl:when test="$month = '3'">
<xsl:text>March</xsl:text>
</xsl:when>
<xsl:when test="$month = '4'">
<xsl:text>April</xsl:text>
</xsl:when>
<xsl:when test="$month = '5'">
<xsl:text>May</xsl:text>
</xsl:when>
<xsl:when test="$month = '6'">
<xsl:text>June</xsl:text>
</xsl:when>
<xsl:when test="$month = '7'">
<xsl:text>July</xsl:text>
</xsl:when>
<xsl:when test="$month = '8'">
<xsl:text>August</xsl:text>
</xsl:when>
<xsl:when test="$month = '9'">
<xsl:text>September</xsl:text>
</xsl:when>
<xsl:when test="$month = '10'">
<xsl:text>October</xsl:text>
</xsl:when>
<xsl:when test="$month = '11'">
<xsl:text>November</xsl:text>
</xsl:when>
<xsl:when test="$month = '12'">
<xsl:text>December</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:variable name="day_before" select="concat(' ', $day, ', ', $year)"/>
<xsl:value-of select="xs:dayTimeDuration($day_before) - xs:dayTimeDuration('P1D')"/>
</xsl:when>
</xsl:choose>
</xsl:template>
Before that I have used <xsl:value-of select="$day_before - xs:dayTimeDuration('P1D')"/>
, but I'm getting the arthmetic error for xslt 2.0
Expected Output would be:
Date: April 31, 2021
But when I'm running I'm getting the error Invalid duration value ' 1, 2021' (missing 'P')
. Please help me to resolve this issue. I'm using XLST 2.0
Upvotes: 0
Views: 178
Reputation: 167571
To convert your input format into an XSLT/XPath xs:date
you can use string manipulations and number formatting, then you can substract an xs:dayTimeDuration
and get the new xs:date
:
let $components := tokenize('5/1/2021', '/')!xs:integer(.),
$date := xs:date($components[3] || '-' || format-integer($components[1], '00') || '-' || format-integer($components[2], '00')),
$oneDay := xs:dayTimeDuration('P1D')
return $date - $oneDay
That would give e.g. 2021-04-30
, to format it use format-date
e.g. format-date($date - $oneDay, '[MNn] [D01], [Y0000]')
which gives e.g. April 30, 2021
.
As for the broader context, I think you want e.g.
<xsl:template match="keyword[contains(@keyref, 'Cost:Date:date4')]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:value-of
select="let $components := tokenize(ancestor::section/Plans/Date, '/')!xs:integer(.),
$date := xs:date($components[3] || '-' || format-integer($components[1], '00') || '-' || format-integer($components[2], '00')),
$oneDay := xs:dayTimeDuration('P1D')
return format-date($date - $oneDay, '[MNn] [D01], [Y0000]')"/>
</xsl:copy>
</xsl:template>
Upvotes: 1