on 09-13-2011 5:22 PM
Hi all,
How should I code in order to navigate between different levels of a given node of the source structure?
example:
Main
Struct_11
Struct1101
Field_1101_A
Field_1101_B
Struct1102
Field_1102_A
Field_1102_B
Struct_22
Struct2201
Field_2201_A
Field_2201_B
Struct2202
Field_2202_A
Field_2202_B
In the sample above, how should I do to map the node Struct_11 and, within a UDF (or some other way, but I only imagine through a Java UDF), access and validate Struct1101-Field_1101_A, or Struct1102-Field_1102_B, etc?
If someone could provide me with a sample code, it'd help me.
Thank you!
Hello,
how should I do to map the node Struct_11 and, within a UDF (or some other way, but I only imagine through a Java UDF
In your message mapping editor, right-click Struct_11(same as what you do to set contexts) and then select Return As XML, from there, you can pass it into a UDF within the mapping.
Hope this helps,
Mark
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Mark, tks. It helped.
I could do all that I needed withing the XML working as a text.
The only problem now is that, the target structure must be built according to the source cardinality (N..N).
In the sample bellow, see that in the source structure, the Struct_11 repeat 3 times. In the 1st and 3rd, it contains the substructure Struct1101. I have to check if Struct1101 exists, if so, I have to take the Field_1101_A and validate if it's equal to WE. If yes, then the correspondent Field_1101_B has to be sent to target <row> field.
In the 2nd occurrence, there NO Struct1101, so the UDF returns #void#.
UDF to map Struct_11:
int v_pos1, v_pos2, v_start = 0;
String v_Struct1101 = "Struct1101";
String v_WE = "WE";
String v_FieldA = "<Field_1101_A>WE</Field_1101_A>";
String v_FieldB = "";
v_pos1 = Item.indexOf(v_Struct1101);
if(v_pos1 >= 0){
v_pos2 = Item.indexOf(v_FieldA);
v_start = v_pos2 + 32;
v_FieldB = Item.substring(v_start, v_start+10);
}else{
v_FieldB = "#void#";
}
return v_FieldB;
Source
<Main>
<Struct_11>
<Struct1101>
<Field_1101_A>WE</Field_1101_A>
<Field_1101_B>110</Field_1101_B>
</Struct1101>
<Struct1102>
<Field_1102_A>ZS</Field_1102_A>
<Field_1102_B>222</Field_1102_B>
</Struct1102>
</Struct_11>
<Struct_11>
<Struct1102>
<Field_1102_A>ZS</Field_1102_A>
<Field_1102_B>222</Field_1102_B>
</Struct1102>
</Struct_11>
<Struct_11>
<Struct1101>
<Field_1101_A>WE</Field_1101_A>
<Field_1101_B>112</Field_1101_B>
</Struct1101>
<Struct1102>
<Field_1102_A>ZS</Field_1102_A>
<Field_1102_B>222</Field_1102_B>
</Struct1102>
</Struct_11>
<Struct_22>
<Struct2201>
</Field_2201_A>
</Field_2201_B>
<Struct2202>
</Field_2202_A>
</Field_2202_B>
</Main>
Target
<result>
<row>110</row></result>
<result>
<row>#void#</row></result>
<result> <row>112</row></result>
<result> is mapped to <Struct_11>, so that for each <Struct_11>, one <result> is created.
I've insert this sample payload and in the Definition tab, Display Queue option shows me the right result:
110
#void#
112
However, during the MM test, it throws error:
Cannot create target element /ns0:MT_TARGET/result[2]/row. 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
Any clue?
Thank you !
Edited by: rvsilvax on Sep 14, 2011 9:00 PM
Hello,
I could do all that I needed withing the XML working as a text.
The only problem now is that, the target structure must be built according to the source cardinality (N..N).
The easiest and fastest to implement solution would be to go for a two-step mapping in your operation mapping. For the first mapping, your source and target structures are the same, but you add the node function mapWithDefault for the fields that you are checking e.g
v_FieldB -> mapWithDefault -> v_FieldB
This will ensure that v_FieldB will always be existing. The second mapping is the actual mapping (the one with return as xml).
Hope this helps,
Mark
Hi,
I feel, there is one more better option to go for XSLT mapping.
XSLT mapping is easy to navigate the different levels of the node of source structure.
Best Regards,
Sateesh
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi,
you need java mapping to meet your requirement. With DOM parser you can reach any node in the the source XML and map onto a target XML. You have not mentioned the target XML structure,mapping requirements and version of PI you working on.
Still you can refer to following articles/blogs for java mapping
http://wiki.sdn.sap.com/wiki/display/XI/ParametrizedJavaMappinginPI+7.1
http://wiki.sdn.sap.com/wiki/display/XI/BeginnersguidetoJavamappingusingDOMparserinSAPXI
regards
Anupam
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Tks Anupam.
We're running PI 7.1.
Regarding the target structure, I didn't mention because it's just a single field which must receive the result of this validation.
By the source structure I provided before, I have to mapp a main node and perform some validations in its child nodes and fields. As soon as it's validated, I'll take the corresponding field content and map to target.
Using the same example:
I'd give the <Struct_11> as the input parameter (as it contains all subnodes I need to the validations).
My Java UDF should check:
if(Struct1101-Field_1101_A == 'TCB')
{
target-field1 = Field_1101_B.
}elseif(Struct1102-Field_1102_A == 'TCB')
{
target-field1 = Field_1102_B.
}
I need it to be done in a UDF.
Tks.
Hi,
Thank you for the explanation. I have a small request , please mention all your requirements and explain them properly when you are posting in forum. By this you ensure correct answers and quick response.
Now as per your requirement, this is better done using java mapping. If you want to use only UDF try this
using message mapping for each Struct11***
Field_1101_A---------->remove context (this is input String a[] to UDF)
Field_1101_B---------->remove context (this is input String b[] to UDF)
------>UDF ------> target-field1
Field_1102_A---------->remove context (this is input String c[] to UDF)
Field_1102_B---------->remove context (this is input String d[] to UDF)
The UDF is advanced UDF using UDF type="context" as per this link http://help.sap.com/saphelp_nw04/helpdata/en/22/e127f28b572243b4324879c6bf05a0/content.htm.
Now the UDF to be written is shown below
public void MapValues(String[] a,String[] b,String[] c,String[] d,ResultList result,Container container){
String s="TCB";
if(a[0]!=null && a[0].equals(s))
{
result.addValue(b[0]);
}
else if( c[0]!=null && c[0].equals(s))
{
result.addValue(d[0]);
}
}
Hope this helps.
Just did a little change to the UDF.
regards
Anupam
Edited by: anupamsap on Sep 13, 2011 9:01 PM
User | Count |
---|---|
90 | |
10 | |
10 | |
10 | |
7 | |
7 | |
6 | |
5 | |
4 | |
3 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.