Hi Thye
I recently upgraded the guide, as I found that there is a better method to do what you attempt.
https://legacysupport.timextender.com/hc/en-us/articles/360052383191-Creating-and-using-RSD-files-for-CData-providers#Nested
The idea is to make one call to get the locationId and then use it in an nested call with an replace statement. The same time I use an enum feature to use pagination as well.
Hi Thomas,
Thanks for your quick reply. First of all; thanks to the comprehensive guide. However, it's a bit overwhelming for me I think. I'm mixing up pagination with parameters, and now you introduce nested calls. Looks like the nested calls variant is more complex. Could you help me out with a sample based on the Post example, where you have two requests and you fill the {PostId} in the second query, based on the first one.
Assuming that I have two RSD's: locations and reviews. The first one contains a locationId, exactly like the PostId in the example.
1) What should I add to the location RSD? (Should I add something??)
2) What shoud I add to the review RSD?
- input parameter:
<input name="locationId" xs:type="string" other:filter="{locationId}" />
- BaseUrl mapping:
api:set attr="BaseURI" value="https://blablapi.com/{locationId}" />
- map Location in custom parameter:
>locationId] IN (SELECT locationId] FROM REST.json)
Sorry for the newbe question; like I said: I'm mixing up some things. Hope you point to the fault I'm making.
Hi Thomas,
Any idea what I'm doing wrong?
Or could you maybe post the two RSD files, used for the Post & Comments request, from your example? The new files, which are available for download, doesn't contain the 'old' example, in which you create the request for Comments ({PostId}) based on a previous request with all the postId's.
Thanks in advance!!
You should use my suggested method, but I can see you aren't doing it correctly. If you look at my guide for doing inputs, you need to call it in a different manner.
<api:script method="GET">
<api:check attr="_input.datein">
<api:set attr="URI" value="http://data.fixer.io/api/[_input.datein]?access_key=522b683569a91b66be6be214027b47bf"/>
</api:check>
<api:call op="jsonproviderGet">
<api:push/>
</api:call>
</api:script>
Hi Thomas,
Thanks for your answer. I'm almost there.
The reason we don't like the nested approach very much, is because we're shifting from SSIS to TX. In SSIS, we created several REST connections, with the fields hardcoded. Editing and managing the fields manually is something we hoped TX could do for us;)
I'm missing one part, could you help me out? The input parameter mapping is working, but it ony fetching the query once, for the first result of the previous query. How can I make sure it iterates over all the results? I've already set my custom paratmeter to (SELECT locationId FROM REST.json).
Exactly, I think that was my initial issue as well with the input method.
It might be possible if you mix the If and Page method with your input.
https://legacysupport.timextender.com/hc/en-us/articles/360052383191-Creating-and-using-RSD-files-for-CData-providers#IfandPage
So something like this.
<api:set attr="BaseURI" value="https://blablapi.com/{locationId}" />
<api:set attr="URI" value="[BaseURI]?page=[_input.rows@next]" />
Are you saying that you didn't got it working?
Is there a way that I can write output to the log? I need to iterate over the values in the locationId parameter, but when I set the custom data filter to locationId IN (SELECT ..), it no longer recognise the value. Is it even possible to pass an array as a parameter?
Hi Thomas, do you have an example of the complete RSD? As where does the _input.datein come from for example.
<api:script method="GET"><api:check attr="_input.datein"> <api:set attr="URI" value="http://data.fixer.io/api/[_input.datein]?access_key=522b683569a91b66be6be214027b47bf"/> </api:check> <api:call op="jsonproviderGet"> <api:push/> </api:call> </api:script>
I have the same as Thye has. I have 3 REST API's (json):
- GET /rest/v2/customers, output contains value of customer_id
- GET /rest/v2/locations?customer_id=1, output contains value of location_id. No api is available to get all locations at once, can only be done with mandatory parameter customer_id
- GET /rest/v2/devices?location_id=1, No api is available to get all devices at once, can only be done with mandatory parameter location_id
At the end I want to have all customers with all of their locations and devices of those locations. As a flat table or nested I don't care much. That's the next step for me.
P.S. De quality of the images on https://legacysupport.timextender.com/hc/en-us/articles/360052383191-Creating-and-using-RSD-files-for-CData-providers is too low to read unfortunately :(
This is my code right now with the gorest example api's, but still without any results.:
<api:script xmlns:api="http://apiscript.com/ns?v1" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- See Column Definitions to specify column behavior and use XPaths to extract column values from JSON. --> <api:info title="JSONData" desc="Generated schema file." xmlns:other="http://apiscript.com/ns?v1"> <attr name="id" xs:type="integer" other:xPath="dummy" /> <attr name="title" xs:type="string" other:xPath="dummy" /> </api:info> <api:set attr="UrlBase" value="https://gorest.co.in/public-api" /> <api:set attr="customerin.DataModel" value="DOCUMENT" /> <api:set attr="customerin.JSONPath" value="$." /> <api:set attr="customerin.TemplateUri" value=""urlbase]/users"/> <api:set attr="customerin.ElementMapPath#" value="/json/data/id"/> <api:set attr="customerin.ElementMapName#" value="id"/> <api:set attr="trayin.Header:Name#" value="Accept"/> <api:set attr="trayin.Header:Value#" value="application/json"/> <api:set attr="trayin.DataModel" value="DOCUMENT"/> <api:set attr="trayin.JSONPath" value="$.data"/> <api:set attr="trayin.TemplateUri" value=""urlbase]//users/{customer_id}/posts"/> <api:set attr="trayin.ElementMapPath#" value="/json/data/title"/> <api:set attr="trayin.ElementMapName#" value="title"/> <api:script method="GET"> <api:set attr="customerin.URI" value=""customerin.TemplateUri]"/> <api:call op="jsonproviderGet" in="customerin" out="customerout"> <api:set attr="trayin.URI" value=""trayin.TemplateUri | replace('{customer_id}',,customerout.id])]"/> <api:call op="jsonproviderGet" in="trayin" out="trayout"> <api:set attr="out.id" value=""customerout.id]"/> <api:set attr="out.title" value=""trayout.title | allownull()]"/> <api:push item="out" /> </api:call> </api:call> </api:script></api:script>
Hi Thomas, I have followed your example for performing nested loops, and I'm having a bit of trouble getting the nested loop to work properly with the text substitution of an ID value. If I hard code the ID, it works fine, but for some reason, the ID from the first loop is not being properly read by the nested loop. Is there any way that an RSD script can output data to a log to review issues? i feel like I'm flying blind without being able to see where data is being transformed. I'm sure that there are a lot of people that are wrestling with this process, I've wasted three days trying every possible combination of variables and values and I really need to get this working correctly as I am working with ConcurSAP REST API services.
Hi Peter
Yes, you can set up logging.
https://legacysupport.timextender.com/hc/en-us/articles/360001029663-Add-a-CData-data-source#set-up-a-log-for-extra-info
When you have the log file it will show what call it is trying to make.
You need to be sure the replace function gives the correct id and that the call for these are successfully.
Hi Thomas, doing my best to get this looping script to work correctly, but I'm afraid that ti's still an issue despite calling the correct endpoints and using the correct data substitution for the result URI. Is there an email address that I can show you how I'm doing this call and I will promise to keep it short and to the point. My relative inexperience (only 2/3 weeks) with TimeXtender is showing.
Hi Peter
You can open a support ticket by emailing support@timextender.com