cancel
Showing results for 
Search instead for 
Did you mean: 

Mapping: Sorting nodes

Former Member
0 Kudos

Hello all,

please see below input document which should be converted to output below in PI.

Nodes //node1/item should be sorted in same order like //node2/item (identified by value of <pid>) and if item does not exist in node2 (like with pid=501 below) it should get a position at the end. //node2 should be copied 1:1.

Any ideas for this mapping in XSLT, Java Mapping or with Graphical Mapping and UDF?

Regards

Markus


Input:
<root>
  <node1>
     <item>
       <pid>201</pid>
       <name>MA</name>
       <street>
          <no>123</no>
       </street>
     </item>
     <item>
       <pid>401</pid>
       <name>MA</name>
       <street>
          <no>123</no>
       </street>
     </item>
     <item>
       <pid>501</pid>
       <name>MA</name>
       <street>
          <no>123</no>
       </street>
     </item>
     <item>
       <pid>101</pid>
       <name>MA</name>
       <street>
          <no>123</no>
       </street>
     </item>
  <node1>
  <node2>
    <item>
       <pid>101</pid>
    </item>
    <item>
       <pid>401</pid>
    </item>
    <item>
       <pid>201</pid>
    </item>
  <node2>
</root>

Output:
<root>
  <node1>
     <item>
       <pid>101</pid>
       <name>MA</name>
       <street>
          <no>123</no>
       </street>
     </item>
     <item>
       <pid>401</pid>
       <name>MA</name>
       <street>
          <no>123</no>
       </street>
     </item>
     <item>
       <pid>201</pid>
       <name>MA</name>
       <street>
          <no>123</no>
       </street>
     </item>
     <item>
       <pid>501</pid>
       <name>MA</name>
       <street>
          <no>123</no>
       </street>
     </item>
  <node1>
  <node2>
    <item>
       <pid>101</pid>
    </item>
    <item>
       <pid>401</pid>
    </item>
    <item>
       <pid>201</pid>
    </item>
  <node2>
</root>

Accepted Solutions (0)

Answers (2)

Answers (2)

markangelo_dihiansan
Active Contributor
0 Kudos

Hi Markus,

This is only achievable by using UDF. Please refer to mapping below:



for node1:

pid(node1) --> mapWithDefault:suppressed --> concat: : --> concat: : --> removeContext --> UDF1 --> node1
name --> mapWithDefault:suppressed ----------> /            /                                /
no --> mapWithDefault:suppressed ------------------------> /                                /
pid(node2) --> removeContext ------------------------------------------------------------> /

UDF1 is of CONTEXT Type, the arguments are:
Arr1
Arr2
Here is the code:
GlobalContainer globalContainer = container.getGlobalContainer(); 

String sortedArr[] = new String[Arr1.length];
String out = "";
int cnt = 0;

for(int a=0;a<Arr2.length;a++){
   for(int b=0;b<Arr1.length;b++){
      if(Arr1<b>.indexOf(Arr2[a])>-1){
        sortedArr[cnt]=Arr1<b>;
        Arr1<b> = "retrieved";
        cnt++;
       }
    }
}

for(int a=0;a<Arr1.length;a++){
   if(!Arr1[a].equals("retrieved")){
      sortedArr[cnt]=Arr1[a];
      cnt++;
   }
}

for(int a=0;a<sortedArr.length;a++){
   out += sortedArr[a] + " ";
   result.addValue(sortedArr[a]);
   }

globalContainer.setParameter("Result",out);

for pid:

Constant:PID --> mapWithDefault --> UDF2 --> SplitByValue:eachValue --> pid

for name:

Constant:NAME --> mapWithDefault --> UDF2 --> SplitByValue:eachValue --> name

for no:

Constant:NUMBER --> mapWithDefault --> UDF2 --> SplitByValue:eachValue --> no

UDF2 is of CONTEXT TYPE, input argument is: param

Here is the code for UDF2:
GlobalContainer globalContainer = container.getGlobalContainer();

String temp  = (String) globalContainer.getParameter("Result");

String arr[] = temp.split(" ");

if(param[0].equals("PID")){
   for(int a=0;a<arr.length;a++){
      result.addValue(arr[a].substring(0,arr[a].indexOf(":")));
   }}
else if(param[0].equals("NAME")){
   for(int a=0;a<arr.length;a++){
      result.addValue(arr[a].substring(arr[a].indexOf(":"),arr[a].lastIndexOf(":")));
}}
else
   for(int a=0;a<arr.length;a++){
     result.addValue(arr[a].substring(arr[a].lastIndexOf(":"),arr[a].length()));
}

Hope this helps,

Mark

former_member208856
Active Contributor
0 Kudos

Use Graphical Mapping Node function --> sort OR sortbyKey

sort

Sorts all values of the multiply-occurring inbound field I within the existing or set context. The sorting process is stable (the order of elements that are the same is not switched) and it sorts the values in O(n*log(n)) steps. Using the function properties, you can specify whether values are to be sorted numerically or lexicographically (case-sensitive or non case-sensitive) and in ascending or descending order.

sortByKey

Like sort, but with two inbound parameters to sort (key/value) pairs. The sort process can be compared to that of a table with two columns.

● Using the first parameter, you pass key values from the first column, which are used to sort the table. If you have classified the key values as numeric in the function properties, they must not be equal to the constant ResultList.SUPPRESS. See also: The ResultList Object

● Using the second parameter, you pass the values from the second column of the table.

If there is a discrepancy between the number of keys and values, the mapping runtime triggers an exception. The function returns a queue with the values sorted according to the keys.

Former Member
0 Kudos

Please have a look at my example. This will not work because:

sort: it's no numerically or lexicographically sort

sortByKey: the number of keys and values are not of same size