I want to convert XML response into CDT format.

I am having process model which scheduled to run after every hour and get XML response from external system and storing into text type pv.

XML data in nested CDT format.

Now, We want to read that XML file into Appian CDT. For reference i am giving below XML response.

<variable type="InputBO">
<paymentInfo type="PaymentBO">
<operationType type="String">CAPTURE</operationType>
<channelId type="String">AAA</channelId>
<paymentTypeCode type="String">BBB</paymentTypeCode>
<referenceNumber type="String">ABCD145891</referenceNumber>
<paymentAmount type="Decimal">515.0</paymentAmount>
<paymentCurrency type="String">GBP</paymentCurrency>
<paymentCardDetails type="PaymentCardDetailsBO">
</paymentInfo>
</variable>

Could you please help me to achieve this task? Thanks for your support in advance.(Appian version 18.1)

  Discussion posts and replies are publicly visible

  • Hi vinodt,

    As far as I know you can use torecord() function i.e,torecord(pv!nameXMLData,type) here type refers to type: (Any Type) Enter a variable (process variable or activity class) that has the same data type that you want the XML to be converted into..
    On a note :The XML given for the xml parameter must be valid for the XSD that was used to create the target data type.

    Thanks,
    ravalik
  • 0
    Certified Lead Developer

    Hi Vinod,

    As if now we do not have any shared component that can do it for you. There are two ways to achieve it.

    1. Use Extract each of the parameter and initialize CDT columns from that.

    2. Create a Java plugin that can parse the given pattern and return data in either JSON format or CDT type. 

  • Hi vinodt376 ,

    As Sachin Raghav (sachinr981) said there are no straight forward way to do it but you can extract each value from the xml by using xpathsnippet and set it to cdt

    Sample code can help you to achieve this

     

    load(
      local!data: toxml(
        {
          paymentInfo: {
            {
              operationType: "CAPTURE",
              channelId: "AAA",
              paymentTypeCode: "BBB",
              referenceNumber: "ABCD145891",
              paymentAmount: "515.0",
              paymentCurrency: "GBP",
              paymentCardDetails: null
            }
            
          }
        },
        true(),
        "variable",
        null
      ),
    /*  you can skip foreach if you are not dealing with multiple elements
    in case of single elements directly create type!cdt and xpathsnippet expression will be simply  */
    "/variable/*/item/operationType/text()"
    
     a!forEach(
        items: xpathsnippet(
          local!data,
          "/variable/*/*"
        ),
        expression: /* your cdt */
        {
          operationType: index(xpathsnippet(fv!item,"/item/operationType/text()"),1,null()),
          channelId:index(xpathsnippet(fv!item,"/item/channelId/text()"),1,null()),
          paymentTypeCode:index(xpathsnippet(fv!item,"/item/paymentTypeCode/text()"),1,null()),
          referenceNumber:index(xpathsnippet(fv!item,"/item/referenceNumber/text()"),1,null()),
          paymentAmount:index(xpathsnippet(fv!item,"/item/paymentAmount/text()"),1,null()),
          paymentCurrency:index(xpathsnippet(fv!item,"/item/paymentCurrency/text()"),1,null()),
          paymentCardDetails:index(xpathsnippet(fv!item,"/item/paymentCardDetails/text()"),1,null()),
        }
      )
      )

  • Thanks all for your help!!!

    @Sachin, I tried your solution and worked at some level but still looking for desired output.

    I am calling expression rule from process model and passing XML response. I am able to extract XML but in properly.

    Test Rule:
    load(
    local!data: ri!service

    a!forEach(
    items: xpathsnippet(
    local!data,
    "/variable/*/*"
    ),
    expression: /* your cdt */
    {
    operationType: index(xpathsnippet(fv!item,"/operationType/text()"),1,null()),
    channelId:index(xpathsnippet(fv!item,"/channelId/text()"),1,null()),
    paymentTypeCode:index(xpathsnippet(fv!item,"/paymentTypeCode/text()"),1,null()),
    referenceNumber:index(xpathsnippet(fv!item,"/referenceNumber/text()"),1,null()),
    paymentAmount:index(xpathsnippet(fv!item,"/paymentAmount/text()"),1,null()),
    paymentCurrency:index(xpathsnippet(fv!item,"/paymentCurrency/text()"),1,null())
    }
    )

    )

    ------------------------------------------------------
    Current Output:
    [operationType:CAPTURE,channelId:,paymentTypeCode:,referenceNumber:,paymentAmount:,paymentCurrency:]; [operationType:,channelId:AAA,paymentTypeCode:,referenceNumber:,paymentAmount:,paymentCurrency:]; [operationType:,channelId:,paymentTypeCode:AAA,referenceNumber:,paymentAmount:,paymentCurrency:]; [operationType:,channelId:,paymentTypeCode:,referenceNumber:AAAA120145891,paymentAmount:,paymentCurrency:]; [operationType:,channelId:,paymentTypeCode:,referenceNumber:,paymentAmount:515.0,paymentCurrency:]; [operationType:,channelId:,paymentTypeCode:,referenceNumber:,paymentAmount:,paymentCurrency:AAA]

    ----------------------------------------------------------------

    Passed XML response:
    <variable type="VmaadBO">
    <paymentInfo type="PaymentBO">
    <operationType type="String">CAPTURE</operationType>
    <channelId type="String">AAA</channelId>
    <paymentTypeCode type="String">AAA</paymentTypeCode>
    <referenceNumber type="String">AAA120145891</referenceNumber>
    <paymentAmount type="Decimal">515.0</paymentAmount>
    <paymentCurrency type="String">AAA</paymentCurrency>
    </paymentInfo>
    </variable>

    Should return single CDT with values. I tried without foreach. We are getting 5 rows as per looping 5 times.

    Could you please help on this. Thank you.
  • 0
    Certified Lead Developer
    in reply to Vinod Tate

    Hi Vinod,

    Please try below expression:

    type!Your_CDTName(

    operationType: extract(ri!XMLText,"String"&Char(34)&">","</operationType")[1],

    channelId:extract(ri!XMLText,"channelId type="&Char(34)&"String"&Char(34)&">","</channelId")[1],

    paymentTypeCode:extract(ri!XMLText,"paymentTypeCode type="&Char(34)&"String"&Char(34)&">","</paymentTypeCode")[1],

    referenceNumber:extract(ri!XMLText,"referenceNumber type="&Char(34)&"String"&Char(34)&">","</referenceNumber")[1],

    paymentAmount:extract(ri!XMLText,"paymentAmount type="&Char(34)&"Decimal"&Char(34)&">","</paymentAmount")[1],

    paymentCurrency:extract(ri!XMLText,"paymentCurrency type="&Char(34)&"String"&Char(34)&">","</paymentCurrency")[1]

    )

    ri!XMLText: Text type input

    Replace Your_CDTName with your CDT name. Pass complete xml text as an input ri!XMLText. Hopefully this will resolve your problem.

  • 0
    A Score Level 2
    in reply to Vinod Tate
    Hi Vinod,

    May be I didn't completely understand your requirement. Why do we need foreach here?
    Are u expecting an array of XML response in a single PV?
    <variable type="VmaadBO">
    <paymentInfo type="PaymentBO">
    <operationType type="String">CAPTURE</operationType>
    <channelId type="String">AAA</channelId>
    <paymentTypeCode type="String">AAA</paymentTypeCode>
    <referenceNumber type="String">AAA120145891</referenceNumber>
    <paymentAmount type="Decimal">515.0</paymentAmount>
    <paymentCurrency type="String">AAA</paymentCurrency>
    </paymentInfo>
    </variable>
    <variable type="VmdbBO">
    <paymentInfo type="PaymentBO">
    <operationType type="String">CAPTURE</operationType>
    <channelId type="String">BBB</channelId>
    <paymentTypeCode type="String">BBB</paymentTypeCode>
    <referenceNumber type="String">BBB120145891</referenceNumber>
    <paymentAmount type="Decimal">4152.0</paymentAmount>
    <paymentCurrency type="String">BBB</paymentCurrency>
    </paymentInfo>
    </variable>
    if not we can simply use,
    type!Your_CDTName(
    operationType:xpathsnippet(local!data,"//operationType/text()"),
    channelId :xpathsnippet(local!data,"//channelId /text()"),
    paymentTypeCode :xpathsnippet(local!data,"//paymentTypeCode/text()"),
    referenceNumber :xpathsnippet(local!data,"//referenceNumber/text()"),
    paymentAmount :xpathsnippet(local!data,"//paymentAmount/text()"),
    paymentCurrency :xpathsnippet(local!data,"//paymentCurrency/text()"
    )
  • 0
    A Score Level 1
    in reply to Vinod Tate

    vinodt376 you are almost correct just replace foreach items with below code

    xpathsnippet(local!data,"/variable/*")