Dynamic XML generation

HI,

What is the best practice to generate XML dynamically ?

The source data is in the database.

  Discussion posts and replies are publicly visible

Parents
  • 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.

Reply
  • 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.

Children
No Data