Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member195202
Participant
0 Kudos

XSLT can handle complex and

tricky requirements specially when copying patterns and manipulating hierarchies. I came across a tricky requirement in my project. It was an IDoc to File scenario where source IDoc xml was to be converted into a third party specific format.

Here we have an invoice Idoc (INVOIC.INVOIC02)

which needs to be converted into a specific format. This transformation is required for a correction

invoice Idoc, which means that Idoc would have even number of E1EDP01 segments in it. For n number of original E1EDP01 segments, there will be another n number of

correction E1EDP01 segments.  Source structure of the idoc is as follows:

             IDOC

                              EDI_DC40

                              E1EDKxx segments

                              E1EDP01 segments (Even number, n original, n correction)

                              E1EDSxx segments

Third party requires the

Idoc xml but in a bit different format  as explained below, Let us introduce some notations:

*E1EDKxx_Original*  - These are E1EDKxx

segments which are present in the source idoc.So lets call them the E1EDKxx_Original

segments.

*E1EDKxx_Changed * - This is modified version of

source E1EDKxx segments. One of the   segment in E1EDKxx segment

would be changed.

*Trailer  *    - Copy of

E1EDSxx, this would be used as trailer record

Target structure required

by third party --

            IDOC

                             EDI_DC40           

                             E1EDKxx_Original  (As is original E1EDKxx).

                             E1EDP01 (item number 1, original item)

                             E1EDSxx (Trailer)

                             E1EDKxx_Changed

                             E1EDP01 (item number 1,

correction item)

                             E1EDSxx (Trailer)

                             E1EDKxx_Original  (As is original E1EDKxx)

                             E1EDP01 (item number 2, original item)

                             E1EDSxx (Trailer)

                             E1EDKxx_Changed

                             E1EDP01 (item number 2, correction item)

                             E1EDSxx (Trailer)

                            ……………………………..

                            ……………………………..

We have a relation here

between original and correction item (E1EDP01).

Original

E1EDP01-POSEX = Correction E1EDP01-HIPOS.

Given the above

information, we need to convert the source IDoc xml into target structure as

explained above. Achieving this transformation via Graphical, Java or ABAP mapping

would be quite difficult. So we will be discussing XSLT transformation here.

We would approach the target xml as mentioned below:

      Loop on all E1EDP01

            If ( Current E1EDP01-POSEX = Any of other E1EDP01-HIPOS)

                         write E1EDKxx_Changed;

                         write current E1EDP01;(original item)

                         write trailer;

                         write E1EDKxx_Original;

                         write correction E1EDP01; (Correction Item)

                         write trailer;

            End If.

     Endloop

First we have to copy the

mulitple E1EDKxx segments in a variable. We will do that using an XSLT function

- *starts-with(name(), 'E1EDK') *in

a loop.

        <!--Copying all the E1EDKxx segments from the idoc, these will work as header for original E1EDP01 ><br />        <xsl:variable name="e1edkxx_original"><br />            <xsl:for-each select="//IDOC/*"><br />                <!Copying the E1EDKxx segments as they are >                         <! Copying all the E1EDKxx segments from the idoc with a change E1EDK14-ORGID = 'G2O', these will work as header for corrected E1EDP01 ><br />        <xsl:variable name="e1edkxx_changed"><br />            <xsl:for-each select="//IDOC/*"><br />                <!Copying other E1EDKxx segments as they are ><br />                <xsl:if test="not (starts-with(name(), 'E1EDK14') and QUALF = '015') and (starts-with(name(), 'E1EDK'))"><br />                    <xsl:copy-of select="."/><br />                </xsl:if><br />                <!Changing E1EDK14-ORGID where qualifier = '015' >                <!Copying the E1EDPxx segments as they are ><br />        <xsl:variable name="all_e1edp01"><br />            <xsl:for-each select="//IDOC/*"><br />                <!Copying the E1EDKxx segments as they are ><br />                <xsl:if test="starts-with(name(), 'E1EDP') "><br />                    <xsl:copy-of select="."/><br />                </xsl:if><br />            </xsl:for-each><br />        </xsl:variable></p></div></td></tr></tbody></table><p> </p><p>E1EDSxx segments would be used as trailer. A variable trailer will hold all the E1EDSxx segments.</p><table border="1" width="710" height="100"><tbody><tr style="height: 100px; background-color: #ffffff;" valign="middle"><td style="width: 600px;"><div style="overflow: auto; width: 700px; height: 90px;">        <xsl:variable name="trailer"><br />            <!Trailer Record E1EDSxx><br />            <xsl:for-each select="//IDOC/*"><br />                <!Copying the E1EDSxx segments as they are ><br />                <xsl:if test="starts-with(name(), 'E1EDS') "><br />                    <xsl:copy-of select="."/><br />                </xsl:if><br />            </xsl:for-each><br />            <!    Finishing the trailer part here-->

We now have E1EDKxx_original, E1EDKxx_changed, all_e1edp01 and trailer records ready. Other requirement remains for relating the original E1EDP01 segments and correction E1EDP01 segments. We have been given following condition for relating original  E1EDP01 segments and correction E1EDP01 segments.

HIPOS of correction E1EDP01 segments = POSEX of original E1EDP01 segments

This can be done using two for loops. But we will be using an XSLT *key()* function. The key() function returns a node-set from the document, using

the index specified by an            <!-- Forming the required structure here><br />            <IDOC><br />                <xsl:copy-of select="$controlRecord"/>    <! Control Record ><br />                <xsl:for-each select="$all_e1edp01/*">     <! Manupulating the E1EDPxx segments here ><br />                    <! Checking if the value of Posex in the current E1EDP01 segment is equal to the HIPOS of any of E1EDP01 segment  ><br />                    <! Assumption is that HIPOS is populated only in case of corrected E1EDP01 items and is equal to POSEX of the original E1EDP01 ><br />                    <xsl:if test="POSEX = key('E1EDPXX_HIPOS', POSEX)/HIPOS "><br />                        <xsl:copy-of select="$e1edkxx_changed"/>    <! Copying E1EDKxx Changed  ><br />                        <xsl:copy-of select="."/>                    <! Copying E1EDP01 segment (original)>                    <br />                        <xsl:copy-of select="$trailer"/>                <!Copying E1EDSxx Segment><br />                        <xsl:copy-of select="$e1edkxx_original"/>     <! Copying E1EDKxx Original><br />                        <xsl:copy-of select="key('E1EDPXX_HIPOS', POSEX)"/>    <! Copying E1EDP01 segment for correction>*****************************************************************************************************************************************************************************************<br />Structure as required by Third Party<br /><br />        IDOC<br />            EDI_DC40<br />            E1EDKxx_changed<br />            E1EDP01 (item number 1, original item) <br />            E1EDSxx ( trailer)<br />            E1EDKxx_original <br />            E1EDP01 (item number 1, corrected item) <br />            E1EDSxx ( trailer)<br />            E1EDKxx_changed<br />            E1EDP01 (item number 2, original item)<br />            E1EDSxx ( trailer) <br />            E1EDKxx_original<br />            E1EDP01 (item number 2, corrected item) PSTYV=ZL2N<br />            E1EDSxx ( trailer)<br />            ................................................<br />            ................................................<br /><br />    Original E1EDP01 segments would be related to corrected E1EDP01 segments by E1EDP01-POSEX and E1EDP01-HIPOS.<br />    POSEX of original E1EDP01 = HIPOS of corrected E1EDP01. HIPOS is populated by custom coding in ECC only for correction line items.<br />    This XSLT does the required transformation.<br />>    <!--Defining key for HIPOS, HIPOS of corrected E1EDP01 = POSEX of original E1EDP01 ><br />    <xsl:key name="E1EDPXX_HIPOS" match="E1EDP01" use="HIPOS"/><br />    <xsl:template match="/"><br />                <!Copying the EDI_DC40 segment ><br />        <xsl:variable name="controlRecord" select="//IDOC/EDI_DC40"/><br />        <!Copying all the E1EDKxx segments from the idoc, these will work as header for original E1EDP01 -->

                <!--Copying the E1EDKxx segments as they are ><br />                <xsl:if test="starts-with(name(), 'E1EDK')"><br />                <xsl:copy-of select="."/><br />                </xsl:if><br />            </xsl:for-each><br />        </xsl:variable><br />        <! Copying all the E1EDKxx segments from the idoc with a change E1EDK14-ORGID = 'G2O', these will work as header for corrected E1EDP01 ><br />        <xsl:variable name="e1edkxx_changed"><br />            <xsl:for-each select="//IDOC/*"><br />                <!Copying other E1EDKxx segments as they are ><br />                <xsl:if test="not (starts-with(name(), 'E1EDK14') and QUALF = '015') and (starts-with(name(), 'E1EDK'))"><br />                    <xsl:copy-of select="."/><br />                </xsl:if><br />                <!Changing E1EDK14-ORGID where qualifier = '015' ><br />                <xsl:if test="starts-with(name(), 'E1EDK14') and QUALF = '015'"><br />                    <E1EDK14><br />                        <xsl:attribute name="SEGMENT"><xsl:value-of select="1"/></xsl:attribute><br />                        <QUALF>015</QUALF><br />                        <ORGID><br />                            <xsl:value-of select="'G2O'"/><br />                        </ORGID><br />                    </E1EDK14><br />                </xsl:if><br />            </xsl:for-each><br />        </xsl:variable><br />        <xsl:variable name="trailer"><br />            <!Trailer Record E1EDSxx><br />            <xsl:for-each select="//IDOC/*"><br />                <!Copying the E1EDSxx segments as they are ><br />                <xsl:if test="starts-with(name(), 'E1EDS') "><br />                    <xsl:copy-of select="."/><br />                </xsl:if><br />            </xsl:for-each><br />            <!    Finishing the trailer part here><br />        </xsl:variable><br />        <!Copying the E1EDPxx segments as they are ><br />        <xsl:variable name="all_e1edp01"><br />            <xsl:for-each select="//IDOC/*"><br />                <!Copying the E1EDKxx segments as they are ><br />                <xsl:if test="starts-with(name(), 'E1EDP') "><br />                    <xsl:copy-of select="."/><br />                </xsl:if><br />            </xsl:for-each><br />        </xsl:variable><br />        <! Forming the required structure here><br />            <IDOC><br />                <xsl:copy-of select="$controlRecord"/>    <! Control Record ><br />                <xsl:for-each select="$all_e1edp01/*">     <! Manupulating the E1EDPxx segments here ><br />                    <! Checking if the value of Posex in the currentE1EDP01 segment is equal to the HIPOS of any of E1EDP01 segment  ><br />                    <! Assumption is that HIPOS is populated only in case of corrected E1EDP01 items and is equal to POSEX of the original E1EDP01 ><br />                    <xsl:if test="POSEX = key('E1EDPXX_HIPOS', POSEX)/HIPOS "><br />                        <xsl:copy-of select="$e1edkxx_changed"/>    <! Copying E1EDKxx Changed  ><br />                        <xsl:copy-of select="."/>                    <! Copying E1EDP01 segment (original)>                    <br />                        <xsl:copy-of select="$trailer"/>                <!Copying E1EDSxx Segment><br />                        <xsl:copy-of select="$e1edkxx_original"/>     <! Copying E1EDKxx Original><br />                        <xsl:copy-of select="key('E1EDPXX_HIPOS', POSEX)"/>    <! Copying E1EDP01 segment for correction-->