XSLT-2.0 transformation of a custom date

2020-05-09 01:37发布

问题:

How to write a custom date function in xslt when a given date is first of the current month then the date should be first of the current month else any date other than first of the current month then first of the next month. In the given example the date is Mar 4th 2019 and the current month is Mar 2019 the output should return Apr 1st 2019 if the date is Mar 1st 2019 the output should return Mar 1st 2019.

XML:

<ad:Sale_Data xmlns:ad="urn:com.ad.report/saleslead">
<ad:Sale_Tx_Entry>
    <ad:name>prominent sale</ad:name>
    <ad:businessID>209320484</ad:businessID>
    <ad:saleDate>20190304</ad:saleDate>
    <ad:Lead_Organization ad:Descriptor="Chiéf Executive Officér Operating Officér">
        <ad:ID ad:type="AID">sadlksalfkdki23i204urfdfmd9mdscdkhytt</ad:ID>
        <ad:ID ad:type="Business_Model_Sale_Ref_ID">475846759</ad:ID>
    </ad:Lead_Organization>
    <ad:Management_Hierarchy>
        <ad:Lead_Organization_ID>475847049</ad:Lead_Organization_ID>
    </ad:Management_Hierarchy>
    <ad:storemanager ad:Descriptor="J Loews">
        <ad:ID ad:type="AID">sadlksalfkdki23i204urfdfmd9mdscdkhytt</ad:ID>
        <ad:ID ad:type="S_ID">754954</ad:ID>
    </ad:storemanager>
    <ad:plantype ad:description="plan a">
        <ad:ID ad:type="pid">29ejdbsn</ad:ID>
        <ad:ID ad:type="planid">PLAN_A</ad:ID>
    </ad:plantype>
    <ad:plantype ad:description="plan b">
        <ad:ID ad:type="pid">deije23jdie</ad:ID>
        <ad:ID ad:type="planid">PLAN_B</ad:ID>
    </ad:plantype>
    <ad:plantype ad:description="plan c">
        <ad:ID ad:type="pid">e23c70202d</ad:ID>
        <ad:ID ad:type="planid">PLAN_C</ad:ID>
    </ad:plantype>
    <ad:SalePerson>
        <ad:Sale_Ref_ID>3457578</ad:Sale_Ref_ID>
        <ad:Sale_Profile ad:Descriptor="Sale Person1">
            <ad:ID ad:type="AID">sadlksalfkdki23i204fdfmd9mdscdkhytt</ad:ID>
            <ad:ID ad:type="Sale_Tx_ID">475847</ad:ID>
        </ad:Sale_Profile>
        <ad:Business_Model ad:Descriptor="3457578 Sale Person1 - Business Development Leader1">
            <ad:ID ad:type="AID">sadlksalfkdki23i204urfdfmd9mdscdkhytt</ad:ID>
        </ad:Business_Model>
        <ad:SalePerson ad:Descriptor="Business Development Leader1">
            <ad:ID ad:type="AID">sadlksalfkdki23i204urfdfmd9mdscdkhytt</ad:ID>
            <ad:ID ad:type="S_ID">4782</ad:ID>
        </ad:SalePerson>
        <ad:StoreManager ad:Descriptor="J Loews">
            <ad:ID ad:type="AID">sadlksalfkdki23i204urfdfmd9mdscdkhytt</ad:ID>
            <ad:ID ad:type="S_ID">754954</ad:ID>
        </ad:StoreManager>
    </ad:SalePerson>
    <ad:SalePerson>
        <ad:Sale_Ref_ID>3457579</ad:Sale_Ref_ID>
        <ad:Sale_Profile ad:Descriptor="Sale Person2">
            <ad:ID ad:type="AID">sadlksalfkdki23i204urfdfmd9mdscdkhytt</ad:ID>
            <ad:ID ad:type="Sale_Tx_ID">918328</ad:ID>
        </ad:Sale_Profile>
        <ad:Business_Model ad:Descriptor="3457579 Sale Person2 - Business Development Leader2">
            <ad:ID ad:type="AID">sadlksalfkdki23i204urfdfmd9mdscdkhytt</ad:ID>
        </ad:Business_Model>
        <ad:SalePerson ad:Descriptor="Business Development Leader2">
            <ad:ID ad:type="AID">sadlksalfkdki23i204urfdfmd9mdscdkhytt</ad:ID>
            <ad:ID ad:type="S_ID">487548</ad:ID>
        </ad:SalePerson>
        <ad:StoreManager ad:Descriptor="J Loews">
            <ad:ID ad:type="AID">sadlksalfkdki23i204urfdfmd9mdscdkhytt</ad:ID>
            <ad:ID ad:type="S_ID">754954</ad:ID>
        </ad:StoreManager>
    </ad:SalePerson>
</ad:Sale_Tx_Entry>
</ad:Sale_Data>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="xsl" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ad="urn:com.ad.report/saleslead">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="linefeed" select="'&#xA;'"></xsl:variable>
    <xsl:template match="/ad:Sale_Data">
        <xsl:text>"BusinessName"|"BusinessCode"|"SaleDate"|"BusinessStructure"|"BusinessStructureID"|"BusinessStructureManager"|"StoreID"|"SaleProfile"|"BusinessModel"|"SalePerson"|"StoreManager"</xsl:text>
        <xsl:apply-templates select="ad:Sale_Tx_Entry/ad:SalePerson"/>
    </xsl:template>

   <xsl:template match="ad:SalePerson">
        <xsl:value-of select="$linefeed"/>
            <xsl:text>"</xsl:text>
            <xsl:value-of select="ancestor::ad:Sale_Tx_Entry/ad:name"/> 
            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ancestor::ad:Sale_Tx_Entry/ad:businessID"/> 
            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ancestor::ad:Sale_Tx_Entry/ad:saleDate"/> 
            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ancestor::ad:Sale_Tx_Entry/ad:Lead_Organization/@ad:Descriptor"/> 
            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ancestor::ad:Sale_Tx_Entry/ad:Management_Hierarchy/ad:Lead_Organization_ID"/> 
            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ancestor::ad:Sale_Tx_Entry/ad:storemanager/@ad:Descriptor"/>
            <xsl:text>"|"</xsl:text>

            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ancestor::ad:Sale_Tx_Entry/ad:plantype/@ad:description" separator=", "/>
            <xsl:text>"|"</xsl:text>

            <xsl:value-of select="ad:Sale_Ref_ID"/>  
            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ad:Sale_Profile/@ad:Descriptor"/>
            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ad:Business_Model/@ad:Descriptor"/>
            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ad:SalePerson/@ad:Descriptor"/> 
            <xsl:text>"|"</xsl:text>
            <xsl:value-of select="ad:StoreManager/@ad:Descriptor"/> 
            <xsl:text>"</xsl:text>
    </xsl:template>    
</xsl:stylesheet>

回答1:

You can use this function

<xsl:function name="ad:dateNextMonth">
  <xsl:param name="curDateString"/>
  <xsl:variable name="curDate" select="xs:date(concat(substring($curDateString,1,4),'-',substring($curDateString,5,2),'-',substring($curDateString,7,2)))"/>
  <xsl:variable name="newDate" select="if (day-from-date($curDate) = 1) then format-date($curDate,'[MNn] [D1o] [Y]') else format-date($curDate + xs:yearMonthDuration('P1M'),'[MNn] 1st [Y]')" />
  <xsl:value-of select="concat(substring(substring-before($newDate,' '),1,3),' ',substring-after($newDate,' '))" />
</xsl:function>

Applying it like

<xsl:value-of select="ad:dateNextMonth(ancestor::ad:Sale_Tx_Entry/ad:saleDate)" /> 

it should work as expected. The result with your example should be Apr 1st 2019.



回答2:

The date of the 1st day of the following month can be calculated from a given date as:

$date - (day-from-date($date) - 1) * xs:dayTimeDuration('P1D') + xs:yearMonthDuration('P1M')

If you want to make it conditional only for dates that are not the 1st day of their month, then define a variable as:

<xsl:variable name="day" select="day-from-date($date)"/>

and use it as the condition:

if ($day = 1) then $date else $date - ($day - 1) * xs:dayTimeDuration('P1D') + xs:yearMonthDuration('P1M')

Demo: https://xsltfiddle.liberty-development.net/3MvmXir


Coercing the input to a valid date and formatting of the output is left as an exercise for the reader.