<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="../../../_utils/schema/yaps.rnc" type="application/relax-ng-compact-syntax"?>
<?xml-model href="../../../_utils/schema/yaps.isosch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<?xml-stylesheet type="text/xsl" href="yaps2slidy1.xslt"?>
<!-- $Id: mdh_xsl_conditionals.xml 51709 2026-05-28 23:29:13Z syd $ -->
<TEI xmlns="http://www.wwp.northeastern.edu/ns/yaps" xml:lang="en" version="5.0">
  <teiHeader>
    <fileDesc>
      <titleStmt>
        <title>XSL Conditionals</title>
        <author>Martin Holmes</author>
      </titleStmt>
      <editionStmt>
        <edition>DHSI 2013, University of Victoria</edition>
      </editionStmt>
      <publicationStmt>
        <distributor>Women Writers Project (via website)</distributor>
        <address>
          <addrLine>url:mailto:wwp@northeastern.edu</addrLine>
        </address>
        <date when="2013-06-08"/>
        <availability status="restricted">
          <p>Copyright 2011 Martin Holmes</p>
          <p>This TEI-encoded XML file is available under the terms of the <ref
              target="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons
              Attribution-ShareAlike 3.0 (Unported)</ref> license.</p>
        </availability>
        <pubPlace>Providence, RI USA</pubPlace>
      </publicationStmt>
      <sourceDesc>
        <p>Born digital</p>
      </sourceDesc>
    </fileDesc>
    <revisionDesc>
      <change when="2016-02-15" who="personography.xml#sbauman.emt">
        <list>
          <item>corrected ultimate tutorial example encoding</item>
          <item>tweaked last slide examples (both slide and tutorial)</item>
          <item>added <att>xml:lang</att> of <val>en</val> to root element</item>
          <item>tweaked some wording and examples here and there</item>
        </list>
      </change>
      <change when="2016-01-16" who="personography.xml#ksmith.awh">Added tutorials on all
        slides</change>
      <change when="2011-05-31" who="mdh">Began writing this file.</change>
    </revisionDesc>
  </teiHeader>
  <text>
    <presentation>
      <abstract>
        <p>This tutorial is designed as a supplement to the XSL Conditionals tutorial, which covers
          two conditional branching structures in detail, but does not cover XPath if-then-else.
          XPath if-then-else is explained in this tutorial on slide 4. An example of a possible
          solution to an XSLT task using XPath if-then-else is given on slide 5.</p>
      </abstract>
      <section>
        <head>XSL Conditionals: ifs, chooses, whens and otherwises</head>
        <slide>
          <list type="incremental">
            <item>Almost all programming languages have <emph>conditional branching</emph>
              structures.</item>
            <item>XSL has two: <tag>xsl:if</tag> and <tag>xsl:choose</tag>.</item>
            <item>XPath also has the <code>if-then-else</code> structure.</item>
          </list>
        </slide>
        <tutorial>
          <p>This tutorial is designed as a supplement to the <ref
              target="../xslt_intro/conditionals_tutorial.xhtml">XSL Conditionals</ref> tutorial,
            which covers <gi>xsl:if</gi> and <gi>xsl:choose</gi> in detail, but does not cover XPath
            if-then-else. XPath if-then-else is explained in this tutorial on slide 4. An example of
            a possible solution to an XSLT task using XPath if-then-else is given on slide 5.</p>
        </tutorial>
      </section>

      <section>
        <head>Using <tag>xsl:if</tag></head>
        <slide>
          <p>A simple example: using <tag>xsl:if</tag> to pluralize <q>author</q> if there are
            multiple authors.</p>
          <eg><![CDATA[
Author<xsl:if test="count($docAuthors/author) gt 1">s</xsl:if>: 
<xsl:for-each select="$docAuthors/author">
  <xsl:value-of select="forename" /> <xsl:value-of select="surname" /><br/>
</xsl:for-each>
                 ]]></eg>
          <list type="incremental">
            <item>Let's look at this in detail: <eg><![CDATA[
<]]><hi rend="css(color: blue;)">xsl:if </hi><![CDATA[ ]]><hi style="color: red;"
                  >test=</hi><![CDATA["]]><hi rend="css(color: darkgreen;)"
                  >count($docAuthors/author) gt 1</hi><![CDATA[">s</]]><hi rend="css(color: blue;)"
                  >xsl:if</hi><![CDATA[>
            ]]></eg>
            </item>
            <item>The <att>test</att> attribute contains an <emph>XPath expression</emph> which
              evaluates to <code>true()</code> or <code>false()</code>.</item>
            <item>What is inside the <tag>xsl:if</tag> tag is only implemented if it evaluates to
                <code>true()</code>.</item>
          </list>
        </slide>
        <tutorial>
          <p>The example above uses <gi>xsl:if</gi> to pluralize the word "author" if there is more
            than one listed. The <att>test</att> attribute on <gi>xsl:if</gi> asks the XSLT
            processor to count the number of <gi>author</gi> elements within <gi>docAuthor</gi>, and
            then to compare that number to one. If the number is greater than one, the text <q>s</q>
            is added after after "Author"</p>
          <p>Every <att>test</att> attribute contains an XPath expression. The expression either
            evaluates as true or as false. If it is true, then the content of <gi>xsl:if</gi> is
            applied. If it is false, nothing is done. </p>
          <p>In this example, the content of <gi>xsl:if</gi> is a simple text node, but we can
            imagine more complex examples like checking if there is an <att>ref</att> on
              <gi>persName</gi>, and if there is, then proceeding with a whole additional snippet of
            code.</p>
        </tutorial>

      </section>

      <section>
        <head>Using <tag>xsl:choose</tag></head>
        <slide>
          <list type="incremental">
            <item>Sometimes you need to handle two or more conditions. This is done with
                <tag>xsl:choose</tag>:</item>
            <item>
              <eg><![CDATA[
<div>      
  <head>DHSI Dress Code</head>
  <]]><hi rend="css(color: maroon;)">xsl:choose</hi><![CDATA[>
      <]]><hi rend="css(color: blue;)">xsl:when </hi><![CDATA[ ]]><hi style="color: red;"
                  >test=</hi><![CDATA["]]><hi rend="css(color: darkgreen;)">surname='Bauman'</hi><![CDATA[">
                tie, no footwear
      </]]><hi rend="css(color: blue;)">xsl:when</hi><![CDATA[>
      <]]><hi rend="css(color: blue;)">xsl:when </hi><![CDATA[ ]]><hi style="color: red;"
                  >test=</hi><![CDATA["]]><hi rend="css(color: darkgreen;)">surname='Holmes'</hi><![CDATA[">
                footwear, no tie
      </]]><hi rend="css(color: blue;)">xsl:when</hi><![CDATA[>
      <]]><hi rend="css(color: blue;)">xsl:otherwise</hi><![CDATA[>
                unpredictable
      </]]><hi rend="css(color: blue;)">xsl:otherwise</hi><![CDATA[>
  </]]><hi rend="css(color: maroon;)">xsl:choose</hi><![CDATA[>
</div> 

]]></eg>
            </item>
            <item>The processor looks at each <tag>xsl:when</tag> in turn; when it finds one whose
                <att>test</att> evaluates to <code>true()</code>, it processed that one, and then
              exits the <tag>xsl:choose</tag>.</item>
            <item>If none are true, it processes <tag>xsl:otherwise</tag> (assuming there is
              one).</item>
          </list>
        </slide>
        <tutorial>
          <p>The <gi>xsl:if</gi> element works well if you only want to apply constructors (i.e., do
            things) when a simple test proves to be true (or false, as you can always reverse the
            logic of a test by wrapping it in a <code>not()</code> function), and don't want to do
            anything if said simple test proves to be false (or true). But there may be instances in
            which you want to do something when the test evaluates as true, and something else when
            it evaluates as false. Indeed, you may want to apply rules to things that aren't even
            simple true/false statements.</p>
          <p>In these cases, you will want to use <gi>xsl:choose</gi>, which allows you to specify
            rules for several different scenarios. The children of <gi>xsl:choose</gi> are one or
            more <gi>xsl:when</gi> statements followed by zero or one <gi>xsl:otherwise</gi>
            statement.</p>
          <p>The processor evaluates the <att>test</att> attribute of each <gi>xsl:when</gi> in
            order. If the XPath expression is false, the processor goes to the next
              <gi>xsl:when</gi>. When the processor finds that the <att>test</att> of an
              <gi>xsl:when</gi> is true, it performs the content of that <gi>xsl:when</gi>,
              <emph>and stops looking</emph> at the rest of the <gi>xsl:when</gi>s and the
              <gi>xsl:otherwise</gi> (if there even is one).</p>
          <p>If none of the <att>test</att>s for <gi>xsl:when</gi> are true, then the processor will
            execute the content of the <gi>xsl:otherwise</gi> (if there is one).</p>
          <p>Thus at most <emph>one</emph> child of an <gi>xsl:choose</gi> is executed. If there is
            no <gi>xsl:otherwise</gi> child of the <gi>xsl:choose</gi>, it is possible that
              <emph>no</emph> child of the <gi>xsl:choose</gi> will be executed.</p>
        </tutorial>
      </section>

      <section>
        <head>Using XPath <code>if-then-else</code></head>
        <slide>
          <list type="incremental">
            <item>If your condition is very simple, and the processing you want to do as a result of
              it does not involve creating elements or attributes, then you can just use an
                <code>if-then-else</code> structure in XPath:</item>
            <item>
              <eg><![CDATA[<]]><hi rend="css(color: blue;)">xsl:value-of </hi><![CDATA[ ]]><hi
                  style="color: red;">select=</hi><![CDATA["
              if (]]><hi rend="css(color: maroon;)">count($docAuthors/author) gt 1</hi><![CDATA[) then 
                  ]]><hi rend="css(color: darkgreen;)">'Authors: '</hi><![CDATA[
              else 
                  ]]><hi rend="css(color: darkgreen;)">'Author: '</hi><![CDATA[
              "/>]]></eg>
            </item>
          </list>
        </slide>
        <tutorial>
          <p>As we saw in the slide explaining how to use <gi>xsl:if</gi>, this slide shows a simple
            example of using the XPath if-then-else structure to pluralize author is there is more
            than one <gi>author</gi> element within <gi>docAuthor</gi>.</p>
          <list>
            <item>In this case the <gi>xsl:value-of</gi> element has a <att>select</att> attribute
              that contains an XPath <emph>if-then-else</emph> construct</item>
            <item>The first condition, <emph>if</emph>, contains the XPath expression: <code>count(
                $docAuthors/author ) gt 1</code>.</item>
            <item>This XPath expression starts by calling the function <code>count()</code>, which
              counts the number of items in its argument sequence. In this case, the argument to
                <code>count()</code> is the sequence of child <gi>author</gi> elements found in the
              variable <code>$docAuthors</code> (presumably the list of authors of the current
              document :-)</item>
            <item>The XPath expression then asks the question <q>is this (the value of the
                  <code>count()</code> function) greater than one?</q>. That's what the
                <code>gt</code> means: <q>greater than</q>. </item>
            <item>The answer to that question (<q>is this (the value of the <code>count()</code>
                function) greater than one?</q>) is either <code>true()</code> or
                <code>false()</code>.</item>
            <item>If the XPath expression after <emph>if</emph> is true, then the content following
                <emph>then</emph> is returned. Otherwise, the content following <emph>else</emph> is
              returned. In this example, if there is more than one <gi>author</gi>, then the
              condition will return the text: <quote>Authors: </quote>; if not, then it will return
              the text: <quote>Author: </quote></item>
          </list>
          <p>XPath if-then-else is useful for when your condition is very simple, and the processing
            you want to do as a result of it does not involve creating XML constructs like elements
            and attributes. Also, unlike <gi>xsl:if</gi>, XPath if-then-else allows you to process
            conditions for both the <code>true()</code> or <code>false()</code> evaluation of an
            XPath expression.</p>
        </tutorial>
      </section>

      <section>
        <head>XSL Conditionals: Task</head>
        <slide>
          <p>Here's a simple task you can try:</p>
          <list type="incremental">
            <item>Open <title>Places</title> XML (<ref target="../../demos/xslt_intro/places.xml"
                >demos/xslt_intro/places.xml</ref>).</item>
            <item>Open XSLT (<ref target="../../demos/xslt_intro/mdh_xsl_conditionals.xsl"
                >demos/xslt_intro/mdh_xsl_conditionals.xsl</ref>).</item>
            <item>Switch to the XSLT debugger in oXygen.</item>
            <item>Follow the instructions in the XSLT file. You'll need to write some conditional
              XSLT code to complete the task.</item>
          </list>
        </slide>
        <tutorial>
          <p>Download the two linked files and open them in the XSLT Debugger in Oxygen. If you
            haven’t used the XSLT Debugger view before, please refer to the the tutorial here: <ref
              target="../xslt/djb_transformations-in-oxygen.xml">XSLT Debugger</ref>.</p>
          <p>On the next slide are possible solutions to the task proposed in the XSLT document
            using <gi>xsl:choose</gi> and the XPath if-then-else structure.</p>
        </tutorial>
      </section>

      <section>
        <head>XSL Conditionals: Task</head>
        <slide>
          <p>This is one possible solution:</p>
          <eg><![CDATA[<xsl:template match="/">
  <xsl:for-each select="//place">
    <xsl:value-of select="placeName" />
    <!-- insert a space: -->
    <xsl:text>&#x20;</xsl:text>
    ]]><hi style="color:red;">&lt;!-- insert correct word based on &lt;location>: -->
              &lt;xsl:choose> &lt;xsl:when test="count( location/geo ) eq 1">(point)&lt;/xsl:when>
              &lt;xsl:when test="location[ @type eq 'path' ]">(path)&lt;/xsl:when>
              &lt;xsl:otherwise>(polygon)&lt;/xsl:otherwise> &lt;/xsl:choose></hi><![CDATA[
    <!-- insert a newline: -->
    <xsl:text>&#x0A;</xsl:text>
  </xsl:for-each>
</xsl:template>]]></eg>
        </slide>
        <tutorial>
          <p>As always, there is more than one way to go about this. The solution here, using
              <gi>xsl:choose</gi>, is one way to produce the desired output, conditionally based on
            the input <gi>location</gi>. We might also use the XPath if-then-else structure to
            accomplish the same thing:</p>
          <eg><![CDATA[<xsl:template match="/">
  <xsl:for-each select="//place">
    <xsl:value-of select="placeName"/>
    <!-- insert a space: -->
    <xsl:text>&#x20;</xsl:text>
    ]]><hi style="color: red;">&lt;!-- insert correct word based on &lt;location> --><![CDATA[
    ]]>&lt;xsl:value-of select=" if ( count( location/geo ) eq 1 ) then '(point)' else if (
              location[@type eq 'path'] ) then '(path)' else '(polygon)' "/></hi><![CDATA[
    <!-- insert a newline: -->
    <xsl:text>&#x0A;</xsl:text>
  </xsl:for-each>
</xsl:template>]]></eg>
          <!--
<p>It is also perfectly reasonable to divide up the work into separate
templates to accomplish the same thing:</p>
<eg><![CDATA[<xsl:template match="/">
    <xsl:for-each select="//place">
      <xsl:value-of select="placeName"/>
      <!- - insert a space: - ->
      <xsl:text>&#x20;</xsl:text>
      <!- - insert correct word based on <location> - ->
      <xsl:apply-templates select="location"/>
      <!- - insert a newline: - ->
      <xsl:text>&#x0A;</xsl:text>
    </xsl:for-each>
  </xsl:template>
  
  <xsl:template match="location[ count( geo ) eq 1 ]">
    <xsl:text>(point)</xsl:text>
  </xsl:template>
  
  <xsl:template match="location[ @type eq 'path']">
    <xsl:text>(path)</xsl:text>
  </xsl:template>

  <xsl:template match="location">
    <xsl:text>(polygon)</xsl:text>
  </xsl:template>]]></eg>
<p>This is tenable because we know that the input file does not
have any cases of a <gi>location</gi> that has a <att>type</att>
of <val>path</val> <emph>and</emph> has more than one <gi>geo</gi>
child. If such a <gi>location</gi> were to occur, we would get an
error because the poor XSLT engine would not know which template
to use.</p>
-->
          <list>
            <head>This tutorial is complete, please see links below to continue:</head>
            <item><ref target="../publication/xtf_teibp_tutorial_00.xhtml">Proceed to next tutorial
                in Transformation and Publication Primer</ref></item>
            <item><ref target="../../../../resources/transformation.html">Return to Transformation
                and Publication Primer</ref></item>
            <item><ref target="../../../../resources/tutorial_main.html">Return to main tutorial
                page</ref></item>
          </list>
        </tutorial>
      </section>

    </presentation>
  </text>
</TEI>
