cancel
Showing results for 
Search instead for 
Did you mean: 

CPI Mapping N to 1 mapping

bodo_koerner
Participant
0 Kudos

Hello,
from a source like this:

...
<Tag> //is 0..* in wsdl
<F1></F1> //is 0..1 in wsdl
</Tag>
...

I want to map all the <F1> value occurences into one Target field comma separated
...
<Target>v1; v2; v3,</Target>
...

How can I do this in CPI Mapping ?

Accepted Solutions (1)

Accepted Solutions (1)

MortenWittrock
Active Contributor

Hi Bodo

You can do this easily in a user-defined function inside you message mapping. Add the following function:

def void concatQueue(String[] f1, Output output, MappingContext context) {
   output.addValue(f1.join(','))
}

Then, map the F1 source element into the function, and map the function's output to your Target element in the target structure. Set the context of the F1 element to the root element, to remove all context changes from the queue. Like this:

I used the following test input:

<?xml version="1.0" encoding="UTF-8"?>
<Source>
    <Tag><F1>A</F1></Tag>
    <Tag><F1>B</F1></Tag>
    <Tag><F1>C</F1></Tag>
    <Tag><F1>D</F1></Tag>
    <Tag><F1>E</F1></Tag>
    <Tag><F1>F</F1></Tag>
</Source>

Which gave me the following output:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Target>A,B,C,D,E,F</Target><br>

Note that the comma separator is hard-coded. You can change it in the function, or possibly add another parameter containing the desired character.

Regards,

Morten

bodo_koerner
Participant
0 Kudos

Thanks for this answer and sorry for being not precise enough.
In my case the source looks a bit different:

<Message>

<B>aaa</B>
<x>

<TAG><F1>31</F1> <F2>true</F2></TAG>
<TAG><F1>32</F1> <F2>false</F2></TAG>
<TAG><F1>10</F1> <F2>true</F2></TAG>
</x>

<C>ccc</C>

</Message>

What I need is a concatenate F1 in one target field for each occurence of F1, when F2 is "true".

Regards, Bodo


MortenWittrock
Active Contributor
0 Kudos

Hi Bodo

This is doable as well. In this case, change the function to take two queues, both F1 and F2. Then loop over the F1 values, and add them if the corresponding F2 value is "true". Here is the code:

def void filterAndConcatQueue(String[] f1, String[] f2, Output output, MappingContext context) {
    def values = []
    f1.eachWithIndex { val, index -> 
        if (f2[index] == 'true') {
            values.add(val)
        }
    }
    output.addValue(values.join(','))
}

This assumes that for each TAG element there is exactly one F1 child element and exactly one F2 child element.

Map as follows:

Again the context of both F1 and F2 must be the root element.

Regards,

Morten

bodo_koerner
Participant
0 Kudos

This is great, but in my case this always delivers only one target entry.

Regards, Bodo

MortenWittrock
Active Contributor
0 Kudos

Have you actually added the function, and changed the context of both the F1 and F2 elements to the root element?

Regards,

Morten

bodo_koerner
Participant
0 Kudos

Yes, I added the function with both F1 and F2, but from the source with 3 source Elements <Tag> only the first value of F1 is taken to the single target field.

Regards, Bodo

MortenWittrock
Active Contributor
0 Kudos

Did you change the context of the F1 and F2 fields? If not, the result will be what you describe.

Select the top-most value in the list of contexts.

Regards,

Morten

bodo_koerner
Participant
0 Kudos

Yes thanks, that was the reason.
After changing the context of the source field to a higher level it worked as requested.
Verry helpful answer.

Regards, Bodo

MortenWittrock
Active Contributor
0 Kudos

Great, glad to hear it. Since your question was answered correctly, I'd appreciate it if you would accept the answer.

Regards,

Morten

Answers (0)