kuhu jain
kuhu jain

Reputation: 43

XML to Fixed Length File Using XSLT_Complex Position Logic- PART 2

We have a requirement in which need to convert XML into Fixed Length File. First record is as header and after that we have actual records..From 2 record onwards we need to apply the logic which is mentioned below:

  1. After length 45, consider 10 numbers 0000001000, what ever be the last digit we need to check and replace by following the below table.
  2. Same logic we need to repeat at position 59th to 74th.
  3. 77th to 80th we need to get the value 5152 and store into one variable

I had asked the question with 1st logic and got the awesome response, now I am left with 2nd and 3rd logic

 For Positive: (0000001000)   - (000000100{)             
  {= 0                                          
  A = 1                                       
  B = 2                                      
  c = 3                                      
  D = 4                                     
  E = 5                                      
  F = 6                                     
  G = 7                                      
  H = 8                                     
  I = 9 

Request anyone to help me to achieve the same, I have mentioned the XSLT which I got from previous answers.Thanks

Input:

<ZR>
    <INPUT>
        <I_FIL>ERES</I_FIL>
    </INPUT>
    <TABLES>
        <T_ER>
            <item>
                <DATA> HEADER1111111122222222333333344456</DATA>
            </item>
            <item>
                <DATA>778944    D4E2   EA     1234567891 2018-11-060000001000EA 0000000000000100005152D04YA30TRE0000000XXXYYY 800{  Q 2018-11-05</DATA>
            </item>
            <item>
                <DATA>987654    D4E2   EA     1987654321 2018-11-060000002001EA 0000000000000100005152D04YA30UUU0000000XXXLRB 100{  Q 2018-11-05</DATA>
            </item>
                .
                .
                .
                .
                .
                .
                .
                .

            <item>
                <DATA>12345678912345678934562754378909726533297TRAILER</DATA>
            </item>         
        </T_ER>
    </TABLES>
</ZR>

XSLT:

<xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:fn="http://www.w3.org/2005/xpath-functions">
     <xsl:output omit-xml-declaration="yes" />
  <xsl:param name="break" select="'&#xA;'" />
    <xsl:template match="/">
      <xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA" />
      <xsl:value-of select="$break" />
      <xsl:for-each select="ZR/TABLES/T_ER/item[position() != 1]">
        <xsl:variable name="length" select="string-length(substring(DATA,0,46))" />
        <xsl:variable name="tenNumbers" select="substring(DATA, ($length + 1), 
         10)"/>
        <xsl:variable name="charToReplace" select="translate(substring($tenNumbers, string-length($tenNumbers), 1),'0123456789','{ABCDEFGHI')" />

        <xsl:value-of select="concat(substring(DATA,0,46), substring(DATA, ($length + 1), 9), $charToReplace, substring(DATA,($length+11),(string-length(DATA) + 1)))"/>
        <xsl:value-of select="$break" />
      </xsl:for-each>
   </xsl:template>
</xsl:stylesheet>

OR

<xsl:template match="/">
  <xsl:value-of select="
    ZR/TABLES/T_ER/item[1]/DATA,
    ZR/TABLES/T_ER/item[position() &gt; 1]/DATA/concat(
     substring(., 1, 54),
     substring('{ABCDEFGHI', number(substring(., 55, 1)) + 1, 1),
     substring(., 56)
  )" separator="&#xA;" />
</xsl:template>

Expected Output:

   HEADER1111111122222222333333344456
   778944    D4E2   EA     1234567891 2018-11-06000000100{EA 
   000000000000010{005152D04YA30TRE0000000XXXYYY 800{  Q 2018-11-05
   987654    D4E2   EA     1987654321 2018-11-06000000200AEA 
   000000000000010{005152D04YA30UUU0000000XXXLRB 100{  Q 2018-11-05
.
.
.
.
  12345678912345678934562754378909726533297TRAILER

Upvotes: 0

Views: 299

Answers (1)

Vebbie
Vebbie

Reputation: 1695

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'&#xA;'" />
<xsl:template match="/">
    <xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA" />
    <xsl:value-of select="$break" />

    <xsl:for-each select="ZR/TABLES/T_ER/item[position() != 1]">
        <xsl:variable name="length" select="string-length(substring(DATA,0,46))" />

        <xsl:variable name="tenNumbers" select="substring(DATA, ($length + 1), 10)" />
        <xsl:variable name="sixteenNumbers" select="substring(DATA, (string-length(substring(DATA,0,59)) + 1), 16)" />

        <xsl:variable name="firstCharToReplace" select="translate(substring($tenNumbers, string-length($tenNumbers), 1),'0123456789','{ABCDEFGHI')" />
        <xsl:variable name="secondCharToReplace" select="translate(substring($sixteenNumbers, string-length($sixteenNumbers), 1),'0123456789','{ABCDEFGHI')" />

        <xsl:choose>
            <xsl:when test="string-length($tenNumbers) != 10">
                <xsl:value-of select="concat(substring(DATA,0,46), substring(DATA, ($length + 1), 9))" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="concat(substring(DATA,0,46),
                                                  substring(DATA, ($length + 1), 9),
                                                  $firstCharToReplace,
                                                  substring(DATA,($length+11), 18),
                                                  $secondCharToReplace,
                                                  substring(DATA,($length+30),(string-length(DATA) + 1)))" />
            </xsl:otherwise>
        </xsl:choose>
        <xsl:value-of select="$break" />
        <xsl:variable name="temp" select="substring(DATA,77,4)" />
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

It depends on what condition you want to replace the char.

If it is based on after EA (as per comment) the solution would be different.

For now, I have implemented it solely length based with both points 2 & 3 covered.

http://xsltfiddle.liberty-development.net/6r5Gh38/1

EDIT:

http://xsltfiddle.liberty-development.net/6r5Gh38/2

EDIT 2: Brief about the points mentioned in comment:

1. <xsl:when test="string-length($tenNumbers) != 10"> This condition is added to remove that extra R appearing for last <item> . It means if the 10 numbers we are taking in variable is actually having 10 numbers or not.

In the last case,

<item>
     <DATA>12345678912345678934562754378909726533297TRAILER</DATA>
</item>

We don't get 10 numbers after 46th character. We get less than that. That's the reason the output has been separated out for two different cases.

2. substring(DATA,0,46) --> which will take first 45 characters to match 778944 D4E2 EA 1234567891 2018-11-06

substring(DATA, ($length + 1), 9) --> which will take 9 characters from index 46th to match 000000100

$firstCharToReplace --> This will replace 10th character as your requirement of 1st question i.e. {

substring(DATA,($length+11), 18) --> It will start remaining string from index (45+11)th to 18 characters that matches EA 000000000000010

$secondCharToReplace --> This will replace (45+11+18)= 74th character as your requirement of 2nd question i.e. {

substring(DATA,($length+30),(string-length(DATA) + 1)) --> It starts from (45+30)= 75th character to last index and gives 005152D04YA30TRE0000000XXXYYY 800{ Q 2018-11-05

Note: In your case, there are extra tabs and white-spaces exist in between the string. That's why the index number has been changed to match your expected output.

Upvotes: 1

Related Questions