Search code examples
xsltxsl-choose

XSLT conditional statement options


In an attempt to learn more about the possibilities of XSLT I'm wondering if the is a better way to write this conditional code using a different approach.

It simply looks for the href in the first instance and if a href input is present the associated image with a link will display + alt tag output. If no href input is present just the image itself will display + alt tag output.

It works fine for the particular purpose albeit looking and feeling a little clunky.

So I'm wanting to know if there is a cleaner or smarter way of achieving the outcome.

Any advice would be greatly appreciated.

Thanks, ozmo

Anyhoo, here's my master-piece...

      <!-- SUPPORTING IMAGE HREF CONDITIONAL -->
      <xsl:choose>
        <xsl:when test="SupportingImageLink/a/@href !=''">
          <tr>
            <td>
              <a href="{SupportingImageLink/a/@href}">
                <img src="{SupportingImage/img/@src}" width="680" alt="{SupportingImage/img/@alt}" style="border: 0;width: 100%;max-width: 680px;" class="center-on-narrow"></img>
              </a>
            </td>
          </tr>
        </xsl:when>
        <xsl:otherwise>
          <tr>
            <td>
                <img src="{SupportingImage/img/@src}" width="680" alt="{SupportingImage/img/@alt}" style="border: 0;width: 100%;max-width: 680px;" class="center-on-narrow"></img>
            </td>
          </tr>
        </xsl:otherwise>
      </xsl:choose>
      <!-- SUPPORTING IMAGE HREF CONDITIONAL : END -->

And as requested here is the stripped down XML...

<root>
  <Title>New layout test</Title>
  <Edition>Octovember 2019</Edition>
  <Notification>
  <Body>Warning Warning Warning Will Robinson!! Aliens Aliens Aliens everywhere!</Body>
  </Notification>
  <Introduction>
    <Heading>Squids attack!</Heading>
    <Body>Ugh tacos artisan, single-origin coffee jianbing hoodie skateboard. 90's unicorn next level fixie. Glossier coloring book drinking vinegar, health goth flexitarian activated charcoal yuccie hexagon whatever normcore bushwick ethical mustache plaid lyft. Chicharrones edison bulb vinyl disrupt tbh glossier, marfa mumblecore four loko +1 leggings.</Body>
  </Introduction>
  <Section>
    <Heading>Just in - Cyborg bears attacking!</Heading>
    <Structure>3</Structure>
    <SupportingImage>
      <img src="/uploadedImages/dev/robots.png?n=3082" alt="Will Robinson" title="Will Robinson" style="width: 680px; height: 283px;" align="left" width="680" height="283" />
    </SupportingImage>
    <SupportingImageLink>
      <a href="http://www.squids-attack/cyb-bears.html">AAARRRRGGGGHHHH!!!</a>
    </SupportingImageLink>
    <Body>Ugh tacos artisan, single-origin coffee jianbing hoodie skateboard. 90's unicorn next level fixie. Glossier coloring book drinking vinegar, health goth flexitarian activated charcoal yuccie hexagon whatever normcore bushwick ethical mustache plaid lyft. Chicharrones edison bulb vinyl disrupt tbh glossier, marfa mumblecore four loko +1 leggings. Knausgaard af YOLO, direct trade drinking vinegar try-hard williamsburg roof party asymmetrical snackwave waistcoat. Venmo food truck next level raw denim, pabst photo booth quinoa chambray art party hot chicken cliche tote bag polaroid direct trade whatever. Shabby chic lomo locavore slow-carb leggings.</Body>
    <Button>More information</Button>
  </Section>
</root>

Solution

  • It is perfectly possible to write XSLT code without any conditional instructions.

    In fact this is the recommended DRY practice!

      <xsl:template match="Section/SupportingImageLink">
        <tr>
          <td>
            <xsl:apply-templates select="a[@href !='']"/>
            <xsl:apply-templates select="self::*[not(a[@href !=''])]" mode="getImage"/>
          </td> 
        </tr>
      </xsl:template>
    
      <xsl:template match="SupportingImageLink/a[@href !='']/text()">
        <xsl:apply-templates select="." mode="getImage"/>
      </xsl:template>
    
      <xsl:template match="node()" mode="getImage">
        <xsl:param name="pImg" select="ancestor::Section[1]/SupportingImage/img"/>
         <img src="{$pImg/@src}" width="680" 
          alt="{$pImg/@alt}" style="border: 0;width: 100%;max-width: 680px;" 
          class="center-on-narrow"></img>
      </xsl:template>
    

    Here is a complete transformation implementing this atop of the most fundamental XSLT Design Pattern: using and overriding the identity rule:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
      <xsl:template match="node()|@*">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="Section/SupportingImageLink">
        <tr>
          <td>
            <xsl:apply-templates select="a[@href !='']"/>
            <xsl:apply-templates select="self::*[not(a[@href !=''])]" mode="getImage"/>
          </td> 
        </tr>
      </xsl:template>
    
      <xsl:template match="SupportingImageLink/a[@href !='']/text()">
        <xsl:apply-templates select="." mode="getImage"/>
      </xsl:template>
    
      <xsl:template match="node()" mode="getImage">
        <xsl:param name="pImg" select="ancestor::Section[1]/SupportingImage/img"/>
         <img src="{$pImg/@src}" width="680" 
          alt="{$pImg/@alt}" style="border: 0;width: 100%;max-width: 680px;" 
          class="center-on-narrow"></img>
      </xsl:template>
    </xsl:stylesheet>
    

    When this transformation is applied on the following XML document (the provided one with an additional SupportingImageLink element that hasn't a link with href attribute:

    <root>
      <Title>New layout test</Title>
      <Edition>Octovember 2019</Edition>
      <Notification>
      <Body>Warning Warning Warning Will Robinson!! Aliens Aliens Aliens everywhere!</Body>
      </Notification>
      <Introduction>
        <Heading>Squids attack!</Heading>
        <Body>Ugh tacos artisan, single-origin coffee jianbing hoodie skateboard. 
        90's unicorn next level fixie. Glossier coloring book drinking vinegar, 
        health goth flexitarian activated charcoal yuccie hexagon whatever 
        normcore bushwick ethical mustache plaid lyft. Chicharrones edison 
        bulb vinyl disrupt tbh glossier, marfa mumblecore four loko +1 leggings.</Body>
      </Introduction>
      <Section>
        <Heading>Just in - Cyborg bears attacking!</Heading>
        <Structure>3</Structure>
        <SupportingImage>
          <img src="/uploadedImages/dev/robots.png?n=3082" alt="Will Robinson" 
               title="Will Robinson" style="width: 680px; height: 283px;" 
               align="left" width="680" height="283" />
        </SupportingImage>
        <SupportingImageLink>
          <a href="http://www.squids-attack/cyb-bears.html">AAARRRRGGGGHHHH!!!</a>
        </SupportingImageLink>
        <SupportingImageLink>
          <a>AAARRRRGGGGHHHH!!!</a>
        </SupportingImageLink>
        <Body>Ugh tacos artisan, single-origin coffee jianbing hoodie skateboard.
         90's unicorn next level fixie. Glossier coloring book drinking vinegar, 
         health goth flexitarian activated charcoal yuccie hexagon whatever normcore 
         bushwick ethical mustache plaid lyft. Chicharrones edison bulb vinyl 
         disrupt tbh glossier, marfa mumblecore four loko +1 leggings. Knausgaard
          af YOLO, direct trade drinking vinegar try-hard williamsburg roof party 
          asymmetrical snackwave waistcoat. Venmo food truck next level raw denim, 
          pabst photo booth quinoa chambray art party hot chicken cliche tote bag 
          polaroid direct trade whatever. Shabby chic lomo locavore slow-carb leggings.</Body>
        <Button>More information</Button>
      </Section>
    </root>
    

    As we see, the wanted, correct output is produced:

    <root>
      <Title>New layout test</Title>
      <Edition>Octovember 2019</Edition>
      <Notification>
          <Body>Warning Warning Warning Will Robinson!! Aliens Aliens Aliens everywhere!</Body>
      </Notification>
      <Introduction>
          <Heading>Squids attack!</Heading>
          <Body>Ugh tacos artisan, single-origin coffee jianbing hoodie skateboard. 
        90's unicorn next level fixie. Glossier coloring book drinking vinegar, 
        health goth flexitarian activated charcoal yuccie hexagon whatever 
        normcore bushwick ethical mustache plaid lyft. Chicharrones edison 
        bulb vinyl disrupt tbh glossier, marfa mumblecore four loko +1 leggings.</Body>
      </Introduction>
      <Section>
          <Heading>Just in - Cyborg bears attacking!</Heading>
          <Structure>3</Structure>
          <SupportingImage>
             <img src="/uploadedImages/dev/robots.png?n=3082" alt="Will Robinson"
                  title="Will Robinson"
                  style="width: 680px; height: 283px;"
                  align="left"
                  width="680"
                  height="283"/>
          </SupportingImage>
          <tr>
             <td>
                <a href="http://www.squids-attack/cyb-bears.html">
                   <img src="/uploadedImages/dev/robots.png?n=3082" width="680" alt="Will Robinson"
                        style="border: 0;width: 100%;max-width: 680px;"
                        class="center-on-narrow"/>
                </a>
             </td>
          </tr>
          <tr>
             <td>
                <img src="/uploadedImages/dev/robots.png?n=3082" width="680" alt="Will Robinson"
                     style="border: 0;width: 100%;max-width: 680px;"
                     class="center-on-narrow"/>
             </td>
          </tr>
          <Body>Ugh tacos artisan, single-origin coffee jianbing hoodie skateboard.
         90's unicorn next level fixie. Glossier coloring book drinking vinegar, 
         health goth flexitarian activated charcoal yuccie hexagon whatever normcore 
         bushwick ethical mustache plaid lyft. Chicharrones edison bulb vinyl 
         disrupt tbh glossier, marfa mumblecore four loko +1 leggings. Knausgaard
          af YOLO, direct trade drinking vinegar try-hard williamsburg roof party 
          asymmetrical snackwave waistcoat. Venmo food truck next level raw denim, 
          pabst photo booth quinoa chambray art party hot chicken cliche tote bag 
          polaroid direct trade whatever. Shabby chic lomo locavore slow-carb leggings.</Body>
          <Button>More information</Button>
      </Section>
    </root>