XSLT date format translation from eg: Aug 23 2018 to 23/08/2018 - xslt-1.0

How to do date format translation from e.g: Aug 23 2018 to 23/08/2018 using XSLT?

XSLT 1.0 does not have any date functions and you will need to use string manipulation functions to convert from one format to another and translate Aug to 08 using some processing logic.
XSLT 2.0 does have format-date() function however the input format expected by this function is YYYY-MM-DD which can then be converted into formats shown in these examples.
You can use the below options for converting the date format
Input XML
<inputDate>Aug 23 2018</inputDate>
XSLT 1.0
<xsl:template match="inputDate">
<xsl:variable name="day" select="substring(., 5, 2)" />
<xsl:variable name="mth" select="substring(., 1, 3)" />
<xsl:variable name="year" select="substring(., 8, 4)" />
<!-- Convert 3 char month name to digit -->
<xsl:variable name="month" select="string-length(substring-before('JanFebMarAprMayJunJulAugSepOctNovDec', $mth)) div 3 + 1" />
<!-- Format the number to 2 digits -->
<xsl:variable name="mthNum" select="format-number($month, '00')" />
<formattedDate>
<xsl:value-of select="concat($day,'/',$mthNum,'/',$year)" />
</formattedDate>
</xsl:template>
XSLT 2.0
Here the solution has used regex to match with the input date format. You can use a different approach as well.
<xsl:template match="inputDate">
<!-- Define array of months -->
<xsl:variable name="months" select="('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')" />
<!-- Define regex to match input date format -->
<xsl:analyze-string regex="^(([A-Za-z]{{3}}) (\d\d) (\d\d\d\d))$" select=".">
<!-- Align the regex groups according to the output format -->
<xsl:matching-substring>
<formattedDate>
<xsl:value-of select="regex-group(3)" />
<xsl:text>/</xsl:text>
<xsl:value-of select="format-number(index-of($months, regex-group(2)), '00')" />
<xsl:text>/</xsl:text>
<xsl:value-of select="regex-group(4)" />
</formattedDate>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:template>
Output from both these templates
<formattedDate>23/08/2018</formattedDate>

Related

Trying to compare two strings in XSLT and outcome is not coming as expected

I'm trying to compare two strings in XSLT and wanted hard coded response as outcome
I have tried keeping an if condition in XSLT but it is providing me two results
<xsl:template name="variableTransformation">
<xsl:param name="text"/>
<xsl:param name="delimiters" select="' /-'"/>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="nextDelimiter" select="substring(translate($text, translate($text, $delimiters, ''), ''), 1, 1)" />
<xsl:variable name="string" select="substring-before(concat($text, ' '), substring(concat($nextDelimiter, ' '), 1, 1))" />
<xsl:value-of select="translate(substring($string, 1, 1), $lower, $upper)"/>
<xsl:value-of select="translate(substring($string, 2), $upper, $lower)"/>
<xsl:if test="$nextDelimiter">
<xsl:value-of select="$nextDelimiter" />
<xsl:call-template name="variableTransformation">
<xsl:with-param name="text" select="substring-after($text, $nextDelimiter)"/>
<xsl:with-param name="delimiters" select="$delimiters"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="$text='SELF EMPLOYED'">
<xsl:value-of select="'Self-Employed'"></xsl:value-of>
</xsl:if>
<xsl:if test="$text='SKILL TRADE'">
<xsl:value-of select="'Skilled Trade'"></xsl:value-of>
</xsl:if>
</xsl:template>
input: 1. GOVERMENT 2. STUDENT 3. HOMEMAKER 4. PROFESSIONAL 5. SELF EMPLOYED 6. SERVICE/RETAIL 7. SKILL TRADE 8. UNEMPLOYED 9. OTHER
Expected:
Government
Student
Homemaker
Professional
Self-Employed
Service/Retail
Skilled Trade
Unemployed
Other
Actual:
Government
Student
Homemaker
Professional
Self EmployedSelf-Employed
Service/Retail
Skill TradeSkilled Trade
Unemployed
Other

How to sum the amounts in a xslt for same ids appearing in XML

I need to produce a text file in the output. I have to first check if a perosn has aby of the following node PreTaxAmt,MatchAmt,RothAmt, then produce a single line in output with required values and then I have to check if the perosn has LoanAmt node, if they have then I have to create another entry for that person. I was able to code till this point but now I am having a requiremnet where if the same person is repated more than once for example below laurel Alex , I need to produce just one entry for single participant id and the PreTaxAmt,MatchAmt,RothAmt amount should be summed up in the first entry in the output and in the in the loan entry row the LoanAmt should be summed up.
Here is my xml.
<Report_Data >
<Report_Entry>
<Participant_ID>03300</Participant_ID>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Mary</Last_Name>
<First_Name>Mehul</First_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>100.8</PreTaxAmt>
<MatchAmt>100.8</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>10600</Participant_ID>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Laurel</Last_Name>
<First_Name>Alex</First_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>61.48</PreTaxAmt>
<MatchAmt>61.47</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>10600</Participant_ID>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Laurel</Last_Name>
<First_Name>Alex</First_Name>
<Middle_Name>S</Middle_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>0</PreTaxAmt>
<MatchAmt>0</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>13100</Participant_ID>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Smita</Last_Name>
<First_Name>Paul</First_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>0</PreTaxAmt>
<MatchAmt>0</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
Here is my xslt :
<xsl:template match="/">
<xsl:for-each select="Report_Data/Report_Entry">
<xsl:if test="(PreTaxAmt) or(MatchAmt) or (RothAmt) ">
<xsl:call-template name="DataRecords"/>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="Report_Data/Report_Entry">
<xsl:if test="LoanAmt">
<xsl:call-template name="LoanDataRecord"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="DataRecords">
<xsl:for-each-group select="." group-by="wd:Participant_ID">
<xsl:variable name="ParticpantLoan" select="current-grouping-key()"/>
!-- Transaction Code -->
<xsl:value-of select="'Contribution'"/>
<!-- Participant Number -->
<xsl:value-of select="Participant_ID,$filler),1,9"/>
<!-- FT/PT Indicator -->
<xsl:value-of select="substring(concat(Workers/FULL_PART_Time_Indicator,$filler),1,1)"/>
<!-- Contribution Amount1 -->
<xsl:value-of select="(sum(current-group()/PreTaxAmt))"/>
<!-- Contribution Amount2 -->
<xsl:value-of select="(sum(current-group()/MatchAmt))"/>
<!-- Contribution Amount3 -->
<xsl:value-of select="(sum(current-group()/RothAmt))"/>
<xsl:value-of select="$linefeed"/>
</xsl:for-each-group>
</xsl:template>
<xsl:template name="LoanDataRecord">
<xsl:for-each-group select="." group-by="Participant_ID">
<xsl:variable name="ParticpantLoan" select="current-grouping-key()"/>
<!-- Transaction Code -->
<xsl:value-of select="substring(concat('LoanData',$filler),1,3)"/>
<!-- Participant Number -->
<xsl:value-of select="substring(concat(Participant_ID,$filler),1,9)"/>
<!-- Loan Amt -->
<xsl:value-of select="(sum(current-group()/LoanAmt))"/>
<xsl:value-of select="$linefeed"/>
</xsl:for-each-group>
</xsl:template>
The output should have six lines.
Also, how can I calculate the total count of the records in my output file. Earlier I was using below code but now since there would be duplicate SSN how should I modify my existing code for counting ..
0 ] or Report_Data/Report_Entry/MatchAmt[number(.) > 0 ] or Report_Data/Report_Entry/RothAmt[number(.) > 0 ])+
count(Report_Data/Report_Entry/LoanAmt[number(.) > 0 ])

how to Add Missing records in a sequence in XSL

<data>
<Ent>
<Fld1>01<Fld1>
<Fld2>ABC<Fld2>
</Ent>
<Ent>
<Fld1>05<Fld1>
<Fld2>ABC<Fld2>
</Ent>
<Ent>
<Fld1>02<Fld1>
<Fld2>ABC<Fld2>
</Ent>
<Ent>
<Fld1>AA<Fld1>
<Fld2>ABCd<Fld2>
</Ent>
</data>
I have to
1)Sort records based on node Fld1 . if the value in Fld1 is String I have Ignore it
2)If I have some Missing numbers in Sorted records I have to Add them
Over All My output should be
01 ABC
02 ABC
03 Empty
04 Empty
05 ABC
Can an one help me how can I Get this done in xslt.
Assuming XSLT 2.0 I would first sort the elements you are interested in and then simply process 1 to xs:integer($sorted[last()]/Fld1):
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output method="text"/>
<xsl:template match="data">
<xsl:variable name="sorted" as="element(Ent)*">
<xsl:perform-sort select="Ent[matches(Fld1, '[0-9]+')]">
<xsl:sort select="xs:integer(Fld1)"/>
</xsl:perform-sort>
</xsl:variable>
<xsl:for-each select="1 to xs:integer($sorted[last()]/Fld1)">
<xsl:value-of select="concat(format-number(., '00'), ' ', ($sorted[xs:integer(Fld1) = current()]/Fld2, 'Empty')[1], '
')"/>
</xsl:for-each>
</xsl:template>
</xsl:transform>
See http://xsltransform.net/6qVRKwR which uses Saxon 9.5 and outputs
01 ABC
02 ABC
03 Empty
04 Empty
05 ABC

How to convert Time Format PT1H55M0.000S or PT12H0M0.000Sto hh:mm:ss in xslt 1.0

Can any body help me How to make this time format into hh:mm:ss in XSLT 1.0 ?
Example 1: PT1H55M0.000S ---> 01:55:00
Example 2 : PT12H0M0 ---> 12:00:00
Given:
<xsl:variable name="input" select="'PT1H55M0.000S'" />
the following:
<output>
<xsl:value-of select="format-number(substring-before(substring-after($input, 'T'), 'H'), '00')"/>
<xsl:value-of select="format-number(substring-before(substring-after($input, 'H'), 'M'), ':00')"/>
<xsl:value-of select="format-number(substring-before(substring-after($input, 'M'), 'S'), ':00')"/>
</output>
will result in:
<output>01:55:00</output>
Note:
This assumes the input contains all of the three characters: H, M and S; otherwise it's much more complicated.

For-each through rows -1 in xslt

I have a question regarding xslt:
basically i have filtered rows:
<xsl:variable name="filteredRows" select="TestRows[(contains(#*[name()='FieldName'],#Title))]" />
And now i want to do for each on them but -1 so if there are 3 rows i want to execute for each only twice ... how to do that?
<xsl:for-each select ="$filteredRows - 1">
<xsl:text> label = </xsl:text>EMPTY
<br />
</xsl:for-each>
Thanks for help ..
Not tested (you didn't provide any sample), but <xsl:for-each select ="$filteredRow[position() < last()]"> could work.