on 02-03-2015 2:15 PM
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
Hi Mou,
Please check your source payload for the field corresponding to the XPATH shown in error..The field doesnt seem present
Regards,
Sriram
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
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,
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
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
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
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
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
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.
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());
}
}
}
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,
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.
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.
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,
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.
Can you please provide the mappinh screen shot showing the context selected.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Mou,
Can you share whats your exisitng mapping like?
Regards,
Sriram
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
87 | |
10 | |
10 | |
9 | |
7 | |
7 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.