Fixed FLAT File to XML

Tags: xml file flat
Question!

Need some help on the XSLT 2.0.

Here is the request of a Fixed flat file that I get using unparsed text and a schema file having offset and length information using a document reference file. I am get all the details but when I start to do the grouping I am not able go further...Any help is greatly appreciated to move my stuck mind.

Source Flat File

P01020 230039....
A30438 009090.....
A30439 009039.....
P02390 039438....
D03049 304830...
A30493 304030...
P30439 230300....

Schema File:

    <Schema>
<Purchase recordIdentifer="P">
    <FIELD1 length="5" offset="1" type="xs:string"/>
    <FIELD2 length="6" offset="8" type="xs:string"/>
</Purchase>
<Account recordIdentifer="A">
    <FIELD1 length="5" offset="1" type="xs:string"/>
    <FIELD2 length="6" offset="8" type="xs:string"/>
</Account>
<Deposit recordIdentifer="D">
    <FIELD1 length="5" offset="1" type="xs:string"/>
    <FIELD2 length="6" offset="8" type="xs:string"/>
</Deposit>

XSLT Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:param name="text-url" select="'test2014032901.txt'"/>
     <xsl:param name="file1" select="document('Schema.xml')"/>
    <xsl:output indent="yes"/>
    <xsl:template name="main">
        <xsl:variable name="text" select="unparsed-text($text-url)"/>
        <xsl:variable name="lines" as="element(line)*">
            <xsl:for-each select="tokenize($text,'\r?\n')[normalize-space()]">
                <line>
                    <xsl:value-of select="."/>
                </line>
            </xsl:for-each>
        </xsl:variable>
        <Root>
            <xsl:for-each-group select="$lines" group-starting-with="line[starts-with(., 'P')]">
            <Purchases>
                 <Purchase>
                            <xsl:for-each select="$file1/Schema/Purchase">
                            <xsl:for-each select="./*">
                                <xsl:element name="{name(.)}">
                                    <xsl:value-of select="substring($lines, ./@offset,./@length)"/>
                                </xsl:element>
                            </xsl:for-each>
                        </xsl:for-each>
               </Purchase>
            </Purchases>
            </xsl:for-each-group>
            <xsl:for-each-group select="$lines" group-starting-with="line[starts-with(., 'A')]">
            <Accounts>
                 <Account>
                            <xsl:for-each select="$file1/Schema/Account">
                            <xsl:for-each select="./*">
                                <xsl:element name="{name(.)}">
                                    <xsl:value-of select="substring($lines, ./@offset,./@length)"/>
                                </xsl:element>
                            </xsl:for-each>
                        </xsl:for-each>
               </Account>
            </Accounts>
            </xsl:for-each-group>
            <xsl:for-each-group select="$lines" group-starting-with="line[starts-with(., 'D')]">
            <Deposits>
                 <Deposit>
                            <xsl:for-each select="$file1/Schema/Deposit">
                            <xsl:for-each select="./*">
                                <xsl:element name="{name(.)}">
                                    <xsl:value-of select="substring($lines, ./@offset,./@length)"/>
                                </xsl:element>
                            </xsl:for-each>
                        </xsl:for-each>
               </Deposit>
            </Deposits>
            </xsl:for-each-group>
        </Root>
    </xsl:template>
</xsl:stylesheet>

Output XML is something as below

<Root>
    <Purchases>
        <Purchase>
            <Field1>01020</Field1>
            <Field2>230039</Field2>
        </Purchase>
        <Purchase>
            <Field1>02390</Field1>
            <Field2>039438</Field2>
        </Purchase>
        <Purchase>
            <Field1>30439</Field1>
            <Field2>230300</Field2>
        </Purchase>
    </Purchases>
    <Accounts>
        <Account>
            <Field1>30438</Field1>
            <Field2>009090</Field2>
        </Account>
        <Account>
            <Field1>01020</Field1>
            <Field2>230039</Field2>
        </Account>
        <Account>
            <Field1>01020</Field1>
            <Field2>230039</Field2>
        </Account>
    </Accounts>
    <Deposits>
        <Deposit>
            <Field1>03049</Field1>
            <Field2>304830</Field2>
        </Deposit>
    </Deposits>
</Root>

Any help is greatly appreciated!!!.

Thanks



Answers

I am not sure I understand the use of for-each-group, it seems, at least for the purchases, that

        <Purchases>
            <xsl:for-each select="$lines[starts-with(., 'P')]">
                <Purchase>
                    <xsl:variable name="line" select="."/>
                    <xsl:for-each select="$file1/Schema/Purchase/*">
                        <xsl:element name="{name(.)}">
                            <xsl:value-of select="substring($line, @offset, @length)"/>
                        </xsl:element>
                    </xsl:for-each>
                </Purchase>
            </xsl:for-each>
        </Purchases>

suffices to give

   <Purchases>
      <Purchase>
         <FIELD1>P0102</FIELD1>
         <FIELD2>230039</FIELD2>
      </Purchase>
      <Purchase>
         <FIELD1>P0239</FIELD1>
         <FIELD2>039438</FIELD2>
      </Purchase>
      <Purchase>
         <FIELD1>P3043</FIELD1>
         <FIELD2>230300</FIELD2>
      </Purchase>
   </Purchases>


Isn’t it better to just make it an empty string if you want to set it as null, and null if did not really sent something at all?

By : Debet Wah


This video can help you solving your question :)
By: admin