XI/PI: Convert Flat File to Deeply Nested XML Structures Using Only 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.

This entry was posted in SAP, SAP XI / PI and tagged , , , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
Around the Web »»

48 Comments

  1. Dharmendra Kumar
    Posted July 16, 2008 at 1:31 am | Permalink

    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]

  2. Posted July 16, 2008 at 10:30 am | Permalink

    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

  3. Dharmendra Kumar
    Posted July 16, 2008 at 7:46 pm | Permalink

    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.

  4. Posted July 17, 2008 at 9:37 am | Permalink

    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

  5. Dharmendra Kumar
    Posted July 18, 2008 at 2:38 am | Permalink

    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.

  6. Shilpa Singh
    Posted July 19, 2008 at 8:49 pm | Permalink

    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

  7. Posted July 21, 2008 at 9:39 am | Permalink

    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

  8. Venkatesh
    Posted July 28, 2008 at 11:36 am | Permalink

    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

  9. Posted July 28, 2008 at 12:43 pm | Permalink

    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

  10. Shwetambari
    Posted August 25, 2008 at 2:01 pm | Permalink

    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.

  11. Posted August 25, 2008 at 2:17 pm | Permalink

    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

  12. Dharmi
    Posted September 12, 2008 at 12:58 am | Permalink

    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.

  13. Posted September 12, 2008 at 10:51 am | Permalink

    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

  14. Dharmi
    Posted September 12, 2008 at 7:24 pm | Permalink

    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.

  15. Posted September 15, 2008 at 5:43 pm | Permalink

    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

  16. Dharmi
    Posted September 15, 2008 at 7:02 pm | Permalink

    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.

  17. 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.

  18. Posted September 16, 2008 at 5:38 pm | Permalink

    you can write to me at riyaz at riyaz.net

  19. Ram
    Posted September 16, 2008 at 9:44 pm | Permalink

    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

  20. Posted September 17, 2008 at 6:09 pm | Permalink

    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

  21. Dharmi
    Posted September 18, 2008 at 11:40 pm | Permalink

    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.

  22. Posted September 19, 2008 at 3:45 pm | Permalink

    Hey Dharmi,

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

    Regards,
    Riyaz

  23. Vaccu
    Posted October 10, 2008 at 4:19 am | Permalink

    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. Posted October 10, 2008 at 2:22 pm | Permalink

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

  25. Vaccu
    Posted October 10, 2008 at 9:34 pm | Permalink

    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]

  26. Posted October 10, 2008 at 10:35 pm | Permalink

    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.

  27. Aaron
    Posted April 1, 2009 at 1:04 am | Permalink

    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

  28. Deepika
    Posted July 8, 2009 at 2:42 pm | Permalink

    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

  29. Posted July 8, 2009 at 4:33 pm | Permalink

    Thats very much possible. See my reply here.

  30. Amol
    Posted July 14, 2009 at 5:30 pm | Permalink

    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

  31. Amol
    Posted July 14, 2009 at 9:31 pm | Permalink

    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

  32. Posted July 16, 2009 at 8:45 am | Permalink

    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.

  33. Amol
    Posted July 16, 2009 at 2:48 pm | Permalink

    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

  34. Amol
    Posted July 21, 2009 at 8:24 pm | Permalink

    Hi Riyaz
    Please let me know your inputs. Thanks.

  35. Posted July 25, 2009 at 4:30 pm | Permalink

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

  36. Posted October 31, 2009 at 1:32 am | Permalink

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

  37. Vishnu
    Posted February 8, 2010 at 12:53 pm | Permalink

    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

  38. Posted February 9, 2010 at 12:57 pm | Permalink

    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.

  39. Abhay
    Posted April 24, 2010 at 10:29 pm | Permalink

    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.

  40. Posted April 26, 2010 at 2:19 pm | Permalink

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

  41. Abhishek Mathur
    Posted July 23, 2010 at 12:45 am | Permalink

    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

    • Posted July 23, 2010 at 10:31 am | Permalink

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

      • Neha Rai
        Posted August 6, 2010 at 6:03 pm | Permalink

        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.

        • Posted August 6, 2010 at 6:21 pm | Permalink

          off course the first one is correct

          • Neha Rai
            Posted August 6, 2010 at 6:36 pm | Permalink

            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

  42. Neha Rai
    Posted August 6, 2010 at 1:11 pm | Permalink

    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

  43. Posted August 6, 2010 at 2:43 pm | Permalink

    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.

  44. Posted August 6, 2010 at 8:18 pm | Permalink

    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.

One Trackback

  1. [...] segregate and group source data from flat structure to deeply nested structure and vice versa. Achieving this using graphical mapping is possible, however would take more development [...]

Post a Comment

Login with your Facebook or Twitter Account to comment. Alternatively, please fill in the fields marked *.

.

Connect with Facebook

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

CommentLuv Enabled

Subscribe without commenting

GetSocial