Top 5 Things to Learn at SAP TechEd 2011 about SAP NetWeaver Process Integration (PI)

In May 2011, SAP NetWeaver PI 7.3 was made generally available after a successful ramp-up earlier this year. SAP TechEd 2011 is a good time to learn about ramp-up experience, new and enhanced features, and our plans going forward – to shape your plans and gain firsthand experience. We have compiled a comprehensive program covering SAP’s integration technology with 12 hours of hands-on sessions and more than 10 hours of lectures (all being offered at least twice in Las Vegas). You can find the full agenda and schedule on the SAP TechEd websites for Las Vegas, Madrid, and Bangalore.

It’s hard to pick the best sessions as this depends on your role and experience with SAP NetWeaver PI (unless you decide to simply attend all). Still, here’s a list of the top 5 things to learn at SAP TechEd 2011 with respective sessions:

1. Gain firsthand experience with the latest release (our hands-on sessions – you’ll get your own Java-only PI instance running in the TechEd cloud!)

  • SAP NetWeaver PI - Integration Flows Deep Dive (PMC164)
  • SAP Netweaver PI - AEX (Improvements & New Features) (PMC266)
  • Build system centric processes using the combined BPM/PI offering (PMC165)
  • Combining SAP NetWeaver BRM and SAP NetWeaver PI (PMC166)
  • The SAP NetWeaver PI Java API (PMC360)

2. Learn about improvements for operating and maintaining SAP NetWeaver PI

  • Monitoring Enhancements for SAP NetWeaver PI (PMC108)
  • Near Zero Downtime Maintenance for SAP NetWeaver PI (ALM220)

3. Prepare your upgrade to SAP NetWeaver PI 7.3

  • SAP NetWeaver PI 7.3: Overview and Feedback from Ramp-up (PMC203)
  • Moving productive landscapes to PI 7.3 single-stack (PMC300)

4. Get up to date on our road to an integrated stack (and other enhancements)

  • SAP NetWeaver PI Roadmap (PMC202)
  • Deep Dive into what is New in SAP NetWeaver PI (PMC201)
  • BPMN for System Integration (PMC106)
  • Running system centric processes on SAP NetWeaver BPM and SAP NetWeaver PI (PMC204)

5. Learn from SAP NetWeaver PI customers and partners (ASUG sessions in Las Vegas; Madrid still in planning phase)

  • SAP NetWeaver Process Integration 7.1 Performance, Scaling, and Security (TEC115)

Moreover, we’ll be around for pod and networking sessions.

Proxy Configuration for PI 7.3 Java only

The purpose of this document to highlight new changes and steps required to configure proxy communication between SAP PI 7.3 (Java only installation) and backend SAP systems like ECC, CRM etc.

PI7.3 is coming with 2 installation options- Java only installation (AEX) and Dual stack (ABAP + Java) installation. In Java only installation i.e AEX we do not have ABAP stack on PI system hence the configuration changes are required in PI as well as Backend systems to enable proxy communication between systems.

In case of PI7.3 dual stack implementation the proxy configuration will remain same as of PI earlier versions.

Steps to be followed in PI system

1. Go to PI NWA using Http://<Hostname>:port/nwa

2. Go to Configuration->JCo RFC Provider

3. Create 2 RFC JCO providers

  • SAPSLDAPI_<PI SID>
  • LCRSAPRFC_<PI SID>

Create SAPSLDAPI_PEX:

Note the Application Server host and Gateway Service.

Here Application system is used to register the program id SAPSLDAPI_PEX.

Reason: In Dual stack we generally give PI ABAP stack details, however for Java only installation we need any ABAP stack details(in landscape) to register the Program ID. I have used for ECC application system that PI is exchanging data.

Perform the similar steps for LCRSAPRFC_PEX

Steps to be followed in Application system

a)     Create 3 RFC destinations  (SM59)

-       SAPSLDAPI (Application system to SLD connection)

-        LCRSAPRFC (Application system to Exchange profile connection)

-       SAP_PROXY_ESR (Application system to ESR connection)

b)    Configure SLDAPICUST and test connections through TA: SLD Check

c)     Test SPROXY transaction

d)    Configure SXMB_ADM transaction for runtime proxy message exchange 

Create RFC destinations

- Create RFC destination SAPSLDAPI through SM59 of type T (Start External Program Using TCP/IP)

The gateway Host and service are blank as in PI NWA (JCo RFC) we have registered the program ID in same application system gateway.

Note: In dual stack generally we give SAP PI ABAP stack details, same details we used while creating JCo RFC Provider.

-       Create RFC destination LCRSAPRFC through SM59 of type T (Start External Program Using TCP/IP) similar to RFC destination SAPSLDAPI and use program ID as LCRSAPRFC_<PI SID>

Note : In case we have more application system connected to PI using SPROXY than we need to create above  RFC destinations in another application system and will pass Gateway host and Gateway service as provided in JCo RFC provider.

-       Test both RFC destinations.

-       Create RFC destination SAP_PROXY_ESR through SM59 of type G (HTTP Connection to External Serv)

Target Host: PI host name

Port: Http port (50XX00) where X X- System number

Long Details:  with PIAPPL<SID> user authorizations

b)    Configure SLDAPICUST and test connections through TA: SLDCheck

The user should have SAP_SLD_CONFIGURATOR role.

Generally we use  SLD_CL_<SID> user

c)      Test  proxy connection with ESR for transaction: SPROXY

Note: Here all the config were working but somehow I am not getting exchange profile values using RFC destination LCRSAPRFC. Hence I had to create RFC destination SAP_PROXY_ESR to make transaction SPROXY work.

d)    Configure SXMB_ADM transaction for runtime proxy message exchange

Create RFC destination <any name> of type G (HTTP Connections to External Server)

Target Host: PI host name

Port: Http port (50XX00) where XX- System number

Path Prefix: /XISOAPAdapter/MessageServlet?ximessage=true

Log on Details: 

Go to Transaction: SXMB_ADM->Integration Engine configuration

Note: For dual stack we generally give ABAP stack RFC destination, since we want to use ICO object we need to connection using SOAP adapter hence the path prefix used for RFC destination is  ( /XISOAPAdapter/MessageServlet?ximessage=true)

Introduction to Process Orchestration

If you analyse common business practices, you will find that they are generally a series of relatively simple activities that interact with each other to accomplish a larger, more complex result. While these smaller processes are the core of day-to-day business activities, many businesses only consider the large and complex aspects of their operations to be "processes". In truth, any chain of business activities that are carried out in order to achieve a specific goal should be considered a business process, regardless of how simple or small. Often costs are reduced, quality is increased and efficiency improved by simplifying and refining even the small processes. Keep in mind that a business process is not restricted to human interaction - it often includes interaction between various software applications as well.

Business Process Management

Business Process Management (BPM) is the way in which you plan, implement, and ultimately improve the processes that run your business. BPM tools such as SAP NetWeaver BPM, help to model and enable the automation of business processes - these tools  offer a clear view into processes through graphical representations, in-depth analysis and testing, process tracking, and continual process improvement. The beauty and power behind BPM is the capability to deliver the right work to the right people at the right time - everything can be automated and monitored. Key Process Indicators (KPI's) can be measured and Service Level Agreements (SLA's) can be enforced with automatic escalation rules - all of this independent of the underlying applications. In other words, a good BPM tool can work seamlessly across all other enterprise applications - including on premise, web, cloud and mobile.

Process Integration

While BPM focuses more on the human interaction of business processes, there are application integration tools such as SAP Process Integration (PI) that bring together various enterprise applications through a unified integration approach. These tools focus specifically on the automated communication between software applications. As an example, you could use SAP PI to facilitate the integration between Oracle Business Suite running Financials and SAP ERP running Human Resources. A well thought out integration product should never be technology or application dependent.

Business Rules Management

A huge problem with most enterprise software is that very often the logical conditions for business logic (business rules) are "hard-coded". What this means is that if the rules ever change, software developers are required to update all of the effected software components. Often complex rules are difficult to comprehend and implement - it can take days or even weeks for the business and developers to finally understand and correctly code the rules. Typically the developers understand the rules differently to what the business has tried to communicate and the change process takes a lot longer than it should. A risky but very common practice is that many business rules are only mapped out in the minds of specific business owners and very badly documented, if at all. If a key business owner leaves the company for any reason, the understanding of those rules go with him/her.

A solution to this is what we call Business Rules Management (BRM). Essentially, all business rules are stored in the business rules engine and enterprise software simply taps into these rules when required. The rules are managed centrally so that when they change, none of your software components need to be recoded. Once again it is very important that a BRM tool (such as SAP BRM) is not application dependent and that all of your software applications can tap into the rules engine and leverage its power.

A good example of a business rule is the calculation of a customer's credit limit at banks. It may sound like a simple rule, but there are many aspects taken into consideration - credit ratings, transaction history, age, level of education, current financial commitments, current income, assets and more.

Process Orchestration

The orchestration of business processes can be a complex task - one has to consider human interaction, application integration, rules management, KPI measurement, SLA monitoring, continuous improvement, user experience, business involvement, exception handling, and much more.

The SAP Process Orchestration bundle includes SAP BPM, SAP PI and SAP BRM. These are enabling tools that pass process ownership on to the business and allow IT to support the technology. All of these tools are completely independent and work across any other applications - this bundle is something that even non-SAP customers should be considering.

SAP has built their BPM and BRM tools in a way that the business can design the processes and rules with graphic modelling. Once a BPM model has been designed, it is simply passed on to the developer who quickly ties up application functionality to the process. The processes and rules that the business designs are the processes and rules that are ultimately executed. No more miscommunications or misunderstandings - simple.

Synchronous calls with the PI SOAP Adapter

I have not worked a lot with synchronous calls and modules. So I had to learn a bit about it.

In July I launched the SAP PIArchiving solution, to make it easier to archive messages in the adapter framework. It could be EDIFact or XML messages that you want to find easily and store safely.

One question I was asked was how the system worked with synchronous calls for instance for a web service. I guess that the adapter would figure it out and it was possible to make it work.

Now I finally had time to test how to put the adapter modules on a SOAP adapter, to archive the messages for both ways. It proved really easy. The only change was that the adapter module should be placed before and after the SAP standard module.

The processing sequence should just look like this.

image

The modules can be configured independent of each other using the module key.

What seems to happen when this occurs is that the two messages are being processed.

image

When looking at the processing logs it is possible to see the connection. In the adapter communication logs the following information exists. There is a link to the continuing processing of a message as well as continuing from this guid. It is thereby possible to find the corresponding message.

image

What I like about this is how the framework works, is that the modules do need to know anything that it is a synchronous message. My archiving modules still works, which is just really nice.

Chem XML Message eStandards and CIDX Scenario Part III

In my earlier blogs efforts are made to explain about CIDX standards, how to design and configure the object to support CIDX communication.

Blog1

Blog2

I would like to make your experience pleasant and fruitful with CIDX communication through this blog.

This blog covers those intricate details in regard to security, certificates through simple steps, focusing on PI 7.1

You have already selected CIDX adapter with Transport Protocol as “HTTPS” and Message Protocol as “RNIF 1.1” for communication. Selecting the message protocol to RNIF 1.1 means you are configuring the scenario to handle Preamble, Service Header, Service Content, Digital Signatures etc…

We will focus on achieving HTTPS communication which is a combination of HTTP with SSL/TLS protocol to provide encrypted communication and secure identification of a network web server.

Step 1: Since the CIDX adapter is available through adapter engine, you need to set your server through Java stack to receive and send secured messages.

SSL Communications are handled by ICM (Internet Communication Manager) for both the Java and ABAP servers. You need to perform the configuration to use one of it, navigate to RZ10, select the profile <SYSID>_DVEBMGS00_<host> and configure the profile parameter.

ssl/pse_provider              = JAVA

Step 2: Restart the server to notice automatic creation of Keystore views in SAP NetWeaver Administration (NWA).

Navigate to NWA >> Configuration Management >> Certificate and Keys.

Identify the new Keystore View named after ICM_SSL_<instance ID>

Create the private key in the specified keystore view using “Create” and follow the wizard.

Notice that “Generate CSR Request” is enabled and use it generate CSR Request. Basically this step is needed to get your certificate issued by 3rd party Authority, to be identified as secure partner to carry out secure online transactions and conduct the business over internet.

When you purchase the certificate that is considered as CSR Response. Select the private key that you have just created and import it as “Import CSR Response”.

Copy these certificates into Trusted CAs and secure_ssl  keystore Views.

Step 3: Load the public key of your partner with entire certificate chain (Public Key, Intermediate and Root) into keystore Views “ICM_SSL_XXXX”, Trusted CAs.

In the following screenshot, you can view Verisign as Certificate Authority and chain of certificates.

They can be recognized as Verisign as root, Verisign Class 3 Secure Server CA – G3 as intermediate and business.partner.com as public key.

At times your partners provide self signed certificates, however PI supports.

Step 4: Choose how you want to enable your partner log into your server to come up with processing a message request.

a) In some cases, the certificate is issued with CN = <user id>, then provide necessary authorizations to the user.

b) In most cases, the certificate is issued after host name for eg., business.partner.com. In this case to support the certificate log in, you need to perform additional settings.

    i. Create a certificate user say PICERTUSER with adequate authorizations (One of it is ‘XI_AF_RECEIVE’).

    ii. Navigate to NWA >> Configuration Management  >> Security >> Authentication

Go to Login module, ClientCertLoginModule.

Edit to maintain Name as “Rule1.getUserFrom” and Value as “wholeCert”.

       iii. Navigate to NWA >> Configuration Management >> Security >> Identity Management.

Display PICERTUSER, Modify to load the partner certificate(Only Public key).

It basically means when message comes from remote server, certificate is authenticated and then accept to login through PICERTUSER.

Internally the message is checked whether valid or not by comparing the certificate Authority in ICM_SSL_XXX and partner through TrustedCAs. If it exists, it passes and then next part of steps is to select the matching user with the certificate.

    iv. As an additional optional step, you may want to restrict the processing of scenario to this user through Business component >>Assigned Users in Configuration.

Step 5: Follow my previous blog 2 for configuration.

Wait for another blog that focuses on Troubleshooting CIDX communication.

For additional help use SAP resources

  1. Maintaining the User’s Certificate Information

http://help.sap.com/saphelp_nwpi711/helpdata/en/a7/1cd08ffe25e34799cbbe1a7ecdb8ed/frameset.htm

     3. You may use diagtool provided by SAP, more details are available in note#1045019 – Web Diagtool for collecting traces. This is a very good tool that provides you the visibility on how the message is being processed.

Handling patterns and manipulating hierarchies through XSLT

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 -->
        <xsl:variable name="e1edkxx_original">
            <xsl:for-each select="//IDOC/*">
                <!--Copying the E1EDKxx segments as they are -->
                <xsl:if test="starts-with(name(), 'E1EDK')">
                <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>

Note: For checking every segment name inside IDOC, we need to run a loop on * (<xsl:for-each select="//IDOC/*"> )

Now we need E1EDKxx segment same as in the source idoc but with a change E1EDK14-ORGID = 'G2O' (where qualifier = '015'). We will store this data in another variable e1edkxx_changed.

                         <!-- Copying all the E1EDKxx segments from the idoc with a change E1EDK14-ORGID = 'G2O', these will work as header for corrected E1EDP01 -->
        <xsl:variable name="e1edkxx_changed">
            <xsl:for-each select="//IDOC/*">
                <!--Copying other E1EDKxx segments as they are -->
                <xsl:if test="not (starts-with(name(), 'E1EDK14') and QUALF = '015') and (starts-with(name(), 'E1EDK'))">
                    <xsl:copy-of select="."/>
                </xsl:if>
                <!--Changing E1EDK14-ORGID where qualifier = '015' -->
                <xsl:if test="starts-with(name(), 'E1EDK14') and QUALF = '015'">
                    <E1EDK14>
                        <xsl:attribute name="SEGMENT"><xsl:value-of select="1"/></xsl:attribute>
                        <QUALF>015</QUALF>
                        <ORGID>
                            <xsl:value-of select="'G2O'"/>
                        </ORGID>
                    </E1EDK14>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>

We will store all the E1EDP01 segments in a variable all_e1edp01.

                <!--Copying the E1EDPxx segments as they are -->
        <xsl:variable name="all_e1edp01">
            <xsl:for-each select="//IDOC/*">
                <!--Copying the E1EDKxx segments as they are -->
                <xsl:if test="starts-with(name(), 'E1EDP') ">
                    <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>

E1EDSxx segments would be used as trailer. A variable trailer will hold all the E1EDSxx segments.

        <xsl:variable name="trailer">
            <!--Trailer Record E1EDSxx-->
            <xsl:for-each select="//IDOC/*">
                <!--Copying the E1EDSxx segments as they are -->
                <xsl:if test="starts-with(name(), 'E1EDS') ">
                    <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
            <!--    Finishing the trailer part here-->
        </xsl:variable>

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 <xsl:key> element.

For using the key function, we first need to declare a definition of key function in the beginning of XSLT code.

     <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="urn:test:xi:Sales:100">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <!--Defining key for HIPOS, HIPOS of corrected E1EDP01 = POSEX of original E1EDP01 -->
    <xsl:key name="E1EDPXX_HIPOS" match="E1EDP01" use="HIPOS"/>

Declaration of key in the beginning of XSLT, informs the processor that we would be using key() function somewhere in the code.Now we just need to run a loop on POSEX of the E1EDP01 and compare the key function output if:

E1EDP01-HIPOS from Key Function = Current E1EDP01-POSEX.

And then place these segments in the required format using copy-of function.

           <!-- Forming the required structure here-->
            <IDOC>
                <xsl:copy-of select="$controlRecord"/>    <!-- Control Record -->
                <xsl:for-each select="$all_e1edp01/*">     <!-- Manupulating the E1EDPxx segments here -->
                    <!-- Checking if the value of Posex in the current E1EDP01 segment is equal to the HIPOS of any of E1EDP01 segment  -->
                    <!-- Assumption is that HIPOS is populated only in case of corrected E1EDP01 items and is equal to POSEX of the original E1EDP01 -->
                    <xsl:if test="POSEX = key('E1EDPXX_HIPOS', POSEX)/HIPOS ">
                        <xsl:copy-of select="$e1edkxx_changed"/>    <!-- Copying E1EDKxx Changed  -->
                        <xsl:copy-of select="."/>                    <!-- Copying E1EDP01 segment (original)-->                   
                        <xsl:copy-of select="$trailer"/>                <!--Copying E1EDSxx Segment-->
                        <xsl:copy-of select="$e1edkxx_original"/>     <!-- Copying E1EDKxx Original-->
                        <xsl:copy-of select="key('E1EDPXX_HIPOS', POSEX)"/>    <!-- Copying E1EDP01 segment for correction-->
                        <xsl:copy-of select="$trailer"/>
                    </xsl:if>
                </xsl:for-each>
                </IDOC>

Here is the complete code which will transform the IDoc into required format.

       <?xml version="1.0" encoding="UTF-8"?>
<!-- This XSLT converts invoice IDoc into a required format as requested by third party.
    In case of correction invoice, Invoice IDoc would have even number of E1EDP01 (Item) segments since for each correction there will be an original E1EDP01   
      segment. Apart from this there will be standard header E1EDKxx segments and E1EDSxx segments in the INVOIC02 IDoc.
    The E1EDKxx segments are treated as header segment for the corrected E1EDP01 segments.
    The same E1EDKxx segments would be repeated for origin items E1EDP01 with a slight change that ORGID will be set as G2O for E1EDK14 segment where qualifier = 015.
    The original IDoc structure received from SAP ECC in case of correction invoice is :
    IDOC
        EDI_DC40
        E1EDKxx segments
        (will be used as header for corrected E1EDP01 segment, and will be used as header (with a slight change in E1EDK14 segment) for original E1EDP01
        E1EDPxx segments ( even number of E1EDPxx segments)
        E1EDSxx segments ( will be used as trailer record in the output)
*****************************************************************************************************************************************************************************************
Structure as required by Third Party
        IDOC
            EDI_DC40
            E1EDKxx_changed
            E1EDP01 (item number 1, original item)
            E1EDSxx ( trailer)
            E1EDKxx_original
            E1EDP01 (item number 1, corrected item)
            E1EDSxx ( trailer)
            E1EDKxx_changed
            E1EDP01 (item number 2, original item)
            E1EDSxx ( trailer)
            E1EDKxx_original
            E1EDP01 (item number 2, corrected item) PSTYV=ZL2N
            E1EDSxx ( trailer)
            ................................................
            ................................................
    Original E1EDP01 segments would be related to corrected E1EDP01 segments by E1EDP01-POSEX and E1EDP01-HIPOS.
    POSEX of original E1EDP01 = HIPOS of corrected E1EDP01. HIPOS is populated by custom coding in ECC only for correction line items.
    This XSLT does the required transformation.
-->
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="urn:test:xi:Sales:100">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <!--Defining key for HIPOS, HIPOS of corrected E1EDP01 = POSEX of original E1EDP01 -->
    <xsl:key name="E1EDPXX_HIPOS" match="E1EDP01" use="HIPOS"/>
    <xsl:template match="/">
                <!--Copying the EDI_DC40 segment -->
        <xsl:variable name="controlRecord" select="//IDOC/EDI_DC40"/>
        <!--Copying all the E1EDKxx segments from the idoc, these will work as header for original E1EDP01 -->
        <xsl:variable name="e1edkxx_original">
            <xsl:for-each select="//IDOC/*">
                <!--Copying the E1EDKxx segments as they are -->
                <xsl:if test="starts-with(name(), 'E1EDK')">
                <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
        <!-- Copying all the E1EDKxx segments from the idoc with a change E1EDK14-ORGID = 'G2O', these will work as header for corrected E1EDP01 -->
        <xsl:variable name="e1edkxx_changed">
            <xsl:for-each select="//IDOC/*">
                <!--Copying other E1EDKxx segments as they are -->
                <xsl:if test="not (starts-with(name(), 'E1EDK14') and QUALF = '015') and (starts-with(name(), 'E1EDK'))">
                    <xsl:copy-of select="."/>
                </xsl:if>
                <!--Changing E1EDK14-ORGID where qualifier = '015' -->
                <xsl:if test="starts-with(name(), 'E1EDK14') and QUALF = '015'">
                    <E1EDK14>
                        <xsl:attribute name="SEGMENT"><xsl:value-of select="1"/></xsl:attribute>
                        <QUALF>015</QUALF>
                        <ORGID>
                            <xsl:value-of select="'G2O'"/>
                        </ORGID>
                    </E1EDK14>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
        <xsl:variable name="trailer">
            <!--Trailer Record E1EDSxx-->
            <xsl:for-each select="//IDOC/*">
                <!--Copying the E1EDSxx segments as they are -->
                <xsl:if test="starts-with(name(), 'E1EDS') ">
                    <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
            <!--    Finishing the trailer part here-->
        </xsl:variable>
        <!--Copying the E1EDPxx segments as they are -->
        <xsl:variable name="all_e1edp01">
            <xsl:for-each select="//IDOC/*">
                <!--Copying the E1EDKxx segments as they are -->
                <xsl:if test="starts-with(name(), 'E1EDP') ">
                    <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
        <!-- Forming the required structure here-->
            <IDOC>
                <xsl:copy-of select="$controlRecord"/>    <!-- Control Record -->
                <xsl:for-each select="$all_e1edp01/*">     <!-- Manupulating the E1EDPxx segments here -->
                    <!-- Checking if the value of Posex in the current E1EDP01 segment is equal to the HIPOS of any of E1EDP01 segment  -->
                    <!-- Assumption is that HIPOS is populated only in case of corrected E1EDP01 items and is equal to POSEX of the original E1EDP01 -->
                    <xsl:if test="POSEX = key('E1EDPXX_HIPOS', POSEX)/HIPOS ">
                        <xsl:copy-of select="$e1edkxx_changed"/>    <!-- Copying E1EDKxx Changed  -->
                        <xsl:copy-of select="."/>                    <!-- Copying E1EDP01 segment (original)-->                   
                        <xsl:copy-of select="$trailer"/>                <!--Copying E1EDSxx Segment-->
                        <xsl:copy-of select="$e1edkxx_original"/>     <!-- Copying E1EDKxx Original-->
                        <xsl:copy-of select="key('E1EDPXX_HIPOS', POSEX)"/>    <!-- Copying E1EDP01 segment for correction-->
                        <xsl:copy-of select="$trailer"/>
                    </xsl:if>
                </xsl:for-each>
                </IDOC>
    </xsl:template>
</xsl:stylesheet>

The source file in Altova

Source IDoc data in Altova

On executing XSLT, target file is generated

Target xml data in Altova

Important Points to Note:

1) For running a loop on IDoc data, we choose //IDoc/* since we have to copy multiple segments.

2) Use of xslt function starts-with(name(), 'Pattern') to copy data.

3) Copying the required segments in variables and then putting them in desired position.

4) Using Key Function to relate two segments. Key function is quite efficient when dealing with large XSLT.

SAP Developer Network SAP Weblogs: SAP Process Integration (PI)