Reputation: 8923
I have one xml A and want to create a new xml B. The outer elements of B are different from A, but some of the child nodes are the same. I have written an XSL file but am struggling to get it right. Can anyone tell me where I am going wrong? How do I copy individual elements from A to B? The issue is, when the transformation happens, the text in A is copied to B. Looking at previous stack overflow questions, this is because there is an error in my xsl but I cant figure out what.
A:
<Request>
<Source>
<RequestorID Client="1" EMailAddress="test@test.com" Password="pwd"/>
<RequestorPreferences Country="JP" Currency="jpy" Language="en">
<RequestMode>SYNCHRONOUS</RequestMode>
</RequestorPreferences>
</Source>
<RequestDetails>
<SearchHotelPriceRequest>
<ItemDestination DestinationCode="LON" DestinationType="city"/>
<ItemCode>98i</ItemCode>
<PeriodOfStay>
<CheckInDate>2015-05-20</CheckInDate>
<CheckOutDate>2015-05-21</CheckOutDate>
</PeriodOfStay>
<IncludePriceBreakdown/>
<IncludeChargeConditions/>
<Rooms>
<Room Code="tb" NumberOfCots="0" NumberOfRooms="1">
<ExtraBeds/>
</Room>
</Rooms>
</SearchHotelPriceRequest>
</RequestDetails>
</Request>
B:
<WebRequest>
<RequestDetails>
<WebSearchHotelPriceRequest
CallCentreClientUI="2577"
Client="1"
Country="JP"
Currency="jpy"
Language="en"
LoginID="">
<GcPriceOptions ShowDeduped="true"/>
<ItemDestination DestinationCode="LON" DestinationType="city"/>
<ItemName></ItemName>
<ItemCode>98i</ItemCode>
<EffectiveDate>2014-08-15</EffectiveDate>
<StarRatingRange>
<Min>0</Min>
<Max>0</Max>
</StarRatingRange>
<PeriodOfStay>
<CheckInDate>2015-05-20</CheckInDate>
<CheckOutDate>2015-05-21</CheckOutDate>
</PeriodOfStay>
<IncludeChargeConditions/>
<Rooms>
<Room Code="tb" NumberOfRooms="1"></Room>
</Rooms>
<SiteId>008</SiteId>
</WebSearchHotelPriceRequest>
</RequestDetails>
</WebRequest>
XSL:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Request">
<xsl:element name="WebRequest">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="RequestDetails">
<xsl:element name="RequestDetails">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="SearchHotelPriceRequest">
<xsl:element name="WebSearchHotelPriceRequest">
<xsl:attribute name="CallCentreClientUI">1</xsl:attribute>
<xsl:attribute name="Client">1</xsl:attribute>
<xsl:attribute name="Country">UK</xsl:attribute>
<xsl:attribute name="Currency">GBP</xsl:attribute>
<xsl:attribute name="Language">EN</xsl:attribute>
<xsl:attribute name="LoginID">100</xsl:attribute>
<SiteId>001</SiteId>
<EffectiveDate>01-01-99</EffectiveDate>
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="ItemDestination">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="ItemCode">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="ItemName">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="PeriodOfStay">
<xsl:copy>
<xsl:copy-of select="node()" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="IncludeChargeConditions">
<xsl:copy>
<xsl:copy-of select="node()" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="Rooms">
<xsl:copy>
<xsl:copy-of select="node()" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Incorrect Output:
<?xml version="1.0" encoding="UTF-8"?>
<WebRequest>SYNCHRONOUS<RequestDetails>
<WebSearchHotelPriceRequest CallCentreClientUI="1" Client="1" Country="UK" Currency="GBP" Language="EN" LoginID="100">
<SiteId>001</SiteId>
<EffectiveDate>01-01-99</EffectiveDate>
<ItemDestination DestinationCode="LON" DestinationType="city"/>
<ItemCode>98i</ItemCode>
<PeriodOfStay>
<CheckInDate>2015-05-20</CheckInDate>
<CheckOutDate>2015-05-21</CheckOutDate>2015-05-202015-05-21</PeriodOfStay>
<IncludeChargeConditions/>
<Rooms>
<Room Code="tb" NumberOfCots="0" NumberOfRooms="1">
<ExtraBeds/>
</Room>
</Rooms>
</WebSearchHotelPriceRequest>
</RequestDetails>
</WebRequest>
Upvotes: 0
Views: 126
Reputation: 117140
I think you are making this much more complicated than it needs to be. The simplest way to copy elements (along with all they contain, i.e. "deep copy") is to use xsl:copy-of
. Also, you don't need to use xsl:element
if you know the name of the element; just output the element literally. Similarly, for xsl:attribute
you can write it directly and - if necessary - use attribute value template to insert the value from the input.
Have a look at the following stylesheet as an example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<WebRequest>
<xsl:for-each select="Request/RequestDetails/SearchHotelPriceRequest">
<RequestDetails>
<WebSearchHotelPriceRequest
CallCentreClientUI="2577"
Client="2577"
Country="J"
Currency="USD"
Language="E"
LoginID="">
<GcPriceOptions ShowDeduped="true"/>
<xsl:copy-of select="ItemDestination"/>
<ItemName></ItemName>
<xsl:copy-of select="ItemCode"/>
<EffectiveDate>2014-08-15</EffectiveDate>
<StarRatingRange>
<Min>0</Min>
<Max>0</Max>
</StarRatingRange>
<xsl:copy-of select="PeriodOfStay | IncludeChargeConditions | Rooms"/>
<SiteId>008</SiteId>
</WebSearchHotelPriceRequest>
</RequestDetails>
</xsl:for-each>
</WebRequest>
</xsl:template>
</xsl:stylesheet>
This is of course not exactly what you need, but I don't know which values go where.
If someone could tell me why the extra text (e.g. SYNCHRONOUS) is being erroneously copied?
Because you are using xsl:apply templates
indiscriminately - and text nodes are copied by default using the built-in templates.
Upvotes: 1