User501
User501

Reputation: 347

Need to get the day before date from the Input xml

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

Answers (1)

Martin Honnen
Martin Honnen

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

Related Questions