cancel
Showing results for 
Search instead for 
Did you mean: 

Mapping structure flat file with neasted structure

Former Member
0 Kudos

Hi all,

I have a flat file  having this structure :

BKPFfield1field2

BSEGfield3fial4 ( 1 unbounded)

BSEGfield5field6

BTAXfield7field8

and the target structure I WANT TO GET : 

BKPF

      BSEG

      BSEG

           BTAX

How could we make the mapping of the different structure??

Cordialy

Accepted Solutions (0)

Answers (6)

Answers (6)

Former Member
0 Kudos

Hi Mou,

Please check your source payload for the field corresponding to the XPATH shown in error..The field doesnt seem present

Regards,

Sriram

Former Member
0 Kudos

Hi,

These are the mapping of nodes :

Cordialy

Former Member
0 Kudos

Hi Mou,

You will face an issue for the 2nd and third node i believe. The first mapping can be direct. For 2nd and 3rd node screen shot provided is not complete. Please provdie complete screen shot of the node further to BBSEG and required mapping seperately.

Regards,

Sriram

Former Member
0 Kudos

Hi,

THis is the complete mapping that I did.Fields of 'PieceCompta' are the same of BSEG: ( I made a direct mapping. Same thing with TVAPiece with BTAX the two structures contain the same fields and they are mapped directly.

The probleme is the mapping of Nodes ( EntetePiece' wwith BKPF, 'PieceCompta' with BBSEG and 'TVAPiece' with BBTAX.

Cordialy

Former Member
0 Kudos

Hello Mou,

Is it that the BTAX should always be under the second BSEG? Or is there any condition attached to identify BTAX corresponding to the required BSEG?

regards,

Diptee

Former Member
0 Kudos

Hello,

It's not necessery that BTAX should be under the second BSEG. This is an exemple :

The flat strcture :

EntetePiece

PieceCompta

PieceCompta

PieceCompta

TVAPiece

PieceCompta

TVAPiece

In this case I should get :

BKPF

   BSEG

   BSEG

   BSEG

        BTAX ( The btax is attached now to the 3 rd BSEG)

   BSEG

        BTAX

Cordialy,

Former Member
0 Kudos

Hello Mou,

As TVAPiece is supposed to correspond to a PieceCompta and your source datatype does not match this, I believe you can create an intermediate structure which creates a nested structure like below

EntetePiece

PieceCompta

TVAPiece

PieceCompta

TVAPiece

PieceCompta

  TVAPiece

And then, map this to the required output structure. Let me know if you need help with this.

BR,

Diptee

Former Member
0 Kudos

Hi,

Thank you for response.I didn't understund how to create an intermediate Structure, and map it with the output deep structure ??

Thank you for your help,

Cordialy

Former Member
0 Kudos

Hello Mou,

You can refer to the below for the intermediate structure that you would need, alongwith the mapping logic.

Please note, only the field TVAPiece needs a SplitByValue others may be mapped one-to-one.

Below are the results of the test of this mapping with the sample data you provided earlier.

Post this you may create another mapping from the intermediate structure to the actual target structure which would be a one-to-one mapping.

BR,

Diptee

Former Member
0 Kudos

Hi,

THis is the result that I get :

The first three BSEG contains each one BTAX witch is not correct.

I should get :

BSEG

BSEG

BSEG

   BTAX

BSEG

BTAX

BSEG

BTAX

Now I get :

BSEG

    BTAX

BSEG

   BTAX

BSEG

  BTAX

BSEG

BSEG

Any idea?

Cordialy

Former Member
0 Kudos

Hello Mou,

Have you created 2 mappings? and is this the output of the second one? What I am trying to say is as below, create 2 message mappings

mapping one - from your source structure to the intermediate structure I have shown as target structure in screenshots - mapping logic as per screenshot

mapping two - from the intermediate structure to your target structure - mapping logic one-to-one.

It will be after the second mapping that you will have the required output.

BR,

Diptee

Former Member
0 Kudos

Hi,

How can I handle the two message mapping ( Message 1 from source to intermediate)

( Message 2, from the intermediate to target).Because the two messages mapping will be independant.

Cordialy,

Former Member
0 Kudos

I have to mapp the result of the intermediate strcture with my target structure one-to-one.I don't know how to do this with two separate message mapping .

Thank you

Former Member
0 Kudos

Hello Mou,

You will need to add both message mappings to one operation mapping.

BR,

Diptee

Former Member
0 Kudos

Hello Mou,

To put the pieces above together, You can follow the below steps

1. Create 3 datatypes

   - your source

   - intermediate I gave

   - your target

2. Create message types for each of the above

3. Create 2 service interfaces

   - for your source message type

   - for your target message type

4. Create 2 message mappings

   - your source to my intermediate

   - my intermediate to your target

5. Create 1 operation mapping

    - Add the SIs you created in step 3 as source and target respectively

    - Add the message mappings created, in the same sequence in which they are mentioned above

6. Run your test on the operation mapping.

BR,

Diptee

Former Member
0 Kudos

Hi,

Thank you so much for your help.I always get the BTAX structure not in the correct position.

I get

BSEG

    BTAX

BSEG

   BTAX

BSEG

  BTAX

BSEG

BSEG

Insted of

BSEG

BSEG

BSEG

   BTAX

BSEG

    BTAX

BSEG

    BTAX

Cordialy

Former Member
0 Kudos

The BSEG structure should be mapped directly with BSEG in intermediate structure ?? Knowing  that BSEG is contained into BKPF

Cordialy

former_member182412
Active Contributor
0 Kudos

Hi mou merou,

Is there any common field available in both PieceCompta and TVPiece to link the both nodes, if you have let me know and provide me the source xml also.

Regards,

Praveen.

Former Member
0 Kudos

Hi,

No there is no Common fields in two structures.

Former Member
0 Kudos

Hello Mou,

I did realize a flaw in the solution I told you about. I believe we will need a custom mapping code like XSLT to help here. The logic would be as below

for each EntetePiece in source structure and create a BKPF for it

     for each PieceCompta structure in source create a BSEG

     loop until next EntetePiece

         check current node isTVPiece

            if yes, create a BTAX

        endloop

        add contextChange

     end for each

end for each

I am afraid I do not have the bandwidth to give you the actual code, may be any experts can help here.

BR,

Diptee

Former Member
0 Kudos

Hi,

Thank you, Yes this is the algorithm that we need.we could not do this only using node functiong in message mapping ??

Cordialy

former_member182412
Active Contributor
0 Kudos

Hi Mou Merou,

You can do this using two UDF's

This UDF for BTAX node:


public void mapBTAXNode(String[] entetePieceXML, ResultList result, Container container) {

        InputStream inputStream = new ByteArrayInputStream(entetePieceXML[0].getBytes());

        try {

            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);

            NodeList nodes = document.getDocumentElement().getChildNodes();

            String currentNode = "", previousNode = "";

            for (int i = 0; i < nodes.getLength(); i++) {

                Node node = nodes.item(i);

                if (node.getNodeType() == Node.ELEMENT_NODE) {

                    currentNode = node.getNodeName();

                    if (previousNode.equals("PieceCompta") && currentNode.equals("TVAPiece")) {

                        result.addValue("");

                    } else if (previousNode.equals("PieceCompta") && currentNode.equals("PieceCompta")) {

                        result.addValue(ResultList.SUPPRESS);

                    }

                    previousNode = currentNode;

                }

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

This UDF is for under BTAX Field:


    public void mapBTAXField(String[] tvaPiece, String[] tvaPieceField, ResultList result, Container container) {

        int index = 0;

        for (int i = 0; i < tvaPiece.length; i++) {

            if (tvaPiece[i].equals(ResultList.SUPPRESS)) {

                result.addSuppress();

            } else {

                result.addValue(tvaPieceField[index]);

                index++;

            }

        }

    }

    }

The above image for BTAXNode mapping using mapBTAXNode UDF. The first field EntetePieceData you must select return as XML.

The below image is for field under BTAX node using two UDF's, First UDF is mapBTAXNode second UDF is mapBTAXField in below image and TVAPiece field context is EntetePieceData (root node for PieceCompta and TVAPiece), The first field EntetePieceData you must select return as XML.

My structure look like below:

Make sure you add these imports for UDF's under Import Instructions tab:

I tested from my side and it is working, please test from your side and let me know.

I hope the problem is solved.

Regards,

Praveen.

Former Member
0 Kudos

Hi,

Thank you for youtr help. This is the result that I get :

I didn't get any BTAX node :

Your EntetePieceData is for me ' MTCYLVEN_Cly', The PieceCompa is mapped directly with BSEG and BKPF with EntetePece. For BTAX I did Exactly what you said.

Cordialy

former_member182412
Active Contributor
0 Kudos

Hi Mou,

When you pass the field MTCYLVEN_Cly to UDF did you select the field as return as XML? send me your BTAXNode and one of the field under BTAX node mapping screen shots so that i can see what went wrong.

Regards,

Praveen.

Former Member
0 Kudos

Hi,

Thank you so much for your help. Yes I did'nt select the field as return XML.

Now I am facing two problems:

1: After the 3 TVAPiece I didn't Get the result mapped :

2: When I add an Other 'EntetePiece', all 'BSEG' fields are under the first BKPF :

Thank you,

Cordialy

RaghuVamseedhar
Active Contributor
0 Kudos

Mou,

You have mentioned that there is no common field in EntetePiece, PieceCompta and TVAPiece. In that case, this transformation can not be achieved using Graphical mapping.

Please use below Java Mapping. After Java mapping add another graphical mapping which will be one-to-one mapping. i.e., In operational mapping, point to Java mapping and then Graphical mapping.

Screenshot of Input and output of Java mapping is attached.

Java Mapping: -


package com.map;

import com.sap.aii.mapping.api.*;

import java.io.*;

import javax.xml.parsers.*;

import javax.xml.transform.*;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import javax.xml.xpath.*;

import org.w3c.dom.*;

public class Transform_JavaMapping extends AbstractTransformation {

    @Override

    public void transform(TransformationInput transformationInput, TransformationOutput transformationOutput) throws StreamTransformationException {

        try {

            InputStream inputstream = transformationInput.getInputPayload().getInputStream();

            OutputStream outputstream = transformationOutput.getOutputPayload().getOutputStream();

            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputstream);

            XPath xPath = XPathFactory.newInstance().newXPath();

            //Move TVAPiece under PieceCompta

            NodeList PieceCompta = (NodeList) xPath.evaluate("//PieceCompta", document.getDocumentElement(), XPathConstants.NODESET);

            for (int i = 0; i < PieceCompta.getLength(); i++) {

                while (1 == 1) {

                    Node nextSib = PieceCompta.item(i).getNextSibling();

                    if (nextSib == null || nextSib.getNodeName().equals("EntetePiece") || nextSib.getNodeName().equals("PieceCompta")) {

                        break;

                    } else {

                        PieceCompta.item(i).appendChild(nextSib);

                    }

                }

            }

            //Move PieceCompta under EntetePiece

            NodeList EntetePiece = (NodeList) xPath.evaluate("//EntetePiece", document.getDocumentElement(), XPathConstants.NODESET);

            for (int i = 0; i < EntetePiece.getLength(); i++) {

                while (1 == 1) {

                    Node nextSib = EntetePiece.item(i).getNextSibling();

                    if (nextSib == null || nextSib.getNodeName().equals("EntetePiece")) {

                        break;

                    } else {

                        EntetePiece.item(i).appendChild(nextSib);

                    }

                }

            }

            //Write to outputStream.

            TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(outputstream));

        } catch (Exception exception) {

            getTrace().addDebugMessage(exception.getMessage());

            throw new StreamTransformationException(exception.toString());

        }

    }

}

Former Member
0 Kudos

Hi,

Thak you for your response. The source Structure is flat structure as you mentiend. The target one, is already a deep structure . So I have :

Source :                                  Target:

EntetePiece                       EntetePiece

PiceCompta                              PieceCompta

TVAPiece                                        TVAPiece

The problme how could we map these structure .

As exemple I could have in my source

EntetePiece

PieceCompta

PieceCompta

PieceCompta

TvaPiece

PieceCompa

EntetePice

PieceCompta

The result should be :

EntetePiece

     PieceCompta

     PieceCompta

     PieceCompta

          TvaPiece

     PieceCompa

EntetePice

     PieceCompta

How could we achieve This result ??

Cordialy,

RaghuVamseedhar
Active Contributor
0 Kudos

Mou,

Please implement  above mentioned solution. Please check above screenshot attachment.

former_member182412
Active Contributor
0 Kudos

Hi Mou,

Please use the below UDF mapBTAXNode instead of previous two UDF's.


public void mapBTAXNode(String[] entetePieceXML, ResultList result, Container container) {

        InputStream inputStream = new ByteArrayInputStream(entetePieceXML[0].getBytes());

        try {

            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);

            NodeList nodes = document.getDocumentElement().getChildNodes();

            String currentNode = "", previousNode = "";

            int entetePieceCount = 0;

            for (int i = 0; i < nodes.getLength(); i++) {

                Node node = nodes.item(i);

                if (node.getNodeType() == Node.ELEMENT_NODE) {

                    currentNode = node.getNodeName();

                    if (currentNode.equals("EntetePiece")) {

                        entetePieceCount++;

                        if (entetePieceCount != 1) {

                            result.addContextChange();

                        }

                    } else if (previousNode.equals("PieceCompta") && currentNode.equals("TVAPiece")) {

                        NodeList tvaNodes = node.getChildNodes();

                        for (int j = 0; j < tvaNodes.getLength(); j++) {

                            Node tvaNode = tvaNodes.item(j);

                            if (tvaNode.getNodeType() == Node.ELEMENT_NODE) {

                                result.addValue(tvaNode.getTextContent());

                            }

                        }

                    } else if (previousNode.equals("PieceCompta") && currentNode.equals("PieceCompta")) {

                        result.addValue(ResultList.SUPPRESS);

                    }

                    previousNode = currentNode;

                }

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

Use above mapping for BTAX node, field under BTAX node (BTAX1 in the image) and BSEG node. The input for UDF is your root node and select return as xml.

Regards,

Praveen.

Former Member
0 Kudos

Hi,

Should I do this mapping for all fields of BTAX node ? for BSEG field I use a direct mapping ??

Cordialy,

Former Member
0 Kudos

I Get this error :

former_member182412
Active Contributor
0 Kudos

Hi Mou,

Send me your sender and receiver XSD's and give me your sender xml which you testing so that i can clearly see what went wrong because my structure and your structures are different so i want work on your structure.

Regards,

Praveen.

Former Member
0 Kudos

Hello,

THese are sender and reciever XML :

former_member182412
Active Contributor
0 Kudos

Hi Mou,

Thanks for the XSD's can you please also send me the test payload which you testing (source xml).

Regards,

Praveen.

Former Member
0 Kudos

Hi,

This is my test source :

Cordialy

Former Member
0 Kudos

Any suggestion?

Thank you for your help

Cordialy

former_member182412
Active Contributor
0 Kudos

Hi Mou,

Use below two UDF's.


public void mapBTAXNode(String[] entetePieceXML, ResultList result, Container container) {

        InputStream inputStream = new ByteArrayInputStream(entetePieceXML[0].getBytes());

        try {

            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);

            NodeList nodes = document.getDocumentElement().getChildNodes();

            String currentNode = "", previousNode = "";

            int entetePieceCount = 0;

            for (int i = 0; i < nodes.getLength(); i++) {

                Node node = nodes.item(i);

                if (node.getNodeType() == Node.ELEMENT_NODE) {

                    currentNode = node.getNodeName();

                    if (currentNode.equals("EntetePiece")) {

                        entetePieceCount++;

                        if (entetePieceCount != 1) {

                            result.addContextChange();

                        }

                    } else if (previousNode.equals("PieceCompta") && currentNode.equals("TVAPiece")) {

                        result.addValue("");

                    } else if ((previousNode.equals("PieceCompta") && currentNode.equals("PieceCompta"))

                            || (previousNode.equals("EntetePiece") && currentNode.equals("PieceCompta") && entetePieceCount != 1)

                            && i == nodes.getLength() - 1) {

                        result.addValue(ResultList.SUPPRESS);

                    }

                    previousNode = currentNode;

                }

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }


public void mapBTAXField(String[] tvaPiece, String[] tvaPieceField, ResultList result, Container container) {

        int index = 0;

        for (int i = 0; i < tvaPiece.length; i++) {

            if (tvaPiece[i].equals(ResultList.SUPPRESS)) {

                result.addSuppress();

            } else {

                result.addValue(tvaPieceField[index]);

                index++;

            }

        }

    }

Use below mapping for BTAX and BSEG node, remember to your root node you need to pass it to UDF and return as XML.

Use below same mapping for all the fields under BTAX node, the STYPE field context is root node. First UDF is mapBTAXNode and second UDF is mapBTAXField in the below screen shot.

Let me know the update.

Regards,

Praveen.

Former Member
0 Kudos

Hi,

Thank you for your response.

I made two tests. The first one using one' EntePiece', this is the result :

The last BTAX dosn't contain any result.

The second test : Using 2 EntetePiece:

The last Btax of my first BKPF dosn't contain any result. and the second BKPF dosn't contain the BSEG nod.

I add that , in function that you gave me, the 'execution typae' I made ' All value of queue', and 'MTCYLVEN_Cly' I return as XML.

Cordialy,

former_member182412
Active Contributor
0 Kudos

Both UDF's are execution type is "All Values of Context", please change it and test it.

Former Member
0 Kudos

Hi,

I get this error when using 'All values of Contexte' :

Cordialy,

Former Member
0 Kudos

Hi,

Any solution ??

Cordialy

Former Member
0 Kudos

Hi,

How can I implement the Java mapping ??, i GET THE ERROR THAT         class AbstractTransformation is not available in the software component version.

i Didn't find the jar that I have to include, I don't have acces to server.

Cordialy,

former_member182412
Active Contributor
0 Kudos

Hi Mou,

In the STYPE mapping when you pass STYPE field mapBTAXField UDF, STYPE field context you need to set to MTCYLVEN_Cly, you need to do this for all the fields under BTAX node.

Regards,

Praveen.

Former Member
0 Kudos

Hi,

Thank you, Now I have Only one problem, is when I add an other EntetePiece. I get Only one BKPF.BSEG of the second BKPF is used under the first BKPF.

Cordialy,

Former Member
0 Kudos

Hi,

What I see is, in the second BKPF created, only BSEG that are folowed by BTAX are created.If BSEG is not folowed by a BTAX, the node is not created.

Cordialy,

former_member182412
Active Contributor
0 Kudos

Hi Mou,

Send me screen shots for BSEG, BTAX and one of the field under BTAX node. It should work because i tested with your structure and your source xml.

Regards,

Praveen.

Former Member
0 Kudos

Hi,

Using my Source XML, did you get the BSEG node under the second BKPF node ?? Because for me I didn't get it.

Cordialy

former_member182412
Active Contributor
0 Kudos

Hi Mou,

Please change the mapBTAXNode UDF like below, please include org.w3c.dom.Element in imports section of UDF.


    public void mapBTAXNode(String[] entetePieceXML, ResultList result, Container container) {

        InputStream inputStream = new ByteArrayInputStream(entetePieceXML[0].getBytes());

        try {

            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);

            NodeList nodes = document.getDocumentElement().getChildNodes();

            int entetePieceCount = 0;

            for (int i = 0; i < nodes.getLength(); i++) {

                Node node = nodes.item(i);

                if (node.getNodeType() == Node.ELEMENT_NODE) {

                    if (node.getNodeName().equals("EntetePiece")) {

                        entetePieceCount++;

                        if (entetePieceCount != 1)

                            result.addContextChange();

                    } else if (node.getNodeName().equals("PieceCompta")) {

                        Node sibling = node.getNextSibling();

                        while (!(sibling instanceof Element) && sibling != null) {

                            sibling = sibling.getNextSibling();

                            if (sibling == null || !sibling.getNodeName().equals("TVAPiece"))

                                result.addSuppress();

                            else

                                result.addValue("");

                        }

                    }

                }

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

I have tested from my side with your xml and it is working.

Regards,

Praveen.

Former Member
0 Kudos

Hi,

Thank you so much for your help. It's work fine.

Cordialy

Former Member
0 Kudos

Can you please provide the mappinh screen shot showing the context selected.

Former Member
0 Kudos

Hi Mou,

Can you share whats your exisitng mapping like?

Regards,

Sriram

Former Member
0 Kudos

Hi,

I made a direct maping :

EntetePiece with BKPF

PieceCompta with BSEG

TVAPiece with BTAX

But this dosen't work, I didn't get the correct result

Regards

RaghuVamseedhar
Active Contributor
0 Kudos

Mou,

Please try

Step 1: FCC to convert flat file to XML. BSEG and BTAX will come at same level.

Step 2: In graphical mapping move corresponding BTAX under BSEG. Please see grouping example in my blog

Former Member
0 Kudos

Hi Mou,

You need to define the source and target structures as required. U can use graphical mapping if structures are simple and achieve this or if its too complex, may be go for XSLT/Java.

Regards,

Sriram

Former Member
0 Kudos

You may use appropriate node functions in graphical mapping and select appropriate contexts.

Let me know if you have any query. Also wud be great if u can put in the actual structures.

Former Member
0 Kudos

Hi,

Thank you for your response.I have defined the structures as required. But as a result I get the " BTAX" structures into the first BSEG structure. ( I have get the BTAX according to the exemple into the second BSEG).

Any idea how to make this mmaping og BSEG and BTAX structures??

Cordialy

Former Member
0 Kudos

This is the flat structue :

The deep structure :

'EntetePiece' should be mapped with BBKPF strcture, PieceCompta with BBSEG, and TVAPIECE with BBTAX wich is contained into  BBSEG structure.

Cordialy