Search code examples
xmlxsltxpathxslt-1.0xslt-2.0

Multiple Elements to Flat String Transform


I am looking to transform multiple elements from source xml and combine them in single target string element in comma separated text.

Conditions Source Inputs are boolean type, only if value true it should be included in target list

E.g. XML

<Root-Element>
<EnggTypes>
<Engg1>true</Engg1>
<Engg2>true</Engg2>
<Engg3>false</Engg3>
<Engg4>false</Engg4>
<Engg5>true</Engg5>
</EnggTypes>
</Root-Element>

Expected Transform

<Root-Element>
<RoleTypes>Role1,Role2,Role5</RoleTypes>
</Root-Element>

Looking to achieve same in XSL 1.0 or 2.0

I started overthinking and tried to use a variable on a target side to see if I can do some choose/when to construct the string using previous value and concatenate but seems like that will not work as variable value cannot be changed once set!

<xsl:variable name="roleVar">
<xsl:if test="Engg1/text()='true'">Role1</if>
<xsl:if test="Engg2/text()='true'">concat(roleVar,",",Role2)</if>
<xsl:if test="Engg3/text()='true'">concat(roleVar,",",Role3)</if>
<xsl:if test="Engg4/text()='true'">concat(roleVar,",",Role4)</if>
<xsl:if test="Engg5/text()='true'">concat(roleVar,",",Role5)</if>
</xsl:variable>

Any inputs appreciated.

Thanks in advance


Solution

  • You can select those elements and construct the value in one expression:

    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="EnggTypes">
            <xsl:copy>
                <xsl:value-of select="*[. = 'true']/concat('Role', replace(local-name(), '[^0-9]+', ''))" separator=","/>
            </xsl:copy>
        </xsl:template>
    
    </xsl:transform>
    

    http://xsltransform.net/bEzjRJR/1 gives

    <Root-Element>
    <EnggTypes>Role1,Role2,Role5</EnggTypes>
    </Root-Element>