HI,
What is the best practice to generate XML dynamically ?
The source data is in the database.
Discussion posts and replies are publicly visible
Stewart Burchell
Thank for your reply. Please find below details :
Use Case : To generate XML dynamically from data in database.
XML Format : Plese refere belw schema
What is going to be consuming data : A variable which will be used to send this on MQ
There is a parent child tags and few levels of casting . We have already tried using toXML() and it would need around 10-15 CDTs.
Can we have another way to creae it?
Below is the sample schema :
<?xml version="1.0" encoding="utf-8"?><BaExchReq xmlns:xc=""> <Envelope> <TransactionRef>##</TransactionRef> <MsgId>##</MsgId> <CreationTime>##</CreationTime> <Requestor>##</Requestor> <Responder>c##</Responder> <Service>##</Service> <RequestType>##</RequestType> </Envelope> <Payload> <AppHdr xmlns=""> <MsgRef>##</MsgRef> <CrDate>##</CrDate> </AppHdr> <Document xmlns="##"> <SbcptOrdrV03> <MsgId> <Id>##</Id> <CreDtTm>##</CreDtTm> </MsgId> <MltplOrdrDtls> <InvstmtAcctDtls> <AcctId> <Prtry> <Id>##</Id> </Prtry> </AcctId> </InvstmtAcctDtls> <IndvOrdrDtls> <OrdrRef>##</OrdrRef> <FinInstrmDtls> <Id> <ISIN>##</ISIN> </Id> </FinInstrmDtls> <GrssAmt Ccy="">##</GrssAmt> <PhysDlvryInd>##</PhysDlvryInd> <ReqdSttlmCcy>##</ReqdSttlmCcy> </IndvOrdrDtls> </MltplOrdrDtls> </SbcptOrdrV03> </Document> </Payload> </BaExchReq>
It won't be elegant but you could assemble the message by providing a template of the message with a set of 'tokens' embedded in it that you want to be substituted with the values from your database. I don't know what the data looks like when you've retrieved it from the database but if you can coerce it into the format that I use in the following example this is how I would approach it:
Here's the XML message as a template with just the first 3 data items set as tags:
<?xml version="1.0" encoding="utf-8"?><BaExchReq xmlns:xc=""> <Envelope> <TransactionRef>###TransactionRef###</TransactionRef> <MsgId>###MsgId###</MsgId> <CreationTime>###CreationTime###</CreationTime> <Requestor>##</Requestor> <Responder>c##</Responder> <Service>##</Service> <RequestType>##</RequestType> </Envelope> <Payload> <AppHdr xmlns=""> <MsgRef>##</MsgRef> <CrDate>##</CrDate> </AppHdr> <Document xmlns="##"> <SbcptOrdrV03> <MsgId> <Id>##</Id> <CreDtTm>##</CreDtTm> </MsgId> <MltplOrdrDtls> <InvstmtAcctDtls> <AcctId> <Prtry> <Id>##</Id> </Prtry> </AcctId> </InvstmtAcctDtls> <IndvOrdrDtls> <OrdrRef>##</OrdrRef> <FinInstrmDtls> <Id> <ISIN>##</ISIN> </Id> </FinInstrmDtls> <GrssAmt Ccy="">##</GrssAmt> <PhysDlvryInd>##</PhysDlvryInd> <ReqdSttlmCcy>##</ReqdSttlmCcy> </IndvOrdrDtls> </MltplOrdrDtls> </SbcptOrdrV03> </Document> </Payload> </BaExchReq>
And here's the code that takes that template a substitutes the tags for the corresponding values:
a!localVariables( local!parameters: { {tag: "###TransactionRef###", value: "ABC123"}, {tag: "###MsgId###", value: "123a4fc4g4aa1204"}, {tag: "###CreationTime###", value: "28-08-2020 09:03"} }, fn!reduce( fn!substitute( _, _ ), ri!xmlTemplate, fn!merge( fn!index(local!parameters,"tag"), fn!index(local!parameters,"value") ) ) )
fn!reduce() is a loop that starts with an initial value - the template - and, for a provided list, runs a function - in this case fn!substitute - on that value and then takes the result and passes that to the next iteration of the provided function.
fn!merge() takes a set of lists and makes a list of those lists - in this case, takes the list of tags and list of values and pairs them up.
The underscore is a way of 'deferring' the actual value to be passed to run-time and maps the inputs to fn!substitute() to the items that follow in fn!reduce() in the order they appear.
I know: it's not intuitive but it is effective.
Note: I am assuming that the example you've provided to me is 'static' - that is, there are not any repeating elements, although the name 'MltplOrdrDtls' does suggest there may be repeating elements within it, which will be a different challenge.