I have to wrap certain nodes inside another element conditionally. In the below example I need to wrap CityName inside MyCity if city is Venezia. I have achieved it now, but i think there is better way of writing this without repeating the node. One way is to create a template and call that for the CityName, but is there any more elegant ways with fewer lines of code?
Input
<cities>
<city name="Milano"/>
<city name="Paris"/>
<city name="Munchen"/>
<city name="Lyon"/>
<city name="Venezia"/>
</cities>
My Xslt
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="city">
<xsl:choose>
<xsl:when test="@name='Venezia'">
<myCity>
<CityName>
<xsl:value-of select="@name"/>
</CityName>
</myCity>
</xsl:when>
<xsl:otherwise>
<CityName>
<xsl:value-of select="@name"/>
</CityName>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Identity Transform-->
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*"/>
</xsl:stylesheet>
Output I am looking for
<cities>
<CityName>Milano</CityName>
<CityName>Paris</CityName>
<CityName>Munchen</CityName>
<CityName>Lyon</CityName>
<myCity>
<CityName>Venezia</CityName>
</myCity>
</cities>
>Solution :
I think that all you need is:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="city[@name='Venezia']">
<myCity>
<xsl:next-match/>
</myCity>
</xsl:template>
<xsl:template match="city">
<CityName>
<xsl:value-of select="@name"/>
</CityName>
</xsl:template>
<!-- Identity Transform-->
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>