0

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

bob.mazzo
  • 5,183
  • 23
  • 80
  • 149
  • 1
    Maybe I am misreading the question, but I can't see what your XML input is and your desired XML output. Could you rephrase your question and provide: a) An complete XML input. b) An complete desired output. c) Some description between the input and output. d) What you have tried so far. – Mark Veenstra May 08 '14 at 17:21
  • My main challenge now is that I'll be processing two different values for - "IRS" and "CDS". The xml output will vary depending on the element value. Will I be using ? – bob.mazzo May 08 '14 at 19:10
  • I edited my original post. Hopefully clearer. thank you much . – bob.mazzo May 08 '14 at 19:30

1 Answers1

1

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

Tobias Klevenz
  • 1,625
  • 11
  • 13
  • this is great advice and I find it quite helpful. I've added select="Trades_Output" to my initial "apply-templates" tag, and I already have two separate sections I've implemented - one for IRS and another for CDS. – bob.mazzo May 09 '14 at 15:58
  • and so for clarity, by having two separate templates ( – bob.mazzo May 09 '14 at 16:00
  • I forgot to mention that I just updated my desired xml output to now include a node wrapped around the entire parent node. I also included a new section, whose children are also a copy of | and change the element names while maintaining the same element values ? – bob.mazzo May 09 '14 at 16:34
  • How is your input file structured when you have multiple trades? Will you have multiple Trade_Output? If not that changes things a bit. Maybe update your source example with more than one tradeType... – Tobias Klevenz May 09 '14 at 17:22
  • xsl:for-each-group is causing an exception in Visual Studio 2012. – bob.mazzo May 09 '14 at 17:37
  • if you are using visual studio you cannot use XSLT-2.0, the .net xslt processor does not support it... can you use another xslt processor like saxon? – Tobias Klevenz May 09 '14 at 17:41
  • I've included CDS node as well. This way you can see that there are indeed mult nodes. – bob.mazzo May 09 '14 at 18:44
  • someone suggested downloading into VS 2012 the xslt 2.0 XSD from w3c. Here's the post I just read: http://appdevonsharepoint.com/adding-xslt-2-0-intellisense-to-visual-studio/ – bob.mazzo May 09 '14 at 20:51
  • 1
    Installing the intellisense for xslt 2.0 will not solve your problem, visual studio will still not be able to do an XSLT 2.0 transformation http://stackoverflow.com/questions/11205268/how-to-use-xslt-2-0-in-visual-studio-2010 the link is for VS 2010 but this is still the case for VS 2012 – Tobias Klevenz May 10 '14 at 14:11