Dash
Dash

Reputation: 314

Update variable value in XSLT for-each loop

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

Answers (3)

Chong Lip Phang
Chong Lip Phang

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

michael.hor257k
michael.hor257k

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

Joel M. Lamsen
Joel M. Lamsen

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() &gt; 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() &gt; 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

Related Questions