简体   繁体   English

使用XSLT将一种xml格式转换为另一种

[英]Using XSLT to transform one xml format into another

I have the following xml input file, and would like to transform it into a different xml schema format. 我有以下xml输入文件,并希望将其转换为其他xml模式格式。 So far what I have is working and producing a well-formatted xml output. 到目前为止,我正在努力并产生格式正确的xml输出。

Two challenges: 两个挑战:

  1. I would like to structure my XSLT a little better where I would be using multiple <xsl:apply-templates/> commands. 我想在使用多个<xsl:apply-templates/>命令的地方更好地构造XSLT。
  2. I'm also going to process several <tradeType> nodes (ie <tradeType>IRS</tradeType> , as well as <tradeType>CDS</tradeType> ), and would need my output to be be slightly different based on that <tradeType> value. 我还要处理几个<tradeType>节点(即<tradeType>IRS</tradeType>以及<tradeType>CDS</tradeType> ),并且需要基于该<tradeType>值。

Here's an input sample for <tradeType>IRS</tradeType> : 这是<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: 和我的XSLT代码的一小段:

<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? 有没有其他建议可以使我的XSLT更好一些? In other words, as opposed to having all xml output within <xsl:template match="Trades_Output"> 换句话说,与在<xsl:template match="Trades_Output">中包含所有xml输出相反

thank you. 谢谢。 Bob 短发

1. I would like to structure my XSLT a little better where I would be using multiple commands. 1.我想在使用多个命令的地方更好地构造XSLT。

The design of the source XML is pretty bad, this would be a lot better if the elements were like: 源XML的设计非常糟糕,如果元素如下所示,那就更好了:

<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: 由于所有LegOne / LegTwo元素似乎基本相同,但是您使用的是XSLT 2.0,因此使用正则表达式可以解决此问题,我将执行以下操作:

<?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 (ie <tradeType>IRS</tradeType> , as well as <tradeType>CDS</tradeType> ), and would need my output to be be slightly different based on that <tradeType> value. 我还要处理几个<tradeType>节点(即<tradeType>IRS</tradeType>以及<tradeType>CDS</tradeType> ),并且需要基于该<tradeType>值。

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 这完全取决于你的意思是什么小幅所以也许在这里提供一些更多的信息在什么将是每个tradeType不同......最简单的solutin是只具有每tradeType一个模板

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

respectively 分别

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

and then have different structures in there... 然后在那里有不同的结构...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM