locked
Map node elements as key value pairs ? RRS feed

  • Question

  • I have a xml message as :

    <Cashflows>

    <Cashflow>

    <NotionalAmount>10.0</NotionalAmount>

    <Position>1</Position>

    <Amount>100.0</Amount>

    <Currency>USD</Currency>

    ....

    ...And few more elements

    </Cashflow>

    <Cashflow>...data elements </Cashflow>

    <Cashflow>...data elements </Cashflow>

    </Cashflows>

    The destination wants it as KeyValue pair like

    <Cashflows>

    <Cashflow>

    <Data name="NotionalAmount" value="10.0">

    <Data name="Position" value="1">

    <Data name="Amount" value="100.0">

    ....

    </Cashflow>

    ...

    ...

    </Cashflows>

    If in input record Position is 0 then an additional cashflow is needed with same data elements but NotionalAmount would be set as 0.


    Sunday, October 16, 2016 9:49 AM

Answers

  • Hi Issel_D,

    There are couple of ways you can get this:

    1. If you want to use mapper what you can do is 

      a. Create a same schema like your input and have another repeating node with cashflow elements . call it say <DuplicateCashflow/>

    MAP1:

     b. Map ur input to the new schema where u map all cashflow to cashflow and based on the condition of Position=0 map cashflow to DuplicateCashflow

    MAP2:

     c. Take this new input with cashflow and duplicatecashflow and map to another message that is same as your original message schema. This way u now have all cashflow and duplicatecashflow under cashflow node.

    MAP3:

     d. Map this new message to name value pair based on the link that Mandar has suggested.

    2. You can use xsl in the map to achieve the required output in 1 Map instead of 3. Efficient.

    I have this based on each element however you can even have this generic on element name and value and then if there are additions or removal of elements you wont have to touch the map.

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" encoding="utf-8" indent="no" />
        <xsl:template match="/Cashflows">
            <Cashflows>
                <xsl:for-each select="Cashflow">
                    <Cashflow>
                        <xsl:call-template name="cashflow">
                            <xsl:with-param name="notional" select="NotionalAmount/text()" />
                        </xsl:call-template>
                    </Cashflow>
                    <xsl:if test="Position/text()='0'">
                        <Cashflow>
                            <xsl:call-template name="cashflow">
                                <xsl:with-param name="notional" select="'0'" />
                            </xsl:call-template>
                        </Cashflow>
                    </xsl:if>
                </xsl:for-each>
            </Cashflows>
        </xsl:template>
        <xsl:template name="cashflow">
            <xsl:param name="notional" />
            <xsl:element name="Data">
                <xsl:attribute name="name">NotionalAmount</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="$notional" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">Position</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="Position/text()" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">Amount</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="Amount/text()" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">Currency</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="Currency/text()" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">Date</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="Date/text()" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">PayDate</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="PayDate/text()" />
                </xsl:attribute>
            </xsl:element>
        </xsl:template>
    </xsl:stylesheet>

    Pi_xel_xar

    Blog: My Blog

    BizTalkApplicationDeploymentTool: BizTalk Application Deployment Tool

    LinkedIn: LinkedIn

    • Marked as answer by Issel_D Monday, October 17, 2016 7:12 AM
    Sunday, October 16, 2016 4:41 PM
    Answerer

All replies

  • Hi Issel_D,

    I believe the article from Sandro Can help you get started. Refer

    BizTalk Mapper Patterns: How to Map Hierarchical Schema to a Name Value Pair

    Regards,


    Mandar Dharmadhikari

    Sunday, October 16, 2016 2:52 PM
    Moderator
  • Hi Mandar, Thanks for the link. I have been trying this options since few hours. I am not able to duplicate the records as per the condition.
    Sunday, October 16, 2016 2:59 PM
  • Hi Issel_D,

    Can you share the expected input and expected output as a sample(a complete one with values)..I will try to replicate the scenario on my dev box...

    Regards,


    Mandar Dharmadhikari

    Sunday, October 16, 2016 3:01 PM
    Moderator
  • Hi Mandar, The xml that I have are the ones . The two elements that are not there is Date and , PayDate. Everything else is the same..
    Sunday, October 16, 2016 3:13 PM
  • Hi Issel_D,

    There are couple of ways you can get this:

    1. If you want to use mapper what you can do is 

      a. Create a same schema like your input and have another repeating node with cashflow elements . call it say <DuplicateCashflow/>

    MAP1:

     b. Map ur input to the new schema where u map all cashflow to cashflow and based on the condition of Position=0 map cashflow to DuplicateCashflow

    MAP2:

     c. Take this new input with cashflow and duplicatecashflow and map to another message that is same as your original message schema. This way u now have all cashflow and duplicatecashflow under cashflow node.

    MAP3:

     d. Map this new message to name value pair based on the link that Mandar has suggested.

    2. You can use xsl in the map to achieve the required output in 1 Map instead of 3. Efficient.

    I have this based on each element however you can even have this generic on element name and value and then if there are additions or removal of elements you wont have to touch the map.

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" encoding="utf-8" indent="no" />
        <xsl:template match="/Cashflows">
            <Cashflows>
                <xsl:for-each select="Cashflow">
                    <Cashflow>
                        <xsl:call-template name="cashflow">
                            <xsl:with-param name="notional" select="NotionalAmount/text()" />
                        </xsl:call-template>
                    </Cashflow>
                    <xsl:if test="Position/text()='0'">
                        <Cashflow>
                            <xsl:call-template name="cashflow">
                                <xsl:with-param name="notional" select="'0'" />
                            </xsl:call-template>
                        </Cashflow>
                    </xsl:if>
                </xsl:for-each>
            </Cashflows>
        </xsl:template>
        <xsl:template name="cashflow">
            <xsl:param name="notional" />
            <xsl:element name="Data">
                <xsl:attribute name="name">NotionalAmount</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="$notional" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">Position</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="Position/text()" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">Amount</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="Amount/text()" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">Currency</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="Currency/text()" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">Date</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="Date/text()" />
                </xsl:attribute>
            </xsl:element>
            <xsl:element name="Data">
                <xsl:attribute name="name">PayDate</xsl:attribute>
                <xsl:attribute name="value">
                    <xsl:value-of select="PayDate/text()" />
                </xsl:attribute>
            </xsl:element>
        </xsl:template>
    </xsl:stylesheet>

    Pi_xel_xar

    Blog: My Blog

    BizTalkApplicationDeploymentTool: BizTalk Application Deployment Tool

    LinkedIn: LinkedIn

    • Marked as answer by Issel_D Monday, October 17, 2016 7:12 AM
    Sunday, October 16, 2016 4:41 PM
    Answerer
  • Hi Pi_Xel_Xar,

    Thanks for the inputs. I tried the mapper solution and it worked great. I however found the xsl solution cleaner but since I am not very good at the xsl I have opted for mapper one. I will do some readings on xsl to learn more on it.

    Monday, October 17, 2016 7:14 AM