Question

I have the following xml input file, and would like to transform it into a different xml schema format. So far what I have is working and producing a well-formatted xml output.

Two challenges:

  1. I would like to structure my XSLT a little better where I would be using multiple <xsl:apply-templates/> commands.
  2. I'm also going to process several <tradeType> nodes (i.e. <tradeType>IRS</tradeType>, as well as <tradeType>CDS</tradeType> ), and would need my output to be be slightly different based on that <tradeType> value.

Here's an input sample for <tradeType>IRS</tradeType> :

<collection>
    <Trades_Output>
        <tradeId>IRS-002</tradeId>
        <tradeDate>2007-09-05</tradeDate>
        <tradeType>IRS</tradeType>
        <buySell>BUY</buySell>
        <counterparty>COUNTERPARTY IRS</counterparty>
        <internalUnit>My Company Inc</internalUnit>
        <legOnePayerPartyReference>COUNTERPARTY IRS</legOnePayerPartyReference>
        <legOneReceiverPartyReference>My Company Inc</legOneReceiverPartyReference>
        <legOneStartDate>2007-09-05</legOneStartDate>
        <legOneEndDate>2014-09-05</legOneEndDate>
        <legOneNotional>151521500</legOneNotional>
        <legOneCurrency>GBP</legOneCurrency>
        <legOneRateIndex>LIBOR</legOneRateIndex>
        <legOneSpread>0.0022</legOneSpread>
        <legOneFixedRate></legOneFixedRate>
        <legTwoPayerPartyReference>My Company Inc</legTwoPayerPartyReference>
        <legTwoReceiverPartyReference>COUNTERPARTY IRS</legTwoReceiverPartyReference>
        <legTwoStartDate>2007-09-05</legTwoStartDate>
        <legTwoEndDate>2014-09-05</legTwoEndDate>
        <legTwoNotional>151521500</legTwoNotional>  
        <legTwoCurrency>GBP</legTwoCurrency>
        <legTwoRateIndex></legTwoRateIndex>
        <legTwoSpread></legTwoSpread>
        <legTwoFixedRate>0.04575</legTwoFixedRate>
        <legTwoRateType>FIXED</legTwoRateType>
    </Trades_Output>
    <Trades_Output>
       <tradeId>CDS-002</tradeId>
       <tradeDate>2010-09-27</tradeDate>
       <tradeType>CDS</tradeType>
       <counterparty>COUNTERPARTY CDS</counterparty>
        <internalUnit>My Company Limited</internalUnit>
       <buySell>BUY</buySell>
       <status>OPEN</status>
       <startDate>2007-09-05</startDate>
       <endDate>2014-09-05</endDate>
       <sellerPartyReference>COUNTERPARTY IRS</sellerPartyReference>
       <buyerPartyReference>My Company Inc</buyerPartyReference>
       <instrumentId>RBS (REG) 01/08/2013</instrumentId>
       <currency>GBP</currency>
       <amount>75000000</amount>
       <fixedRate>0.0098</fixedRate>
       <dayCountFraction>ACT/360</dayCountFraction>
     </Trades_Output>
</collection>

My desired output:

 <deal>
 <dealHeader>
      <dealId>IRS-RRT-002</dealId>
      <dealType>IRS</dealType>
      <dealDate>2007-09-05</dealDate>
      <status>OPEN</status>
 </dealHeader>
 <trade>
    <sysId>2</sysId>
    <tradeHeader>
        <tradeId>IRS-RRT-002</tradeId>
        <tradeDate>2007-09-05</tradeDate>
        <tradeType>IRS</tradeType>
        <counterparty>COUNTERPARTY IRS</counterparty>
        <internalUnit>My Company Inc</internalUnit>
        <buySell>BUY</buySell>
        <status>OPEN</status>
    </tradeHeader>
    <extensions>
        <extension>
            <name>OrigID</name>
            <value>IRS-RRT-002</value>
        </extension>
    </extensions>
    <product>
        <swap>
            <swapStream>
                <payerPartyReference href='COUNTERPARTY IRS'/>
                <receiverPartyReference href='My Company Inc'/>
                <calculationPeriodDates id='CalcPeriodDates0'>
                    <effectiveDate>
                        <unadjustedDate>2007-09-05</unadjustedDate>
                        <dateAdjustments>
                            <businessDayConvention>MODFOLLOWING</businessDayConvention>
                        </dateAdjustments>
                    </effectiveDate>
                    <terminationDate>
                        <unadjustedDate>2014-09-05</unadjustedDate>
                        <dateAdjustments>
                            <businessDayConvention>MODFOLLOWING</businessDayConvention>
                        </dateAdjustments>
                    </terminationDate>
                    <calculationPeriodDatesAdjustments>
                        <businessDayConvention>MODFOLLOWING</businessDayConvention>
                    </calculationPeriodDatesAdjustments>
                    <calculationPeriodFrequency>
                        <periodMultiplier>6</periodMultiplier>
                        <period>M</period>
                        <rollConvention>NONE</rollConvention>
                    </calculationPeriodFrequency>
                </calculationPeriodDates>
                <paymentDates>
                    <calculationPeriodDatesReference href='#CalcPeriodDates0'/>
                    <paymentFrequency>
                        <periodMultiplier>6</periodMultiplier>
                        <period>M</period>
                    </paymentFrequency>
                    <payRelativeTo>CalculationPeriodEndDate</payRelativeTo>
                    <paymentDatesAdjustments>
                        <businessDayConvention>MODFOLLOWING</businessDayConvention>
                    </paymentDatesAdjustments>
                </paymentDates>
                <calculationPeriodAmount>
                    <calculation>
                        <notionalSchedule>
                            <notionalStepSchedule>
                                <initialValue>151521500</initialValue>
                                <currency>GBP</currency>
                            </notionalStepSchedule>
                        </notionalSchedule>
                        <floatingRateCalculation>
                            <floatingRateIndex>LIBOR</floatingRateIndex>
                            <indexTenor>
                                <periodMultiplier>6</periodMultiplier>
                                <period>M</period>
                            </indexTenor>
                            <spreadSchedule>
                                <initialValue>0</initialValue>
                            </spreadSchedule>
                        </floatingRateCalculation>
                        <dayCountFraction>Act/360</dayCountFraction>
                    </calculation>
                </calculationPeriodAmount>
                <stubCalculationPeriodAmount>
                    <finalStub/>
                </stubCalculationPeriodAmount>
                <principalExchanges>
                    <initialExchange>false</initialExchange>
                    <finalExchange>false</finalExchange>
                    <intermediateExchange>false</intermediateExchange>
                </principalExchanges>
            </swapStream>
            <swapStream>
                <payerPartyReference href='My Company Inc'/>
                <receiverPartyReference href='COUNTERPARTY IRS'/>
                <calculationPeriodDates id='CalcPeriodDates0'>
                    <effectiveDate>
                        <unadjustedDate>2007-09-05</unadjustedDate>
                        <dateAdjustments>
                            <businessDayConvention>MODFOLLOWING</businessDayConvention>
                        </dateAdjustments>
                    </effectiveDate>
                    <terminationDate>
                        <unadjustedDate>2014-09-05</unadjustedDate>
                        <dateAdjustments>
                            <businessDayConvention>MODFOLLOWING</businessDayConvention>
                        </dateAdjustments>
                    </terminationDate>
                    <calculationPeriodDatesAdjustments>
                        <businessDayConvention>MODFOLLOWING</businessDayConvention>
                    </calculationPeriodDatesAdjustments>
                    <calculationPeriodFrequency>
                        <periodMultiplier>6</periodMultiplier>
                        <period>M</period>
                        <rollConvention>NONE</rollConvention>
                    </calculationPeriodFrequency>
                </calculationPeriodDates>
                <paymentDates>
                    <calculationPeriodDatesReference href='#CalcPeriodDates0'/>
                    <paymentFrequency>
                        <periodMultiplier>6</periodMultiplier>
                        <period>M</period>
                    </paymentFrequency>
                    <payRelativeTo>CalculationPeriodEndDate</payRelativeTo>
                    <paymentDatesAdjustments>
                        <businessDayConvention>MODFOLLOWING</businessDayConvention>
                    </paymentDatesAdjustments>
                </paymentDates>
                <calculationPeriodAmount>
                    <calculation>
                        <notionalSchedule>
                            <notionalStepSchedule>
                                <initialValue>151521500</initialValue>
                                <currency>GBP</currency>
                            </notionalStepSchedule>
                        </notionalSchedule>
                        <fixedRateSchedule>
                            <initialValue>0.04575</initialValue>
                        </fixedRateSchedule>
                        <dayCountFraction>Act/360</dayCountFraction>
                    </calculation>
                </calculationPeriodAmount>
                <principalExchanges>
                    <initialExchange>false</initialExchange>
                    <finalExchange>false</finalExchange>
                    <intermediateExchange>false</intermediateExchange>
                </principalExchanges>
            </swapStream>
        </swap>
    </product>
  </trade>
 </deal>

and a snippet of my XSLT code:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/*">
        <body>
            <insertions>          
                <xsl:apply-templates/>          
            </insertions>
        </body>
    </xsl:template>     
    <xsl:template match="Trades_Output">
        <trade>
            <tradeHeader>
                <tradeId>
                    <xsl:value-of select="tradeId"/>
                </tradeId>
                <tradeDate>
                    <xsl:value-of select="tradeDate"/>
                </tradeDate>
            </tradeHeader>
            <product>
                <swap>
                    <swapStream>
                        <payerPartyReference>
                            <xsl:value-of select="legOnePayerPartyReference"/>
                        </payerPartyReference>
                        <receiverPartyReference>
                            <xsl:value-of select="legOneReceiverPartyReference"/>
                        </receiverPartyReference>
                    </swapStream>
                    <swapStream>
                        <payerPartyReference>
                            <xsl:value-of select="legTwoPayerPartyReference"/>
                        </payerPartyReference>
                        <receiverPartyReference>
                            <xsl:value-of select="legTwoReceiverPartyReference"/>
                        </receiverPartyReference>                
                    </swapStream>
                </swap>
            </product>
        </trade>
    </xsl:template>
....

Is there any additional advice one can provide to structure my XSLT a little better? In other words, as opposed to having all xml output within <xsl:template match="Trades_Output">

thank you. Bob

Was it helpful?

Solution

1. I would like to structure my XSLT a little better where I would be using multiple commands.

The design of the source XML is pretty bad, this would be a lot better if the elements were like:

<PayerPartyReference leg="one"/>

Since all the LegOne/LegTwo elements seem to be basically the same, however you using XSLT 2.0 so there's a solution to that using regex, I'd do something like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output indent="yes"/>

<xsl:template match="/*">
    <body>
        <insertions>
            <xsl:apply-templates select="Trades_Output"/>
        </insertions>
    </body>
</xsl:template>

<xsl:template match="Trades_Output">
    <trade>
        <tradeHeader>
            <xsl:copy-of select="tradeId | tradeDate"/>
        </tradeHeader>
        <product>
            <swap>
                <!-- this will generate two groups for the elements starting with legOne/legTwo -->
                <xsl:for-each-group select="*[matches(name(),'(legOne|legTwo)')]"
                    group-by="substring(name(),1,6)">
                    <swapStream>
                        <!-- 
                          this will apply to legOnePayerPartyReference and legOneReceiverPartyReference
                          when in group legOne and respectively when in group legTwo 
                        -->
                        <xsl:apply-templates select="current-group()[ends-with(name(),'PartyReference')]"/>
                        <calculationPeriodDates>
                            <xsl:apply-templates select="current-group()[ends-with(name(),'Date')]"/>
                        </calculationPeriodDates>
                    </swapStream>
                </xsl:for-each-group>
            </swap>
        </product>
    </trade>
</xsl:template>

<xsl:template match="*[matches(name(),'(legOne|legTwo)PayerPartyReference')]">
    <payerPartyReference href="{.}"/>
</xsl:template>

<xsl:template match="*[matches(name(),'(legOne|legTwo)ReceiverPartyReference')]">
    <receiverPartyReference href="{.}"/>
</xsl:template>

<xsl:template match="*[matches(name(),'(legOne|legTwo)StartDate')]">
    <effectiveDate>
        <unadjustedDate>
            <xsl:value-of select="."/>
        </unadjustedDate>
        <dateAdjustments>
            <businessDayConvention>MODFOLLOWING</businessDayConvention>
        </dateAdjustments>
    </effectiveDate>
</xsl:template>

<xsl:template match="*[matches(name(),'(legOne|legTwo)EndDate')]">
    <terminationDate>
        <unadjustedDate>
            <xsl:value-of select="."/>
        </unadjustedDate>
        <dateAdjustments>
            <businessDayConvention>MODFOLLOWING</businessDayConvention>
        </dateAdjustments>
    </terminationDate>
</xsl:template>
</xsl:stylesheet>

It's unclear to me were most of the stuff in your desired Output comes from, I'm guessing lot's of it is fixed...however this should get you started.


I'm also going to process several <tradeType> nodes (i.e. <tradeType>IRS</tradeType>, as well as <tradeType>CDS</tradeType> ), and would need my output to be be slightly different based on that <tradeType> value.

This totally depends on what you mean by slightly so maybe provide some more info here on what would be different for each tradeType... the simplest solutin would be to just have one template per tradeType

<xsl:template match="Trades_Output[tradeType='IRS']"> 

respectively

<xsl:template match="Trades_Output[tradeType='CDS']">

and then have different structures in there...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top