Control Flow Statements

Control flow statements in XSL break up the flow of execution, top to bottom by default, by employing decision making and looping. Looping allows execution of identical pieces of code for multiple items, while conditional statements enable you to define behaviours specific to particular input values.

for-each Loop

<books>
  <book>
    <author>Brian Christian</author>
    <title data-type="string">The Most Human Human</title>
    <pages data-type="number">303</pages>
  </book>
  <book>
    <author>Aldous Huxley</author>
    <title data-type="string">Brave New World</title>
    <pages data-type="number">268</pages>
  </book>
  <book>
    <author>Ian Goodfellow</author>
    <title data-type="string">Deep Learning</title>
    <pages data-type="number">787</pages>
  </book>
</books>

Given the above set of data, a for-each loop listing authors of all the individual books might look like this:

<xsl:for-each select="/books/book">
  <fo:block><xsl:value-of select="author" /></fo:block>
</xsl:for-each>

if and choose: Conditional Block Statements

There are basically two conditional block statements:

  • a unary if
  • an if -> else if -> else or switch sort of statement, depending on how you look at it
<!-- declare boolean variables -->
<xsl:variable name="isMine" select="true()" />
<xsl:variable name="isYours" select="false()" />

<!-- a unary "if" statement -->
<xsl:if test="$isMine">
  <fo:block>This seems to be mine!</fo:block>
</xsl:if>

<!-- a `choose`, `if -> else-if -> else` sort of statement -->
<xsl:choose>
  <xsl:when test="$isYours">
    <fo:block>Yours</fo:block>
  </xsl:when>
  <xsl:when test="$isMine">
    <fo:block>Mine</fo:block>
  </xsl:when>
  <xsl:otherwise>
    <fo:block>Someone else's</fo:block>
  </xsl:otherwise>
</xsl:choose>

The above yields the following results:

This seems to be mine!
Mine

Both statements are fairly self-explanatory. The code inside the unary if is executed only if the expression inside the test attribute evaluates to true. Regarding the choose block: only one branch is ever executed, leaving any potential further truthful branches untouched.

if shorthand

The block statements above are perfect for more complicated conditionals but how about simple if-else statements? There's got to be a better way, right? Well, if you make one, there is.

Officially, the following if shorthand should work out of the box:

<!-- a simple "if shorthand" conditional inside a `value-of` -->
<xsl:variable name="isMine" select="true()" />

<fo:block>
  <xsl:value-of select="if $isMine then 'is mine' else 'is not mine'" />
</fo:block>

... unfortunately though, more often than not, it either does not compile or does not produce the desired results when processed by BI Publisher. Do not ask me why, I have no clue.

Anyway, the problem can be circumvented with the following user-defined function:

<!-- `if-else` shorthand helper function -->
<xsl:function name="utils:ifElse">
  <xsl:param name="condition" />
  <xsl:param name="true" />
  <xsl:param name="false" />
  <xsl:variable name="result" select="if ($condition) then $true else $false" />

  <xsl:value-of select="$result" />
</xsl:function>

From now on, writing short if-else statements is a piece of cake:

<xsl:variable name="isMine" select="true()" />
<fo:block>
  <xsl:value-of select="utils:ifElse($isMine, 'is mine', 'is not mine')" />
</fo:block>

Honestly, even if the official if shorthand worked, I much prefer the user-defined one.

results matching ""

    No results matching ""