21

Is it possible to implement "if else, if else" in xsl? for example I have data:

<document>
    <line>
        <name>MAR111</name>
        <value>1</value>
    </line>

    <line>
        <name>MAR111</name>
        <value>3</value>
    </line>
    <line>
        <name>MEA111</name>
        <value>1</value>
    </line>
    <line>
        <name>MPR111</name>
        <value>1</value>
    </line>
    <line>
        <name>MEA111</name>
        <value>4</value>
    </line>
    <line>
        <name>MPR111</name>
        <value>2</value>
    </line>
</document>

I need to get three document templates with three names:

<document>
    <MAR>
        <name>MAR111</name>
        <number>1</number>
        <number>4</number>
    </MAR>
</document>
<document>
    <MEA>
        <name>MEA111</name>
        <number>1</number>
        <number>4</number>
    </MEA>
</document>
<document>
    <MPR>
        <name>MPR111</name>
        <number>1</number>
        <number>2</number>
    </MPR>
</document>

I try to use "choose, when" on apply template, but maybe there is a better way:

<xsl:template match="/">
    <xsl:choose>
        <xsl:when test="/document/line/name='MEA111'">
            <xsl:apply-templates mode="MEA" select="/document"/>
        </xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="/document/line/name='MPR111'">
            <xsl:apply-templates mode="MPR" select="/document"/>
        </xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="/document/line/name='MAR111'">
            <xsl:apply-templates mode="MAR" select="/document"/>
        </xsl:when>
    </xsl:choose>
</xsl:template>
1
  • Check my answer for the correct XSLT way for doing this. Commented Mar 2, 2011 at 15:49

7 Answers 7

26

Actually you can merge them together:

<xsl:template match="/">
    <xsl:choose>
        <xsl:when test="/document/line/name='MEA111'">
            <xsl:apply-templates mode="MEA" select="/document"/>
        </xsl:when>
        <xsl:when test="/document/line/name='MPR111'">
            <xsl:apply-templates mode="MPR" select="/document"/>
        </xsl:when>
        <xsl:when test="/document/line/name='MAR111'">
            <xsl:apply-templates mode="MAR" select="/document"/>
        </xsl:when>
    </xsl:choose>
</xsl:template>

EDIT: Petras, after your clarification, it seems that what you want is even easier:

<xsl:template match="/">
    <xsl:if test="/document/line/name='MEA111'">
       <xsl:apply-templates mode="MEA" select="/document"/>
    </xsl:if>
    <xsl:if test="/document/line/name='MPR111'">
        <xsl:apply-templates mode="MPR" select="/document"/>
    </xsl:if>
    <xsl:if test="/document/line/name='MAR111'">
        <xsl:apply-templates mode="MAR" select="/document"/>
    </xsl:if>
</xsl:template>
Sign up to request clarification or add additional context in comments.

1 Comment

But when we will get only one result of first condition which will be true. I need to get three result because all condition is correct
6

The best way is to use separate templates.

<xsl:template match="/document/line/name='MEA111'">
       <xsl:apply-templates mode="MEA" select="/document"/>
</xsl:template>

<xsl:template match="/document/line/name='MPR111'">
       <xsl:apply-templates mode="MPR" select="/document"/>
</xsl:template>

<xsl:template match="/document/line/name='MAR111'">
       <xsl:apply-templates mode="MAR" select="/document"/>
</xsl:template>

Even less lines and this is more maintainable.

Comments

5

No, choose when is the xsl way of saying if else. No better way

Comments

2

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kLineByName" match="line" use="name"/>
    <xsl:template match="line[count(.|key('kLineByName',name)[1]) = 1]">
        <document>
            <xsl:element name="{substring(name,1,3)}">
                <xsl:copy-of select="name|key('kLineByName',name)/value"/>
            </xsl:element>
        </document>
    </xsl:template>
    <xsl:template match="text()"/>
</xsl:stylesheet>

Output:

<document>
    <MAR>
        <name>MAR111</name>
        <value>1</value>
        <value>3</value>
    </MAR>
</document>
<document>
    <MEA>
        <name>MEA111</name>
        <value>1</value>
        <value>4</value>
    </MEA>
</document>
<document>
    <MPR>
        <name>MPR111</name>
        <value>1</value>
        <value>2</value>
    </MPR>
</document>

Comments

2

if you want to implement a catch-all fall through (e.g. equivalent to "else"), you should use otherwise

Comments

1

Do you mean something like:

<xsl:choose>
  <xsl:when test="name() = 'MAR111'">
    ... do something ...
  </xsl:when>
  <xsl:otherwise>
    ... do something as fallback ...
  </xsl:otherwise>
</xsl:choose>

BR Markus

Comments

1

Yes, we can achieve things using <xsl:choose><xsl:when> but if, else if, condition is also supported in @select attribute of different xslt construct for example :

<xsl:value-of select="if (@geography = 'North America') then 
                 'Domestic car'
                else if (@geography = 'Europe') then 
                  'Import from Europe'
                else if (@geography = 'Asia') then 
                  &quot;It's from Asia&quot;
                (: If it's anything else :)
                else 
                   'We don''t know!'"/>

1 Comment

Requires XSLT 2.0.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.