Reputation: 277
I am trying to use an identity/copy pattern to transform only the Segments/Segment part below and retain the rest of the structure. What would the template look like? I tried some examples from the forum to apply templates in an xslt:for-each SegmentFares/Segments/Segment but I don't know how to put the base fare in the first SegmentFare and set it to zero in the subsequent ones in the remaining segments.
Input XML:
<FareQuoteRS>
<PaxFareQuotes>
<item>
<PTC>ADT</PTC>
<TotalFare>
<Currency>INR</Currency>
<Fare>8403</Fare>
<TotalBaseFare>3620</TotalBaseFare>
</TotalFare>
<SegmentFares>
<SegmentFare>
<Currency>INR</Currency>
<BaseFare>3620</BaseFare>
<Segments>
<Segment>
<Origin>DEL</Origin>
<Destination>BOM</Destination>
<DeptrDate>2012-06-23</DeptrDate>
<DeptrTime>10:10</DeptrTime>
<ArrDate>2012-06-23</ArrDate>
<ArrTime>12:15</ArrTime>
<FareBasis>J</FareBasis>
<PromoCode></PromoCode>
<FltNum>109</FltNum>
<Airline>YY</Airline>
<BagAllow>20K</BagAllow>
</Segment>
<Segment>
<Origin>BOM</Origin>
<Destination>GOI</Destination>
<DeptrDate>2012-06-23</DeptrDate>
<DeptrTime>15:15</DeptrTime>
<ArrDate>2012-06-23</ArrDate>
<ArrTime>16:20</ArrTime>
<FareBasis>J</FareBasis>
<PromoCode></PromoCode>
<FltNum>248</FltNum>
<Airline>YY</Airline>
<BagAllow>20K</BagAllow>
</Segment>
</Segments>
</SegmentFare>
</SegmentFares>
<Taxes>
<Currency>INR</Currency>
<TotalTaxes>4783</TotalTaxes>
<item>
<TaxCode>YQ</TaxCode>
<TaxName>Fuel Surcharge</TaxName>
<Currency>INR</Currency>
<TaxAmount>3150</TaxAmount>
</item>
<item>
<TaxCode>WO</TaxCode>
<TaxName>PSF</TaxName>
<Currency>INR</Currency>
<TaxAmount>146</TaxAmount>
</item>
<item>
<TaxCode>IN</TaxCode>
<TaxName>UDF</TaxName>
<Currency>INR</Currency>
<TaxAmount>745</TaxAmount>
</item>
<item>
<TaxCode>JN</TaxCode>
<TaxName>Service Tax</TaxName>
<Currency>INR</Currency>
<TaxAmount>335</TaxAmount>
</item>
<item>
<TaxCode>TF</TaxCode>
<TaxName>Transaction Fee</TaxName>
<Currency>INR</Currency>
<TaxAmount>407</TaxAmount>
</item>
</Taxes>
</item>
</PaxFareQuotes>
<Status>Success</Status>
<StatusRemark/>
</FareQuoteRS>
Output XML:
<FareQuoteRS>
<PaxFareQuotes>
<item>
<PTC>ADT</PTC>
<TotalFare>
<Currency>INR</Currency>
<Fare>8403</Fare>
<TotalBaseFare>3620</TotalBaseFare>
</TotalFare>
<SegmentFares>
<!-- There is now one SegmentFare for each Segment in the input -->
<!-- while the BaseFare is set to zero for the subsequent segments -->
<SegmentFare>
<Currency>INR</Currency>
<BaseFare>3620</BaseFare>
<Segments>
<Segment>
<Origin>DEL</Origin>
<Destination>BOM</Destination>
<DeptrDate>2012-06-23</DeptrDate>
<DeptrTime>10:10</DeptrTime>
<ArrDate>2012-06-23</ArrDate>
<ArrTime>12:15</ArrTime>
<FareBasis>J</FareBasis>
<PromoCode></PromoCode>
<FltNum>109</FltNum>
<Airline>YY</Airline>
<BagAllow>20K</BagAllow>
</Segment>
</Segments>
</SegmentFare>
<SegmentFare>
<Currency>INR</Currency>
<BaseFare>0</BaseFare>
<Segments>
<Segment>
<Origin>BOM</Origin>
<Destination>GOI</Destination>
<DeptrDate>2012-06-23</DeptrDate>
<DeptrTime>15:15</DeptrTime>
<ArrDate>2012-06-23</ArrDate>
<ArrTime>16:20</ArrTime>
<FareBasis>J</FareBasis>
<PromoCode></PromoCode>
<FltNum>248</FltNum>
<Airline>YY</Airline>
<BagAllow>20K</BagAllow>
</Segment>
</Segments>
</SegmentFare>
</SegmentFares>
<Taxes>
<Currency>INR</Currency>
<TotalTaxes>4783</TotalTaxes>
<item>
<TaxCode>YQ</TaxCode>
<TaxName>Fuel Surcharge</TaxName>
<Currency>INR</Currency>
<TaxAmount>3150</TaxAmount>
</item>
<item>
<TaxCode>WO</TaxCode>
<TaxName>PSF</TaxName>
<Currency>INR</Currency>
<TaxAmount>146</TaxAmount>
</item>
<item>
<TaxCode>IN</TaxCode>
<TaxName>UDF</TaxName>
<Currency>INR</Currency>
<TaxAmount>745</TaxAmount>
</item>
<item>
<TaxCode>JN</TaxCode>
<TaxName>Service Tax</TaxName>
<Currency>INR</Currency>
<TaxAmount>335</TaxAmount>
</item>
<item>
<TaxCode>TF</TaxCode>
<TaxName>Transaction Fee</TaxName>
<Currency>INR</Currency>
<TaxAmount>407</TaxAmount>
</item>
</Taxes>
</item>
</PaxFareQuotes>
<Status>Success</Status>
<StatusRemark/>
</FareQuoteRS>
Upvotes: 1
Views: 126
Reputation: 24826
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/><xsl:strip-space elements="*"/>
<!-- identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- build first SegmentFare -->
<xsl:template match="SegmentFares/SegmentFare">
<xsl:copy>
<xsl:apply-templates select="Currency|BaseFare"/>
<Segments>
<!-- leave first Segment as is -->
<xsl:apply-templates select="Segments/Segment[1]"/>
</Segments>
</xsl:copy>
<!-- apply templates to any next Segment -->
<xsl:apply-templates select="Segments/Segment[position()>1]" mode="BaseFare0"/>
</xsl:template>
<!-- wrap single Segment with BaseFare 0 -->
<xsl:template match="Segment" mode="BaseFare0">
<SegmentFare>
<xsl:copy-of select="ancestor::SegmentFare/Currency"/>
<BaseFare>0</BaseFare>
<Segments>
<xsl:apply-templates select="."/>
</Segments>
</SegmentFare>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 20731
Your idea with <xsl:for-each>
was good; it can be done as shown below.
The crucial part is the <xsl:choose>
element: The current context node is a <Segment>
element (from the <xsl:for-each>
loop iteration). Therefore, the condition <xsl:when>
element evaluates to true if before the current element, there is no other <Segment>
element in the same parent element. If that is true, the original <BaseFare>
value is copied, otherwise, a <BaseFare>
of zero is inserted.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/FareQuoteRS/PaxFareQuotes/item/SegmentFares">
<xsl:copy>
<xsl:for-each select="SegmentFare/Segments/Segment">
<SegmentFare>
<xsl:copy-of select="../../Currency"/>
<xsl:choose>
<xsl:when test="not(preceding-sibling::Segment)">
<xsl:copy-of select="../../BaseFare"/>
</xsl:when>
<xsl:otherwise>
<BaseFare>0</BaseFare>
</xsl:otherwise>
</xsl:choose>
<Segments>
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</Segments>
</SegmentFare>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1