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

3
  • 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. Commented May 8, 2014 at 17:21
  • My main challenge now is that I'll be processing two different values for <tradeType> - "IRS" and "CDS". The xml output will vary depending on the <tradeType> element value. Will I be using <xsl:if > ? Commented May 8, 2014 at 19:10
  • I edited my original post. Hopefully clearer. thank you much . Commented May 8, 2014 at 19:30

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

9 Comments

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 <xsl:template> sections I've implemented - one for <tradeType>IRS</tradeType> and another for <tradeType>CDS</tradeType>.
and so for clarity, by having two separate templates (<xsl:template match="..."), the XSL code will flow sequentially and process both templates ?
I forgot to mention that I just updated my desired xml output to now include a <deal> node wrapped around the entire <trade> parent node. I also included a new <dealHeader> section, whose children are also a copy of <tradeId> | <tradeDate | etc. How can I use the <xsl:Copy> and change the element names while maintaining the same element values ?
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...
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 stackoverflow.com/questions/11205268/… the link is for VS 2010 but this is still the case for VS 2012
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.