Add a Floating Social Media bar to your blog - Get it Free! X

XI/PI: Convert Flat File to Deeply Nested XML Structures Using Only Graphical Mapping

Converting a flat file to deeply nested XML structures would require the use of either custom developed adapter modules or third-party conversion agents. This article provides a workaround to accomplish the same thing by using just the standard file content conversion and graphical mapping.

Many a times, you are required to convert flat file structures to deeply nested structures like IDocs. Standard File Content Conversion allows you to convert the incoming file to flat XML structures only i.e. only one level of nesting is possible. Converting incoming file to deeply nested structures would require use of either custom developed adapter modules or third-party conversion agents.

This article provides a workaround to accomplish the same thing by using only the graphical mapping. William had a similar requirement, and we came up with a generic solution which is described below.

Lets say we have an incoming flat file with structure as described below –

Node1 – Occurs 0..1
Node2 – Occurs 0..unbounded
Node3 – Occurs 0..unbounded
Node4 – Occurs 0..unbounded

And the target structure is as shown below –

Node1 – Occurs 0..1
Node2 – Occurs 0..unbounded
Node3 – Occurs 0..unbounded and repeats under the preceding Node2
Node4 – Occurs 0..unbounded and repeats under the preceding Node3

File Content ConversionDue to limitation of the standard File adapter, it is not possible to directly convert the incoming file to the deeply nested target structure. Hence we will use a two step message mapping to attain the required result.

First, we will use file content conversion as shown to covert the incoming file to flat XML structure as supported by the adapter. Click the image on the right to see an enlarged view. We will then use two-step message mapping to convert the flat XML to a nested XML. Figure below shows the flat XML structure generated by the file adapter using file content conversion.

Source Message

Our aim is to convert the above flat structure to a nested shown below –

Target Message

Note that there is no common element between parent and child nodes (e.g. Node2 and Node3, or Node3 and Node4) which we could use to determine corresponding parent node for each child node.

Hence, we need to create an intermediate message type which will establish a relationship between the parent and child nodes. We have achieved this by adding id attributes to each of the nodes as shown below.

Intermediate Message

The id attribute is mapped using a user defined function globalCounter which records the order in which the nodes appear in the source structure. The variable used to store the count is a global variable and is incremented every time a node is found in the source structure (irrespective of the node name).

Create one-to-one message mapping between source message and the intermediate message. Map the id attribute in the target with the globalCounter function.

globalcounter UDF

The Java code of the globalCounter function is given below –

public String globalCounter(Container container){
GlobalContainer globalContainer;

globalContainer = container.getGlobalContainer();
Object o = globalContainer.getParameter("count");
Integer i;

if ( o == null ) i = new Integer( 0 );
else i = (Integer)o;

i = new Integer(i.intValue() + 1 );
globalContainer.setParameter("count", i );

return i.toString();
}

Now create another message mapping to map the intermediate message type to the target message type. The message mapping is shown below.

Message Mapping

Node 1 is directly mapped to Node1 in the target as this node is not part of any hierarchy. The topmost parent node Node2 is mapped using removeContexts function.

First node mapping

All the nodes appearing below the topmost node (Node3 and Node4 in this case) have been mapped using removeContexts function and user defined nest function as shown below -

Child node mapping using UDF nest

The first parameter to the nest function is the id attribute of the parent node while the second parameter is the id attribute of the current node (child node). Both parameters have been first processed with removeContexts function before passing them to the nest function. The third parameter is the actual value of the node that needs to passed on to the target structure. Below is the Java code for the nest function.

public void nest(String[] parent,String[] current,String[] node,ResultList result,Container container){
int i, j;
int a, b, c;
int x;
j = 0;
x = j+1;
for( i = 0; i < current.length; i++ ) {

for (;x<parent.length; j++,x++ ){

a = Integer.parseInt(parent [j]);
b = Integer.parseInt(current [i]);
c = Integer.parseInt(parent [x]);
if ( a < b ) {

if(c > b ) {

result.addValue(node[i]);
break;
}

else if (c < b) {

result.addContextChange();
}

}

}

if (x == parent.length) {

result.addValue(node[i]);
}

}

}

PS: If you are new to the idea of context handling, do read An Introduction to Context Handling.

Once this is done, create an interface mapping between the source and target interface and provide the mapping programs in the correct order i.e. first the mapping between source and intermediate message and then the one between intermediate and target structure. The same is shown below –

Interface Mapping with Two-step Message Mapping

Now you can test the interface mapping locally and then test your scenario by doing appropriate directory configuration. Interface mapping test result is shown in the figure below –

Test Result

Thus, we have seen how we can use plain file adapter and graphical mapping to convert a flat file to a deeply nested XML structure.

This idea could even be extended to convert EDI documents to IDoc structures as an alternative to third-party EDI adapters like Seeburger.

Comments

  1. We’re a group of volunteers and opening a new scheme in our community. Your web site offered us with valuable information to work on. You’ve done a formidable job and our whole community will be
    thankful to you.

  2. Rosetta says:

    Quick tip…. more pictures and video clips in upcoming posts.
    Big blocks of text hurt my eyes and I detest it, lol. Walls
    of text hits for 900 damage…. haha. This joke never ever gets old.
    Nice information though!

  3. Prasanna says:

    Hi Riyaz,
    My problem is similar to what Neha Rai has posted.
    After the first mapping , instead of this output:
    Header – 1
    Detail – 2
    Weight – 3
    Weight – 4
    Detail – 5
    Weight – 6
    Weight – 7
    Trailer

    I am getting below:

    Header – 1
    Detail – 2
    Detail – 3
    Weight – 4
    Weight – 5
    Weight – 6
    Weight – 7
    Trailer

  4. Hi Riyaz,

    Hope you are having a good time.

    I am stuck with one error in SXMB_MONI_BPE. We did the upgrade of objects from XI production to PI. The interface working in XI is not working in PI. This is showing up an error in BPE monitoring. Error is
    -
    Mapping http://fuelGoodsIssue.sap.dominofoods.com IM_FUELFILE_2_FUELVAL_REQUEST , Software Component Version A8A25E80F59011DAC55BEE540ADE8788
    Mapping Step 1 , Type JAVA , Program com/sap/xi/tf/_MM_FUELFILE_2_FUELVAL_REQUEST_
    RuntimeException during appliction Java mapping com/sap/xi/tf/_MM_FUELFILE_2_FUELVAL_REQUEST_ Thrown: com.sap.aii.mappingtool.tf7.IllegalInstanceException: Cannot create target element /ns1:Z_FUEL_VAL_UPDATE_PROCESS/PCFILE. Values missing in queue context. Target XSD requires a value for this element, but the target-field mapping does not create one. Check whether the XML instance is valid for the source XSD, and whether the target-field mapping fulfils the requirement of the target XSD at com.sap.aii.mappingtool.tf7.AMappingProgram.processNode(AMappingProgram.java:369) at com.sap.aii.mappingtool.tf7.AMappingProgram.processNode(AMappingProgram.java:411) at com.sap.aii.mappingtool.tf7.AMappingProgram.start(AMappingProgram.java:503) at com.sap.aii.mappingtool.tf7.Transformer.start(Transformer.java:134) at com.sap.aii.mappingtool.tf7.AMappingProgram.transform(AMappingProgram.java:635) at com.sap.aii.ib.server.mapping.execution.JavaMapping.executeStep(JavaMapping.java:92) at com.sap.aii.ib.server.mapping.execution.Mapping.execute(Mapping.java:60) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:87) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:71) at com.sap.aii.ibrun.sbeans.mapping.MappingRequestHandler.handleMappingRequest(MappingRequestHandler.java:119) at com.sap.aii.ibrun.sbeans.mapping.MappingRequestHandler.handleRequest(MappingRequestHandler.java:72) at com.sap.aii.ibrun.sbeans.mapping.MappingServiceImpl.processFunction(MappingServiceImpl.java:79) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:592) at com.sap.engine.services.ejb3.runtime.impl.RequestInvocationContext.proceedFinal(RequestInvocationContext.java:46) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:166) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatesTransition.invoke(Interceptors_StatesTransition.java:19) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Resource.invoke(Interceptors_Resource.java:71) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.doWorkWithAttribute(Interceptors_Transaction.java:38) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.invoke(Interceptors_Transaction.java:22) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:189) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatelessInstanceGetter.invoke(Interceptors_StatelessInstanceGetter.java:16) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_SecurityCheck.invoke(Interceptors_SecurityCheck.java:21) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_ExceptionTracer.invoke(Interceptors_ExceptionTracer.java:16) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.DefaultInvocationChainsManager.startChain(DefaultInvocationChainsManager.java:133) at com.sap.engine.services.ejb3.runtime.impl.DefaultEJBProxyInvocationHandler.invoke(DefaultEJBProxyInvocationHandler.java:164) at $Proxy982.processFunction(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:592) at com.sap.engine.services.rfcengine.RFCDefaultRequestHandler.handleRequest(RFCDefaultRequestHandler.java:183) at com.sap.engine.services.rfcengine.RFCJCOServer$J2EEApplicationRunnable.run(RFCJCOServer.java:267) at com.sap.engine.core.thread.impl3.ActionObject.run(ActionObject.java:37) at java.security.AccessController.doPrivileged(Native Method) at com.sap.engine.core.thread.impl3.SingleThread.execute(SingleThread.java:182) at com.sap.engine.core.thread.impl3.SingleThread.run(SingleThread.java:280)
    Runtime Exception when executing application mapping program com/sap/xi/tf/_MM_FUELFILE_2_FUELVAL_REQUEST_; Details: com.sap.aii.mappingtool.tf7.IllegalInstanceException; Cannot create target element /ns1:Z_FUEL_VAL_UPDATE_PROCESS/PCFILE. Values missing in queue context. Target XSD requires a value for this element, but the target-field mapping does not create one. Check whether the XML instance is valid for the source XSD, and whether the target-field mapping fulfils the requirement of the target XSD Thrown: com.sap.aii.ib.core.mapping.execution.ApplicationRuntimeException: Runtime Exception when executing application mapping program com/sap/xi/tf/_MM_FUELFILE_2_FUELVAL_REQUEST_; Details: com.sap.aii.mappingtool.tf7.IllegalInstanceException; Cannot create target element /ns1:Z_FUEL_VAL_UPDATE_PROCESS/PCFILE. Values missing in queue context. Target XSD requires a value for this element, but the target-field mapping does not create one. Check whether the XML instance is valid for the source XSD, and whether the target-field mapping fulfils the requirement of the target XSD at com.sap.aii.ib.server.mapping.execution.JavaMapping.executeStep(JavaMapping.java:118) at com.sap.aii.ib.server.mapping.execution.Mapping.execute(Mapping.java:60) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:87) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:71) at com.sap.aii.ibrun.sbeans.mapping.MappingRequestHandler.handleMappingRequest(MappingRequestHandler.java:119) at com.sap.aii.ibrun.sbeans.mapping.MappingRequestHandler.handleRequest(MappingRequestHandler.java:72) at com.sap.aii.ibrun.sbeans.mapping.MappingServiceImpl.processFunction(MappingServiceImpl.java:79) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:592) at com.sap.engine.services.ejb3.runtime.impl.RequestInvocationContext.proceedFinal(RequestInvocationContext.java:46) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:166) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatesTransition.invoke(Interceptors_StatesTransition.java:19) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Resource.invoke(Interceptors_Resource.java:71) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.doWorkWithAttribute(Interceptors_Transaction.java:38) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.invoke(Interceptors_Transaction.java:22) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:189) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatelessInstanceGetter.invoke(Interceptors_StatelessInstanceGetter.java:16) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_SecurityCheck.invoke(Interceptors_SecurityCheck.java:21) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_ExceptionTracer.invoke(Interceptors_ExceptionTracer.java:16) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.DefaultInvocationChainsManager.startChain(DefaultInvocationChainsManager.java:133) at com.sap.engine.services.ejb3.runtime.impl.DefaultEJBProxyInvocationHandler.invoke(DefaultEJBProxyInvocationHandler.java:164) at $Proxy982.processFunction(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:592) at com.sap.engine.services.rfcengine.RFCDefaultRequestHandler.handleRequest(RFCDefaultRequestHandler.java:183) at com.sap.engine.services.rfcengine.RFCJCOServer$J2EEApplicationRunnable.run(RFCJCOServer.java:267) at com.sap.engine.core.thread.impl3.ActionObject.run(ActionObject.java:37) at java.security.AccessController.doPrivileged(Native Method) at com.sap.engine.core.thread.impl3.SingleThread.execute(SingleThread.java:182) at com.sap.engine.core.thread.impl3.SingleThread.run(SingleThread.java:280) Caused by: com.sap.aii.mappingtool.tf7.IllegalInstanceException: Cannot create target element /ns1:Z_FUEL_VAL_UPDATE_PROCESS/PCFILE. Values missing in queue context. Target XSD requires a value for this element, but the target-field mapping does not create one. Check whether the XML instance is valid for the source XSD, and whether the target-field mapping fulfils the requirement of the target XSD at com.sap.aii.mappingtool.tf7.AMappingProgram.processNode(AMappingProgram.java:369) at com.sap.aii.mappingtool.tf7.AMappingProgram.processNode(AMappingProgram.java:411) at com.sap.aii.mappingtool.tf7.AMappingProgram.start(AMappingProgram.java:503) at com.sap.aii.mappingtool.tf7.Transformer.start(Transformer.java:134) at com.sap.aii.mappingtool.tf7.AMappingProgram.transform(AMappingProgram.java:635) at com.sap.aii.ib.server.mapping.execution.JavaMapping.executeStep(JavaMapping.java:92) … 39 more

    I checked all the mapping seems to be identical to XI prod box.

    Please let me know the resolution for this. We are in PI7.11

    Thanks a lot in advance

    Regards,
    Mahesh

  1. Infittisy says:

    Hihi guys, long time lurker first time poster here

    pleased to be a member, and I look forward to begin getting more active here

    For now take a look at my site http://articlewriter.websex7.com/?p=3

  2. Riyaz says:

    If you are getting a specific output that is because of the input data you are passing. The code will add the counters in the same sequence as the source data. Either change your source data and test or then chnage the code to suit your requirements.

  3. Riyaz says:

    I guess you need to revisit and make sure that the contexts used for individual nodes are giving correct results. If not, you can try changing the contexts. To do this, make sure you have a source xml in the test tab of your mapping editor. Then on design tab, right click each node function, say removeContexts, nest etc and choose Display Queue to see if the conversion is as desired. If not, you can change the contexts of source elements by right-clicking and choosing appropriate context. For more details on context handling see http://www.riyaz.net/blog/xipi-introduction-to-context-handling-in-message-mapping/technology/sap/5/

    I would also suggest using tool like NWDS or eclipse to further debug the Java code.

  4. Neha Rai says:

    Hi Riyaz

    I have a simillar requirement and I tried ur global container and nest function but i am

    still not getting the appropriate response. My source structure is after content conversion

    is:

    Header — 0…1
    Detail — 0..unbounded
    Weights — 0..unbounded
    trailer — 0…1

    and i want to convert it to the following target:

    Header — 0…1
    Detail — 0..unbounded
    Weights — 0..unbounded (repeats under preceding node detail)
    trailer — 0…1

    To acheive this I made one mapping MM_Intermediate where source and target were as given

    below and I added the global container UDF provided by you as it is and target came out like

    this:
    ————-Source————–
    ns: MT_REQ
    header
    …………
    /header
    Detail
    ……..
    ……..
    /Detail
    Weight
    ……..
    ……….
    /Weight
    Weight
    ……….
    ………..
    /Weight
    Detail
    ……..
    ……..
    /Detail
    Weight
    ……..
    ……….
    /Weight
    Weight
    ……….
    ………..
    /Weight
    trailer
    ………
    /trailer

    ——Target——– After applying the UDF

    ns: MT_Intermediate
    header>
    …………
    /header
    Detail
    SEQ —- value 1
    ……..
    /Detail
    Detail
    SEQ —- value 2
    ……..
    /Detail
    Weight
    SEQ —- value 3
    ……….
    /Weight
    Weight
    SEQ —- value 4
    ………..
    /Weight
    Weight
    SEQ —- value 5
    ……….
    /Weight
    Weight
    SEQ —- value 6
    ………..
    /Weight
    trailer
    ………
    /trailer

    And finally i made the message mapping MM_Target where I mapped the above response to the

    IDOC to achieve this as final target:
    NOTE: I added SEQ of of Detail, SEQ of Weights and Weights to the UDF “nest” but all

    the weights are getting shifted to the second detail.
    <ns: MT_Target
    header
    …………
    /header
    Detail
    Weight
    ……….
    /Weight
    Weight
    ……….
    /Weight
    /Detail
    Detail
    Weight
    ……….
    /Weight
    Weight
    ……….
    /Weight
    /Detail
    trailer
    ………
    /trailer

    My code for UDF nest is this:

    public void nest(String[] parent,String[] current,String[] node,ResultList result,Container

    container){
    int i, j;
    int a, b, c;
    int x;
    j = 0;
    x = j+1;
    for( i = 0; i < current.length; i++ ) {

    for (;x<parent.length; j++,x++ ){

    a = Integer.parseInt(parent [j]);
    b = Integer.parseInt(current [i]);
    c = Integer.parseInt(parent [x]);
    if ( a b ) {

    result.addValue(node[i]);
    break;
    }

    else if (c < b) {

    result.addContextChange();
    }

    }

    }

    if (x == parent.length) {

    result.addValue(node[i]);
    }

    }
    }

    I don't have much knowledge of Java. Please help.
    I am waiting for your reply.

    Thanks

    Neha

  5. Abhishek Mathur says:

    Hi Riyaz,

    This one is really cool blog. Just reviwed my old SAP XI skills which was quiet washed away in last couple of months :-) :-)

    Thanks
    Abhishek

    • Riyaz says:

      Thank you Abhishek. Glad that you liked my blog :)

      • Neha Rai says:

        Hi Riyaz

        My first question is when applying code for global Container UDF to attribute SEQ the count should be like the one given below or anything else:

        Header – 1
        Detail – 2
        Weight – 3
        Weight – 4
        Detail – 5
        Weight – 6
        Weight – 7
        Trailer

        OR like the one I am getting below:

        Header – 1
        Detail – 2
        Detail – 3
        Weight – 4
        Weight – 5
        Weight – 6
        Weight – 7
        Trailer

        Can this be a problem.

        • Riyaz says:

          off course the first one is correct

          • Neha Rai says:

            Hi Riyaz

            But the code is giving the following output

            Header – 1
            Detail – 2
            Detail – 3
            Weight – 4
            Weight – 5
            Weight – 6
            Weight – 7
            Trailer

            This is the code:

            public String globalCounter(Container container){
            GlobalContainer globalContainer;

            globalContainer = container.getGlobalContainer();
            Object o = globalContainer.getParameter(“count”);
            Integer i;

            if ( o == null ) i = new Integer( 0 );
            else i = (Integer)o;

            i = new Integer(i.intValue() + 1 );
            globalContainer.setParameter(“count”, i );

            return i.toString();
            }

            I have sent you an Email with an attachment. Could you please check it.

            Regards

            Neha

  6. Riyaz says:

    Abhay,
    Can you please elaborate your question. What is the source structure and what is the target structure you are trying to map to?

  7. Abhay says:

    Hi Riyaz,

    I want to populate my fields in header line on receiver file adapter

    let say 2 fields

    Countey , City

    India,Bangalore
    UK,London
    Sweden,Stockholm
    Japan,tokoyo

    How can we achive this??

    Waiting for your reply.

  8. Riyaz says:

    In my example, there is no nesting for node1. Multiple level nesting starts with Node2. Node3 is child of Node2 while Node4 is child of Node3. But Node2 is not child of Node1. This is just an example. You may need to adapt the mapping as per the target structure you need to derive.

  9. Vishnu says:

    Hi Riyaz,

    Thanks for all your wonderful information.

    We have requirement of hierarchial mapping from IDOC to fIe and File to IDOC .
    I have seen your blog. I got struck at one point.

    I would like to know, how to do first level mapping.. is it same as flat file.. then do
    hierarchial map of source with Id’s( as per your blog ) with target IDOc.

    Please help me if with any detail documents or screenshots of both scenarios.

    Thanks in Advance.
    Vishnu

  10. LaptopAces says:

    Thanks! Its realy cool. I think you make realy hard work.

  11. Riyaz says:

    try testing locally in IR. Probably the namespace of the source XML may not be correct, i.e as per the source xsd.

  12. Amol says:

    Hi Riyaz
    Please let me know your inputs. Thanks.

  13. Amol says:

    Hi Riyaz
    I have corss checked the mapping and its exactly same as you have mentioned above, here is the error i am getting when i send more than one record row

    RuntimeException during appliction Java mapping com/sap/xi/tf/__

    com.sap.aii.mappingtool.tf7.IllegalInstanceException: Cannot create target element /ns1:ProductActivityNotification/ProductActivity/Item[2]/Product. Values missing in queue context. Target XSD requires a value for this element, but the target-field mapping does not create one. Check whether the XML instance is valid for the source XSD, and whether the target-field mapping fulfils the requirement of the target XSD at com.sap.aii.mappingtool.tf7.AMappingProgram.processNode(AMappingProgram.java:366) at com.sap.aii.mappingtool.tf7.AMappingProgram.processNode(AMappingProgram.java:406) at com.sap.aii.mappingtool.tf7.AMappingProgram.processNode(AMappingProgram.java:406) at com.sap.aii.mappingtool.tf7.AMappingProgram.processNode(AMappingProgram.java:406) at com.sap.aii.mappingtool.tf7.AMappingProgram.start(AMappingProgram.java:496) at com.sap.aii.mappingtool.tf7.Transformer.start(Transformer.java:133) at com.sap.aii.mappingtool.tf7.AMappingProgram.transform(AMappingProgram.java:626) at com.sap.aii.ib.server.mapping.execution.JavaMapping.executeStep(JavaMapping.java:92) at com.sap.aii.ib.server.mapping.execution.Mapping.execute(Mapping.java:60) at com.sap.aii.ib.server.mapping.execution.SequenceMapping.executeStep(SequenceMapping.java:40) at com.sap.aii.ib.server.mapping.execution.Mapping.execute(Mapping.java:60) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:87) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:54) at com.sap.aii.ibrep.server.mapping.rt.MappingHandlerAdapter.run(MappingHandlerAdapter.java:139) at com.sap.aii.ibrep.server.mapping.exec.ExecuteIfMapCommand.execute(ExecuteIfMapCommand.java:33) at com.sap.aii.ib.server.mapping.exec.CommandManager.execute(CommandManager.java:43) at com.sap.aii.ibrep.server.mapping.ServerMapService.execute(ServerMapService.java:40) at com.sap.aii.ibrep.server.mapping.MapServiceBean.execute(MapServiceBean.java:40) at sun.reflect.GeneratedMethodAccessor824.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at com.sap.engine.services.ejb3.runtime.impl.RequestInvocationContext.proceedFinal(RequestInvocationContext.java:43) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:166) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatesTransition.invoke(Interceptors_StatesTransition.java:19) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Resource.invoke(Interceptors_Resource.java:71) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.doWorkWithAttribute(Interceptors_Transaction.java:38) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.invoke(Interceptors_Transaction.java:22) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:189) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatelessInstanceGetter.invoke(Interceptors_StatelessInstanceGetter.java:16) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_SecurityCheck.invoke(Interceptors_SecurityCheck.java:21) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_ExceptionTracer.invoke(Interceptors_ExceptionTracer.java:16) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.DefaultInvocationChainsManager.startChain(DefaultInvocationChainsManager.java:133) at com.sap.engine.services.ejb3.runtime.impl.DefaultEJBProxyInvocationHandler.invoke(DefaultEJBProxyInvocationHandler.java:164) at $Proxy1579.execute(Unknown Source) at sun.reflect.GeneratedMethodAccessor823.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at com.sap.engine.services.rmi_p4.P4DynamicSkeleton.dispatch(P4DynamicSkeleton.java:234) at com.sap.engine.services.rmi_p4.DispatchImpl._runInternal(DispatchImpl.java:351) at com.sap.engine.services.rmi_p4.server.ServerDispatchImpl.run(ServerDispatchImpl.java:70) at com.sap.engine.services.rmi_p4.P4Message.process(P4Message.java:62) at com.sap.engine.services.rmi_p4.P4Message.execute(P4Message.java:37) at com.sap.engine.services.cross.fca.FCAConnectorImpl.executeRequest(FCAConnectorImpl.java:872) at com.sap.engine.services.rmi_p4.P4Message.process(P4Message.java:53) at com.sap.engine.services.cross.fca.MessageReader.run(MessageReader.java:58) at com.sap.engine.core.thread.execution.Executable.run(Executable.java:108) at com.sap.engine.core.thread.execution.CentralExecutor$SingleThread.run(CentralExecutor.java:304)

    Please give your inputs to solve the issue

  14. Riyaz says:

    Amol,
    Check the globalContainer UDF code. there could be typographic error. Copy and paste the code from the above code snippet. For your requirement, I guess the code given in this article for nest function should work without modifications. Header correspods to Node2 and Record correpsonds to Node3 while Forecast corresponds to Node4 in the article. Ensure that you do graphical mapping correctly as shown.

  15. Amol says:

    Hi Riyaz
    I am trying to implement above well described scenario but facing issue. Please find my requirement detail below

    Flat File Structure
    Header (1) -> Record (1…unbounded) -> Forecast (1…unbounded)

    Example of input file
    Header (Topmost node)
    Record 1 (should come under Header)
    Forecast 11 (should come under record 1)
    Forecast 12 (should come under record 1)
    Record 2 (should come under Header)
    Forecast 21 (should come under record 2)
    Forecast 21 (should come under record 2)

    It works fine if there is only 1 record row and multiple Forecast rows but it gives runtime error when I there is input of multiple record rows.

    Please let me know you inputs to solve the issue. I really appreciate your knowledge sharing. Thanks

    Regards
    Amol

  16. Amol says:

    Hi Riyaz
    Thank you for the information. But I am getting an error for global container UDF.

    the error is “Invalid start of expression” and the indication is at 1st line of code.

    I don’t know java, please give your inputs to solve the error. thanks

  17. Riyaz says:

    Thats very much possible. See my reply here.

  18. Deepika says:

    Hi Riyaz,

    that was a good blog. can we do the the same for the vice versa scenario. means can we convert the deeply nested structure to a flat file? if so, kinldy let me know

    Best Regards
    Deepika

  19. Aaron says:

    Hello Riyaz,

    I thought this suggestion might help some of your readers. If you have a flat file in the form of:

    File_Header
    Order-header 1
    order1line 1
    order1line 2
    Order-header 2
    order2line 1
    order2line 2
    order2line 3
    Footer

    If you need this as a two level xml file with multiple nodes at detail header level and associated line items immediately following, you can set the adapter config to something like:

    FILE_HEADER,1,ORDER_HEADER,1,ORDER_DETAIL,*,FOOTER,*

    This seems to make the footer optional and wrap the file into a nicely separated heirarchy with a new recordset for each Order_Header

    Regards,

    Aaron

  20. Riyaz says:

    Hi Vaccu,

    NumberFormatException might occur if you are passing empty string to a function that expects a number as a parameter. Check where this could be happening and you should be able to resolve the issue.

  21. Vaccu says:

    Hi Riyaz

    I fixed the error.. But i am getting the error .. when i duplicate the Node2 and Node3 and Node4..

    Runtime exception when processing target-field mapping /ns0:MT_GLAccountPosting_GE/HeaderInfo/GLInfo; root message: Exception:[java.lang.NumberFormatException: For input string: ""] in class com.sap.xi.tf._MM_GLAccountPostingIntermediate_GLPostingGE_ method nest[[Ljava.lang.String;@420357b9, [Ljava.lang.String;@6974548a, [Ljava.lang.String;@545a661c, com.sap.aii.mappingtool.tf7.rt.ResultListImpl@7ae5e387, com.sap.aii.mappingtool.tf7.rt.Context@abcf31a]

  22. Riyaz says:

    What is array sortedFunctionKeys? Check code of the UDF where this array is used. Possibly the array is not initialized or has no elements.

  23. Vaccu says:

    Hi Riyaz

    When i tried the Global Counter UDF i am getting the error..

    the length 0 of the array ‘sortedFunctionKeys’ is not equal to the number 1 of functions.

    Any idea why i am getting that..

  24. Riyaz says:

    Hey Dharmi,

    Replied to your mail. Let me know if it helps.

    Regards,
    Riyaz

    • Amol says:

      Hi Riyaz,

      Nice Blog… But Iam also facing problem similar to Dharmis problem…

      (( Dharmi
      Posted September 16, 2008 at 2:16 am | Permalink
      Riyaz,

      I can send couple of screen prints to explain the issue in a better way but I need your e-mail ID for that. please let me know.

      Thanks,
      Dharmi. ))

      What suggestion you provided to him?

      Thanks,
      Amol

  25. Dharmi says:

    Riyaz,

    I sent an e-mail to you couple of days back with details of my issue. Please let me know if you find any solution.

    Regards,
    Dharmi.

  26. Riyaz says:

    Hi Ram,

    In my case Node1 is out of the hierarchy. Only Node2, Node3 and Node4 are nested under one another. And all the three are 0..unbounded. So I guess this solves your problem.

    Let me know if I did not understand your concern correctly.

    Thanks.

    Regards,
    Riyaz

  27. Ram says:

    Hi Riyaz, Nice blog and trying to fit it for my scenerio. I am working on a scenerio for which source is mainframe file to Idoc Order05. I tried applying the above logic. It worked fine, but not exactly fit into my scenerio. My scenerio needs parent node “node1″ should be 0 to unbound.
    Node1 – Occurs 0..unbounded
    Node2 – Occurs 0..unbounded

    Can you suggest modification to your code? I appreciate your help in this regard.

    Thanks
    Ram

  28. Riyaz says:

    you can write to me at riyaz at riyaz.net

  29. Dharmi says:

    Riyaz,

    I can send couple of screen prints to explain the issue in a better way but I need your e-mail ID for that. please let me know.

    Thanks,
    Dharmi.

  30. Dharmi says:

    Riyaz,

    All the nodes are at same level. Parent node is Orders for all these nodes. My scenario is exactly like your example but I think your test data doesn’t have different occurances for the nodes. I have seen few people mentioned about XSLT mapping for these kind of issues but do you have any samples.

    Thanks,
    Dharmi.

  31. Riyaz says:

    Hi Dharmi,

    This is probably because of the way the XML is processed by XI. As I understand, you are trying to assign ID values to nodes whose parent nodes are different.

    In my case, if you observe, Node1,2,3,4 all have a common parent (Recordset) i.e. its a flat structure. So it gets processed in the correct sequence.

    If you dont have a flat structure, you can consider twicking the UDF code a bit or try using a separate copy of globalCounter function for every different outer node (In my case Recordset is the outer node). By separate copy I mean something like globalCounter1, globalCounter2,… etc.

    Hope this helps.

    Regards,
    Riyaz

  32. Dharmi says:

    Riyaz,

    Sorry, I might have explained the issue clearly. I used the globalContainer to populate the value for ID variable. I used your sample code to populate the value for ID.

    In the Input message, One of the order contains the nodes order like below
    CC,PO1,PID1,SCH1,PO2,PID2,SCH2,NTE2,PO3,PID3,SCH3

    Whne I transform the message, I am getting the following order
    CC,PO1,PO2,PO3,PID1,PID2,PID3,SCH1,SCH2,SCH3,NTE2

    Note: In the above example 1,2,3 are used just to explain the issue properly.

    As per the input message, Value of the ID element in NTE2 segment supposed to be ’8′ if it follows the correct order but because of the above issue, ID element is getting the value as ’11′. This is creating the problem while creating the IDOC in R/3. Note is getting created for a different PO.

    I hope I explained the issue but if you need more details then I can send them to your e-mail. Please provide your e-mail ID.

    Your help is greatly appreciated.

    Thanks,
    Dharmi.

  33. Riyaz says:

    Hi Dharmi,

    I could not understand the issue you are facing. From what I understand, make sure you are using a global variable to store the ID values. If the variable is local, it would behave just like the standard counter function.

    Regards,
    Riyaz

  34. Dharmi says:

    Riyaz,

    By using the above mentioned approach, I could able to create the deeply nested structures but I am getting the following issue.

    I am trying to populate data from source message type to an Intermediate message type (have an additional ID fields in few nodes). Here I am getting the following issue. Because of this issue, value of the ID field in each node is getting varied.

    Source Node loop After the Transform

    PO PO
    PID, PO
    SCH PO
    PO, PID
    PID, PID
    SCH, PID
    NTE2, SCH
    PO, SCH
    PID, SCH
    SCH NTE2

    I couldn’t find any simpler way to resolve this issue. Please suggest me if you know any.

    Thanks,
    Dharmi.

  35. Riyaz says:

    Hi Shwetambari,

    You can consider taking a reverse approach to this article to convert from deeply nested structure to a flat structure.

    Take a look at this thread for inputs.

    Regards,
    Riyaz

  36. Shwetambari says:

    Hi Riyaz,

    Your blog “XI/PI: Convert Flat File to Deeply Nested XML Structures Using Only Graphical Mapping” is really good.

    My requirement is exactly the opposite of what you explained. I.e. I need to map nested structure (4 hierarchical level) of IDOC to flat structure.
    I will really appreciate you can tell me how to achieve this.

    Regards,
    Shwetambari.

  37. Riyaz says:

    Hi Venkatesh,

    You can consider taking a reverse approach to this article to convert from deeply nested structure to a flat structure.

    Take a look at this thread for inputs.

    Regards,
    Riyaz

  38. Venkatesh says:

    Hi Riyaz,
    It looks great to me…
    I am also biginner in the SAP XI mapping…
    Actually i wanted to convert the deeply nested structure into flat structure…
    Any help in this regard will be appreciated….

    My mail id is onlyvenkatesh@gmail.com

    Regards
    Venkatesh

  39. Riyaz says:

    Hi Shilpa,

    Please go thru the explaination of functionality of nest() function explained in previous comment.

    We are working with counters here and are integers always. So fractions wont occur. Also, id of child node will always be greater than its corresponding parent node. so b will always be greater than a and c.

    Hope this helps.

    Regards,
    Riyaz

  40. Shilpa Singh says:

    Hi Riyyaz,
    Looks like you are doing a good job for beginers like me
    Can you explain me what really the nested loop in nest does, because when I look at it
    I have a feeling that X is always j+1. So anything in between will have fraction in it and it will either be truncated down to X or up to J.
    so that said
    a strictly lesser than b and c strictly greater than b will never occur…… Can you please explain me that logic or send me an email on it.

    I will appreciate your help.

    Thanks
    Shilpa

  41. Dharmendra Kumar says:

    Thank you very much for your quick and very detailed response. Looks like your fix is working fine.

    I need little more time to validate the data and to let you know the fix is working.

    Thanks again for your help.

    Dharmi.

  42. Riyaz says:

    Dharmi,

    The Nest function is designed in this way – The first argument is the list of id attributes of the node under which you want to create a child node (without any context changes), second argument is the list of id attributes of the node you want to nest under the above parent node (without any context changes) and the third argument is the list of values of the child node (again without any context changes).

    So in the above example, we have nested Node3 under Node2. Node1 does not come into picture. The nest function is applied to Node3 i.e. id attributes of Node2 is first argument, id attributes of Node3 is second argument and Node3 itself is the third argument. removeContexts() function is used to pass on a contexts free list of values and is applied to all three arguments. Node2 is mapped only with removeContexts() since it is the topmost node in the hierarchy (Note that Node 1 is out of the hierarchy and is a separate node).

    Similarly for Node4, we pass id attributes of Node3 and Node4 as first and second argument and Node4 values as third argument with removeContexts() applied to them before passing them to nest() function.

    Since Node2, Node3 and Node4 occur 0..unbounded, they can occur any number of times anywhere. So it very supports multiple occurrences. Thus for every Node2, there can be any number of Node3 nodes and for every Node3 there can be any number of Node4 nodes.

    Regards,
    Riyaz

  43. Dharmendra Kumar says:

    Riyaz,

    Thanks for your comments. In my debugging, I realised that the issue is with Nest function. I think this function designed to support the mandatory nodes (Node1, Node2, Node3 and Node4) on your source mapping and it supports one iteration only. In my case, for every Node1 we can get multiple Node2′s and for every Node2 we can get multiple Node3′s (from 0 to 10). If you have some free time can you help me in fixing the Nest function to support the above requirement. I can provide the sample data for the scenario.

    Thanks,
    Dharmi.

  44. Riyaz says:

    Hi Dharmendra,

    Cross check the Java code of your UDFs, especially check the for loops. ArrayIndexOutOfBoundsException indicates that the array is running out of bounds when you are looping through it.

    Hope this helps.

    Regards,
    Riyaz

  45. Dharmendra Kumar says:

    Riyaz,

    Blog is very descriptive and very useful. I did the Message mapping and Interface mapping exactly as you described but when I started testing the interface mapping, I am getting the following error message.

    Your response is greatly appreaciated.

    Runtime exception occurred during execution of application mapping program com/sap/xi/tf/_MM_HCLP_HDOC850_to_ORDERS05bundle_: com.sap.aii.utilxi.misc.api.BaseRuntimeException; RuntimeException in Message-Mapping transformation: Runtime exception during processing target field mapping /ORDERS05/IDOC/E1EDP01/E1EDPT1/E1EDPT2. The message is: Exception:[java.lang.ArrayIndexOutOfBoundsException: 3] in class com.sap.xi.tf._MM_HCLP_HDOC850_to_ORDERS05bundle_ method nest$[com.sap.aii.mappingtool.flib3.Plainer@c2af46, com.sap.aii.mappingtool.flib3.Plainer@18135ac, com.sap.aii.mappingtool.flib3.Plainer@1eacebf]