Searching into 2 Recordlists in one Loop?

Hi,

I have a flow service, where I read an XML catalog file, which contains a record, which looks like:

catalog (record)

  • catalogheader (record)
    — information
  • catalogdata (record)
    — product (recordlist)
    ----- productID/*body ← string with the productID
    ----- other information
    — pricing (recordlist)
    ----- productIDref ← string which references to the productID, to which the price belongs
    ----- productPrice/amount ← string with the price

I would like to create a list which combines the information of these 2 lists looking like:
products (recordlist)

  • productID
  • other informations
  • price

I also tried to solve this problem in an output template (I’m working with SAP BC 4.6), but it was impossible to me, to get the productID when I’m in another scope. Here is the code I wrote:

<table border=1>
 %scope ProductCatalog%
  %scope CatalogData%
   %loop Product%
    <tr>
     <td>%value ProductName/*body%</td>
     <td>%value ProductID/*body%</td>
 
     %loop ../Pricing%
 
      %ifvar ProductID/*body vequals( ProductIDRef)%
       <td>%value ProductPrice/Amount%</td>
      %endifvar%
     %endloop%
    </tr>
   %endloop% 
  %endscope% 
 %endscope% 
</table>

I hope you can help me :slight_smile:

Varrius

Hi Varrius,

To do this, your code should look like:

LOOP(InArray: catalog/catalogdata/product; OutArray: products)
MAP catalog/catalogdata/product/productID/*body–> products/productID; catalog/catalogdata/product/otherInformation–> products/otherInformation

LOOP(InArray: catalog/catalogdata/pricing; OutArray: products)
MAP catalog/catalogdata/pricing/productPrice–> products/price

HTH,
Bhawesh.

Bhawesh: I think if this approach is tried, one will find that the second loop completely replaces the products out array, replacing the data from the first loop. Plus, it is probably unsafe to assume that the product and pricing lists: 1) are in the same relative order; 2) have a 1-to-1 relationship.

Flattening (or denormalizing) the product and pricing lists is going to require a bit more work. I would recommend not doing this within the dsp but have the dsp invoke a service to do the flattening and then have the dsp work with the resulting list.

Create a utility service that accepts as input the productID. The service then loops over the pricing list looking for the matching productIDRef. When found, it returns the price.

Create a main service (that the dsp invokes) that loops over the product list. The out array will be a document list containing the fields you want for each product (product ID, price, other information). For each entry, call the utility service to get the price. Map the data to temp record. Map that record to the out array list. Drop the temp record.

This results in looping through the pricing list multiple times but IMO that’s the only way this will really work (given the information at hand).

Hi Rob,
I agree with you that the approach I wrote, only works if product and pricing lists: 1) are in the same relative order; 2) have a 1-to-1 relationship.

I also agree with you of not doing this within the dsp but have the dsp invoke a service to do this flattening and then have the dsp work with the resulting list.

You wrote: “I think if this approach is tried, one will find that the second loop completely replaces the products out array, replacing the data from the first loop”

I have not found yet when the second loop replaced the data populated in the first loop, as long as the fields mapped in these 2 loops were totally different field sets.

Regards,
Bhawesh.

Thanks for the replies, but i have a problem with the mapping in the utility service reamon discribed (the lists are not in the same relative order like you mentioned).

In the mapping I created a string in which the price is copied, but the price is never in it (I stepped through the flow to test it).
How my flow works:
Loop over pricelist

Branch (evaluate-labels: true)
→ Sequence (%/catalog[0]/ProductCatalog/CatalogData/Pricing/ProductIDRef% = %ProdID%)
–>Map (/catalog[0]/ProductCatalog/CatalogData/Pricing/Amount to price)
Map (to clean the data)

Result: price is empty

edit:
Do I have to write this as a java service?
Does it matter that I used a record reference list für looping over it? Because it haven’t worked as a single record.

edit2:
I tried a little bit more to test the data, so I included the transformer pub.string:length and as input it get’s the string I’m interested in and the output is a string. But when it runs, I got the following error:
java.lang.RuntimeException: [B2BCORE.0049.9027] Error at pub.string:length - Transformers cannot loop over list elements.

Then I changed the index of the arrays to 0 in the properties of the in-mapping, but then the destination variable is “null”.

Absolutely not.

No. Is catalog a list? If so, the loop step needs to use the same index. If not, then get rid of the [0] index in the comparison.

This usually indicates that your loop statement is wrong. Can you post your service? Then we can fix it more quickly than trying to explain the basics of referring to variables.

I have never seen it work otherwise. The second loop basically says “create a new list named products.” The second loop always replaces the out-array, never updates and never appends. I will create a sample to verify. Can you create a sample that shows the behavior you describe?

Hi Rob,
I have attached a sample describing the behaviour I have noticed all along.
My IS ENV are:

Product webMethods Integration Server
Version 6.1
Updates None
Build Number 132
Java Version 1.4.2 (48.0)
Java Vendor Sun Microsystems Inc.
OS Windows 2000
OS Platform x86
OS Version 5.0
Working Dir C:\webMethods61\IntegrationServer

Regards,
Bhawesh.

Nice sample. I learned something new today! I apparently have been holding a misconception about loops for some time now–since 4.0 I think. I wonder if there was a change in behavior at some point, or if my understanding of this particular construct has just been wrong all along.

Thanks Bhawesh.

Hi Rob,
You are absolutely right. This was the behaviour till IS4.0.1. Since IS4.6, the behaviour changed and since then, I have been using this very useful construct in all the projects. It saves from many mapping steps, otherwise will be needed.

Regards,
Bhawesh.

That’s good, I’m not so bad in programming Java, but I’m very new to webMethods, so it is hard to combine it (for me).

catalog is a record reference list, but i changed it to record (tip from another forum) and now it works, without the [0] of course. There is now a small problem with the mapping, because the new record test would not show the subrecords it contains, so i have to substitute the values. Is there a possibility to change that and how does it work with lists, because i don’t know how long they are?

Thanks for your help and I’m glad to see, that someone with your experience can learn new things. But i have to learn a lot more :wink:

Edit:
I created a service where i generate a recordlist with the products, but i’m not sure, if it got the right data from the DSP. I tested the service with loading the right data in it, but later i need to send the data from the DSP to the service.
The service name is createProductList and it creates the following structure:
Products(record list)

  • Product (record)
    – Name (String)
    – ProdID (String)
    – Price (String)

The DSP i use is in another folder then the service createProductList (folder “catalog”), so i tried the following to invoke the service and use the data:

%invoke catalog:createProductList%
%loop Products%

%value Product/Name% %value Product/ProdID% %value Product/Price% %endloop% %endinvoke%

But nothing i shown so i think this is wrong or the input data is missing. The service with the output template (the DSP) has an output which is equivalent to the input of createProductList. (a record called catalog)