You can change your loop to the following. The location of the recipe
element has been changed to be included in the corresponding table
(Of course, change it back if neccessary).
<xsl:for-each select="recipe">
<xsl:sort select="cooking_Time" />
<xsl:variable name="time" select="number(replace(cooking_Time,'minutes',''))" />
<tr>
<td>
<h4>
<xsl:value-of select="title" />
</h4>
</td>
<td>
<recipe>
<xsl:value-of select="if ($time > 60) then 'Slow Burner' else if ($time >= 30) then 'Medium Burner' else 'Quick and Easy'" />
</recipe>
</td>
<td>
<xsl:value-of select="description" />
</td>
<td>
<xsl:value-of select="servings" />
</td>
<td>
<xsl:value-of select="preparetion_Time" />
</td>
<td>
<xsl:value-of select="cooking_Time" />
</td>
<td>
<xsl:value-of select="passiveTime" />
</td>
<td>
<xsl:value-of select="difficulty" />
</td>
<td>
<xsl:for-each select="ingredients">
<xsl:for-each select="ingredient">
<li>
<xsl:value-of select="." />
</li>
</xsl:for-each>
</xsl:for-each>
</td>
</tr>
</xsl:for-each>
This sorts the elements by cooking_Time
(You had the xsl:sort
at the wrong place; it has to immediately follow the xsl:for-each
).
The main logic is in this expression:
<xsl:value-of select="if ($time > 60) then 'Slow Burner' else if ($time >= 30) then 'Medium Burner' else 'Quick and Easy'" />
It outputs the appropriate string depending on the value of the $time
variable (which was created to simplify the expression). The fn:replace
in the variable
<xsl:variable name="time" select="number(replace(cooking_Time,'minutes',''))" />
takes care that the value of the $time
variable is always a number and doesn’t contain the string “minutes”.
If you cannot use XSLT-2.0, you can, alternatively, use this XSLT-1.0 solution:
<xsl:for-each select="recipe">
<xsl:sort select="normalize-space(cooking_Time)" />
<xsl:variable name="time">
<xsl:choose>
<xsl:when test="contains(cooking_Time,'minutes')">
<xsl:value-of select="number(substring-before(cooking_Time,'minutes'))" />
</xsl:when>
<xsl:when test="number(cooking_Time)">
<xsl:value-of select="number(cooking_Time)" />
</xsl:when>
<xsl:otherwise>
<!-- This value represents any items that don't have a 'cooking_Time' value present -->
<xsl:value-of select="0" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<tr>
<td>
<h4>
<xsl:value-of select="title" />
</h4>
</td>
<td>
<recipe>
<xsl:choose>
<xsl:when test="$time > 60">
<xsl:text>Slow Burner</xsl:text>
</xsl:when>
<xsl:when test="$time >= 30 and $time <= 60">
<xsl:text>Medium Burner</xsl:text>
</xsl:when>
<xsl:when test="$time < 30">
<xsl:text>Quick and Easy</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>Undefined</xsl:text>
</xsl:otherwise>
</xsl:choose>
</recipe>
</td>
<td>
<xsl:value-of select="description" />
</td>
<td>
<xsl:value-of select="servings" />
</td>
<td>
<xsl:value-of select="preparetion_Time" />
</td>
<td>
<xsl:value-of select="cooking_Time" />
</td>
<td>
<xsl:value-of select="passiveTime" />
</td>
<td>
<xsl:value-of select="difficulty" />
</td>
<td>
<xsl:for-each select="ingredients">
<xsl:for-each select="ingredient">
<li>
<xsl:value-of select="." />
</li>
</xsl:for-each>
</xsl:for-each>
</td>
</tr>
</xsl:for-each>
It improves the sorting by using normalize-space(...)
and uses xsl:choose
instead of inline if
s.