Reputation: 314
I have this XML:
<Root>
<Employee>
<Name>Dash</Name>
<Age>23</Age>
</Employee>
<Employee>
<Name>Gwen</Name>
<Age>22</Age>
</Employee>
</Root>
And I need to convert to below XML using XSLT:
<Root>
<Employee>
<Name>Dash,Gwen</Name>
<Age>23,22</Age>
</Employee>
</Root>
I am using the for-each loop to get the values of the sub-nodes of the <Employee>
node.The problem I am facing is I cannot figure out how to store the concatenated values in another temperoary variable in XSLT.I found on many sites that we cannot update the variables in the XSLT, so is there any alternative solution for this?
Upvotes: 0
Views: 3812
Reputation: 9279
Will this do?
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="3.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="Root">
<Root>
<Employee>
<Name>
<xsl:value-of select="Employee/Name" separator="," />
</Name>
<Age>
<xsl:value-of select="Employee/Age" separator="," />
</Age>
</Employee>
</Root>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2
Reputation: 117140
This is what I meant by "use a common template for both and avoid the code repetition":
XSLT 1.0
<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="/Root">
<Root>
<Employee>
<Name>
<xsl:apply-templates select="Employee/Name"/>
</Name>
<Age>
<xsl:apply-templates select="Employee/Age"/>
</Age>
</Employee>
</Root>
</xsl:template>
<xsl:template match="Name|Age">
<xsl:value-of select="."/>
<xsl:if test="position()!=last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
While I am here, let me also point out that this replaces a solid XML structure with a very problematic one. I am not sure what's the purpose of this transformation, but the result is an XML that could be very difficult to consume by downstream applications.
Upvotes: 1
Reputation: 7173
please try the following stylesheet:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="Root">
<Root>
<Employee>
<Name>
<xsl:for-each select="Employee/Name">
<xsl:if test="position() > 1">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
</Name>
<Age>
<xsl:for-each select="Employee/Age">
<xsl:if test="position() > 1">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
</Age>
</Employee>
</Root>
</xsl:template>
</xsl:stylesheet>
or as an alternative,
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="/">
<Root>
<Employee>
<xsl:apply-templates select="Root/Employee[1]"/>
</Employee>
</Root>
</xsl:template>
<xsl:template match="Employee[1]/Name|Employee[1]/Age">
<xsl:variable name="curr_name" select="name()"/>
<xsl:copy>
<xsl:value-of select="."/>
<xsl:for-each select="following::*[name()=$curr_name]">
<xsl:text>,</xsl:text>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0