Hi @aftabpÂ
Yes you can use nested calls.
So you start by generating an RSD file on each level you want to connect to.
So if you want to iterate over https://www.energinet.net/api/unit/1Afolder you will need to pull a list of folders in a call and then use it as explained in the guide.
You can get many levels in one file, so you can have unit folder and unitfolder info in the same rsd file.
Hi @aftabpÂ
Were you able to resolve the issue using the guide Thomas mentions above?
@Christian HauggaardÂ
Unfortunately, no.
I had a meeting with the vendor and asked if they could provide with custom API to which they agree.Â
Hi @aftabpÂ
What do they mean with a custom API? Is it some alternative provider and if so what does it return?
Same vendor and same system/applicationÂ
We have asked them to create a single data stream instead of multiple endpointsÂ
I haven’t gotten the endpoint yet so not sure how the data looks like.
Hi @aftabpÂ
OK, if you want a suggestion to how it can be done with two URI calls to do what you wanted.
<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="GetAllStopsModified" desc="Generated schema file." xmlns:other="http://apiscript.com/ns?v1">
<!-- You can modify the name, type, and column size here. -->
<attr name="country" xs:type="string" readonly="false" other:xPath="/json/result/entity/stops/country" />
<attr name="id" xs:type="string" readonly="false" other:xPath="/json/result/entity/stops/id" />
<attr name="lastModificationTime" xs:type="datetime" readonly="false" other:xPath="/json/result/entity/stops/lastModificationTime" />
<attr name="lastModifierUserId" xs:type="integer" readonly="false" other:xPath="/json/result/entity/stops/lastModifierUserId" />
<attr name="mobileNumber" xs:type="string" readonly="false" other:xPath="/json/result/entity/stops/mobileNumber" />
<attr name="orderNumber" xs:type="integer" readonly="false" other:xPath="/json/result/entity/stops/orderNumber" />
<attr name="products" xs:type="string" readonly="false" other:xPath="/json/result/entity/stops/products" />
<attr name="telephoneNumber" xs:type="decimal" readonly="false" other:xPath="/json/result/entity/stops/telephoneNumber" />
<attr name="tenantId" xs:type="integer" readonly="false" other:xPath="/json/result/entity/stops/tenantId" />
</api:info>
<api:set attr="urlbase" value="https://webapi.open.com/api/services/app/TransportFile"/>
<api:set attr="filein.DataModel" value="DOCUMENT" />
<api:set attr="filein.JSONPath" value="$.result.items" />
<api:set attr="filein.URITemplate" value=""urlbase]/GetAll"/>
<api:set attr="filein.ElementMapPath#" value="/json/result/items/id" />
<api:set attr="filein.ElementMapName#" value="file_id" />
<api:set attr="stopin.DataModel" value="DOCUMENT" />
<api:set attr="stopin.EnablePaging" value="TRUE" />
<api:set attr="stopin.JSONPath" value="$.result.entity.stops" />
<api:set attr="stopin.URITemplate" value=""urlbase]/GetAllStops?TransportFileId={file_id}"/>
<!-- The GET method corresponds to SELECT. Here you can override the default processing of the SELECT statement. The results of processing are pushed to the schema's output. See SELECT Execution for more information. -->
<api:script method="GET">
<api:set attr="filein.URI" value=""filein.URITemplate]"/>
<api:call op="jsonproviderGet" in="filein" out="fileout">
<api:set attr="stopin.URI" value=""stopin.URITemplate | replace('{file_id}', fileout.file_id])]"/>
<api:call op="jsonproviderGet" in="stopin" out="stopout">
<api:set attr="out.country" value=""stopout.country | allownull()]"/>
<api:set attr="out.id" value=""stopout.id | allownull()]"/>
<api:set attr="out.lastModificationTime" value=""stopout.lastModificationTime | allownull()]"/>
<api:set attr="out.lastModifierUserId" value=""stopout.lastModifierUserId | allownull()]"/>
<api:set attr="out.mobileNumber" value=""stopout.mobileNumber | allownull()]"/>
<api:set attr="out.orderNumber" value=""stopout.orderNumber | allownull()]"/>
<api:set attr="out.products" value=""stopout.products | allownull()]"/>
<api:set attr="out.telephoneNumber" value=""stopout.telephoneNumber | allownull()]"/>
<api:set attr="out.tenantId" value=""stopout.tenantId | allownull()]"/>
<api:push item="out"/>
</api:call>
</api:call>
</api:script>
</api:script>
This is how you could do it. Only for you the baseurl would be https://www.energinet.net/api the first call is urlbase]/unit to get the unit_id and then use it in a second call to get the urlbase]/unitinfo/{unit_id}
It seems like the vendor is going to take it’s time to create new endpoints. In the mean time i have started using nested call to create a RSD-file.Â
So far i have this, which workes fines:Â
<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="GetAllStops" desc="Generated schema file." xmlns:other="http://apiscript.com/ns?v1">
<!-- You can modify the name, type, and column size here. -->
<attr name="date_from" xs:type="string" readonly="false" other:xPath="/json/datasources/available-data/date_from" />
<attr name="date_to" xs:type="string" readonly="false" other:xPath="/json/datasources/available-data/date_to" />
<attr name="label" xs:type="string" readonly="false" other:xPath="/json/datasources/label" />
<attr name="name" xs:type="string" readonly="false" other:xPath="/json/name" />
<attr name="file_id" xs:type="string" readonly="false" other:xPath="/json/unit_id" />
</api:info>
<api:set attr="urlbase" value="https://my-app/api/unit"/>
<api:set attr="filein.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="filein.JSONPath" value="$." />
<api:set attr="filein.URITemplate" value="uurlbase]/20548folder"/>
<api:set attr="filein.ElementMapPath#" value="/json/unit_id" />
<api:set attr="filein.ElementMapName#" value="file_id" />
<api:set attr="stopin.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="stopin.EnablePaging" value="TRUE" />
<api:set attr="stopin.JSONPath" value="$.;$.datasources;$.datasources.available-data" />
<api:set attr="stopin.URITemplate" value="uurlbase]/file_id"/>
<api:set attr="stopin.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="stopin.EnablePaging" value="TRUE" />
<api:set attr="stopin.JSONPath" value="$.;$.datasources;$.datasources.available-data" />
<api:set attr="stopin.URITemplate" value="uurlbase]/file_id"/>
<!-- The GET method corresponds to SELECT. Here you can override the default processing of the SELECT statement. The results of processing are pushed to the schema's output. See SELECT Execution for more information. -->
<api:script method="GET">
<api:set attr="filein.URI" value="ufilein.URITemplate]"/>
<api:call op="jsonproviderGet" in="filein" out="fileout">
<api:set attr="stopin.URI" value="ustopin.URITemplate | replace('file_id', dfileout.file_id])]"/>
<api:call op="jsonproviderGet" in="stopin" out="stopout">
<api:set attr="out.file_id" value="ustopout.file_id | allownull()]"/>
<api:set attr="out.name" value="ustopout.name | allownull()]"/>
<api:set attr="out.label" value="ustopout.label | allownull()]"/>
<api:set attr="out.date_from" value="ustopout.date_from | allownull()]"/>
<api:set attr="out.date_to" value="ustopout.date_to | allownull()]"/>
<api:push item="out"/>
</api:call>
</api:call>
</api:script>
</api:script>
Now, the next step is a bit tricky.
When i am at the end-point https://my-app/api/unit/file_id i have JSON structure like this:
c
{
"unit_id": "0000building",
"name": "My building ",
},
"datasources": e
{
"type": "1",
"label": "Energy",
"links": {
"data": {
"verb": "GET",
"href": "/api/unitdata/0000building1"
}
},
"available-data": {
"date_from": "2017-01-01T00:00:00+01:00",
"date_to": "2024-02-18T23:00:00+01:00"
}
},
{
"type": "2",
"label": "Temperature",
"links": {
"data": {
"verb": "GET",
"href": "/api/unitdata/0000building2"
}
},
"available-data": {
"date_from": "1998-01-02T00:00:00+01:00",
"date_to": "2024-02-19T01:00:00+01:00"
}
},
]
How do i append the trending digit inside (href://) the following:
<api:set attr="stopin.URI" value="lstopin.URITemplate | replace('file_id', ifileout.file_id])]"/>
unit_id the same for each herf
is it also possible to lopp through multiple endpoints like this:
<api:set attr="urlbase" value="https://my-app.endpoint"/>
<api:set attr="filein.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="filein.JSONPath" value="$." />
<api:set attr="filein.URITemplate" value="[urlbase]/api/unit/20548folder"/>
<api:set attr="filein.ElementMapPath#" value="/json/unit_id" />
<api:set attr="filein.ElementMapName#" value="unit_id" />
<api:set attr="stopin.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="stopin.EnablePaging" value="TRUE" />
<api:set attr="stopin.JSONPath" value="$." />
<api:set attr="stopin.URITemplate" value="[urlbase]/api/unit/unit_id"/>
<api:set attr="filein.ElementMapPath#" value="/json/unit_id" />
<api:set attr="filein.ElementMapName#" value="file_id0" />
<api:set attr="stopin.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="stopin.EnablePaging" value="TRUE" />
<api:set attr="stopin.JSONPath" value="$." />
<api:set attr="stopin.URITemplate" value="[urlbase]/api/unit/file_id0"/>
<api:set attr="filein.ElementMapPath#" value="/json/unit_id" />
<api:set attr="filein.ElementMapName#" value="file_id" />
Â
Hi @aftabpÂ
Yes you can do multiple endpoints, each one just needs to have its own set of attributes.
That is also why I have stopin, stopout, filein and fileout. You need two for each additional call you want to make.
I got a old guide that shows this here. https://legacysupport.timextender.com/hc/en-us/articles/360052383191-Creating-and-using-RSD-files-for-CData-providers#2nestcall
You can point at href as a elementmapname# and elementmappath# and loop each href value with that.
You need to pull out the value and use it as the URI, not just a small replace, it needs to be the whole thing.
@Thomas LindÂ
Just before you posted i did try href.
The code looks like this:
<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="GetAllStops" desc="Generated schema file." xmlns:other="http://apiscript.com/ns?v1">
<!-- You can modify the name, type, and column size here. -->
<attr name="End" xs:type="string" readonly="false" other:xPath="/json/End" />
<attr name="NanoSeconds" xs:type="string" readonly="false" other:xPath="/json/NanoSeconds" />
<attr name="Start" xs:type="string" readonly="false" other:xPath="/json/Start" />
<attr name="Value" xs:type="string" readonly="false" other:xPath="/json/Value" />
<attr name="IsValueEmpty" xs:type="string" readonly="false" other:xPath="/json/IsValueEmpty" />
</api:info>
<api:set attr="urlbase" value="https://my.app"/>
<api:set attr="filein.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="filein.JSONPath" value="$.;$.datasources" />
<api:set attr="filein.URITemplate" value="=urlbase]/api/unit/0000folder"/>
<api:set attr="filein.ElementMapPath#" value="/json/datasources/links/data/href" />
<api:set attr="filein.ElementMapName#" value="href" />
<api:set attr="stopin.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="stopin.EnablePaging" value="TRUE" />
<api:set attr="stopin.JSONPath" value="$." />
<api:set attr="stopin.URITemplate" value="=urlbase]{href}"/>
<!-- The GET method corresponds to SELECT. Here you can override the default processing of the SELECT statement. The results of processing are pushed to the schema's output. See SELECT Execution for more information. -->
<api:script method="GET">
<api:set attr="filein.URI" value="=filein.URITemplate]"/>
<api:call op="jsonproviderGet" in="filein" out="fileout">
<api:set attr="stopin.URI" value="=stopin.URITemplate | replace('{href}', ,fileout.href])]"/>
<api:call op="jsonproviderGet" in="stopin" out="stopout">
<api:set attr="out.Start" value="=stopout.Start | allownull()]"/>
<api:set attr="out.End" value="=stopout.End | allownull()]"/>
<api:set attr="out.NanoSeconds" value="=stopout.NanoSeconds | allownull()]"/>
<api:set attr="out.Value" value="=stopout.Value | allownull()]"/>
<api:set attr="out.IsValueEmpty" value="=stopout.IsValueEmpty | allownull()]"/>
<api:push item="out"/>
</api:call>
</api:call>
</api:script>
</api:script>
value for herf is :/api/v/0000buildingÂ
hence URITemplate is  Âurlbase]{href} so that the URI wont get a double slash
Pagination is set to TURE
When i run it, it says
e500] Could not execute the specified command: 400 -- HTTP protocol error. 400 Bad Request.
Â
However when i set pagination to FALSE i get retuned an empty tableÂ
Dont know what i am doing wrong hereÂ
Hi @aftabpÂ
I would usually check the log to see if it shows the path that gets generated. It usually explains it.
It should generate this Uri
https://my.app/api/unitdata/0000building1/
I don’t know if that is correct or not.
@Thomas Lind
When i have pagination set to TRUE and the code finds a building without any JSON structure , TX throws an error
2024-02-20T13:50:57.571+00:00Â Â Â 2Â Â Â 137|Q-Id]Â Â Â dHTTP|Req: 386] GET https://my.app/api/unitdata/0003building1
2024-02-20T13:50:57.571+00:00Â Â Â 3Â Â Â Â137|Q-Id]Â Â Â HTTP|Req: 386] ÂNew]
Â
So i guess, the issue lies in source dataÂ
Hi @aftabpÂ
So the call is empty due to the source not existing?
I have seen that before, I can’t really remember if it was solved or how. I will see if I can find it.
The AllowNull() only works when it is a single or a few fields that are empty, not when it is all of them.
@Thomas LindÂ
There aren’t any fields at all.
The endpoint in POSTMAN returns (just) null in body.
Â
BTW
Is it possible to define somewhere in RSD to extract data from label Energy, since the following extract everything either its Energy or Temperature:
Â
<api:set attr="filein.ElementMapPath#" value="/json/datasources/links/data/href" />
{
"unit_id": "0000building",
"name": "My Building",
"datasources": "
{
"type": "1",
"label": "Energy",
"links": {
"data": {
"verb": "GET",
"href": "/api/unitdata/0000building1"
}
},
},
{
"type": "2",
"label": "Temperature",
"links": {
"data": {
"verb": "GET",
"href": "/api/unitdata/0000building2"
}
},
}
]
}
Â
Need a little help here. I have tried solving it for 2 hours now.
I am trying to create a nested statment here.Â
The columns building and county are not getting populated. The rest of the table is fine.
What am i missing.
<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="GetAllStops" desc="Generated schema file." xmlns:other="http://apiscript.com/ns?v1">
<!-- You can modify the name, type, and column size here. -->
<attr name="building" xs:type="string" readonly="false" other:xPath="dummy" />
<attr name="county" xs:type="string" readonly="false" other:xPath="dummy" />
<attr name="file_id" xs:type="string" readonly="false" other:xPath="/json/unit_id" />
<attr name="name" xs:type="string" readonly="false" other:xPath="/json/name" />
<attr name="unitinfo" xs:type="string" readonly="false" other:xPath="/json/links/info/href" />
<attr name="drilldown" xs:type="string" readonly="false" other:xPath="/json/links/drilldown/href" />
</api:info>
<api:set attr="urlbase" value="https://www.energinet.net/api/unit"/>
<api:set attr="filein.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="filein.JSONPath" value="$." />
<api:set attr="filein.URITemplate" value=""urlbase]/111111"/>
<api:set attr="filein.ElementMapPath#" value="/json/unit_id" />
<api:set attr="filein.ElementMapName#" value="file_id" />
<api:set attr="filein.ElementMapPath#" value="/json/name" />
<api:set attr="filein.ElementMapName#" value="building" />
<api:set attr="stopin.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="stopin.EnablePaging" value="TRUE" />
<api:set attr="stopin.JSONPath" value="$." />
<api:set attr="stopin.URITemplate" value=""urlbase]/file_id"/>
<api:set attr="stopin.ElementMapPath#" value="/json/unit_id" />
<api:set attr="stopin.ElementMapName#" value="file_id" />
<api:set attr="stopin.ElementMapPath#" value="/json/name" />
<api:set attr="stopin.ElementMapName#" value="county" />
<api:set attr="postin.DataModel" value="FLATTENEDDOCUMENTS" />
<api:set attr="postin.EnablePaging" value="TRUE" />
<api:set attr="postin.JSONPath" value="$.;$.links;$.links.info;$.links.drilldown " />
<api:set attr="postin.URITemplate" value=""urlbase]/file_id"/>
<api:set attr="postin.ElementMapPath#" value="/json/unit_id" />
<api:set attr="postin.ElementMapName#" value="file_id" />
<!-- The GET method corresponds to SELECT. Here you can override the default processing of the SELECT statement. The results of processing are pushed to the schema's output. See SELECT Execution for more information. -->
<api:script method="GET">
<api:set attr="filein.URI" value=""filein.URITemplate]"/>
<api:call op="jsonproviderGet" in="filein" out="fileout">
<api:set attr="stopin.URI" value=""stopin.URITemplate | replace('file_id', fileout.file_id])]"/>
<api:call op="jsonproviderGet" in="stopin" out="stopout">
<api:set attr="postin.URI" value=""postin.URITemplate | replace('file_id', stopout.file_id])]"/>
<api:call op="jsonproviderGet" in="postin" out="postout">
<api:set attr="out.building" value=""fileout.building | allownull()]"/>
<api:set attr="out.county" value=""stopout.county | allownull()]"/>
<api:set attr="out.file_id" value=""postout.file_id | allownull()]"/>
<api:set attr="out.name" value=""postout.name | allownull()]"/>
<api:set attr="out.unitinfo" value=""postout.unitinfo | allownull()]"/>
<api:set attr="out.drilldown" value=""postout.drilldown | allownull()]"/>
<api:push item="out"/>
</api:call>
</api:call>
</api:call>
</api:script>
</api:script>
Â
Hi @aftabpÂ
It is most likely one of your <api:set attr="filein.JSONPath" value="$." />
 JSONPath rows that isn’t pointing at the data.
<attr name="unitinfo" xs:type="string" readonly="false" other:xPath="/json/links/info/href" />
<attr name="drilldown" xs:type="string" readonly="false" other:xPath="/json/links/drilldown/href" />
For example you can see links/drilldown in this, which is on a lower level than $. which is equal to json/
Thank you @Thomas LindÂ
I have managed to solve it now.
I have provided different names for ElementPath name for each of the element in endpoints and changed xPath to dummy.
Â
Â