Solution 1 :

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 &gt; 60">
                        <xsl:text>Slow Burner</xsl:text>
                    </xsl:when>
                    <xsl:when test="$time &gt;= 30 and $time &lt;= 60">
                        <xsl:text>Medium Burner</xsl:text>
                    </xsl:when>
                    <xsl:when test="$time &lt; 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 ifs.

Solution 2 :

It’s been a LONG time since I’ve messed with XSL, but my guess would be that you’re treating a string “30 minutes” as if it were a number: if cooking_time >= 30. If that’s the case, one possible workaround would be to include a numeric duration in an attribute within the XML:

<cooking_time duration="30" unit="minutes">30 minutes</cooking_time>

Also, it may have been a copy/paste issue, but this doesn’t look right:

cooking_Time &gt; -or- > 30 &lt; 60

Problem :

I am trying to dynamically create an additional element based on the content of the cooking
time element. I also Sort recipe data by cooking time and recipe name to display the additional elements.

If the cooking time is greater than sixty minutes, the new element should display the words Slow Burner. If the cooking time is less than or equal to sixty minutes, and greater than or equal to thirty minutes, this new element should display the words Medium Burner. Otherwise, the new element should display the words Quick and Easy.

I am getting a error and I don’t understand why the if statement is not working.

Why?

The XSL is here:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
    xmlns_xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
    <xsl:template match="/collection">
        <html>

        </html>

Comments

Comment posted by zx485

Are you sure that you can use XSLT-2.0? Because it seems that you intend to use your stylesheet in a browser environment…

Comment posted by Lucas

yes I’m sure about the XSLT-2.0. thanks

Comment posted by Michael Kay

You say you’re getting an error, so give us a clue – tell us what the error is. We enjoy solving puzzles, but there’s no need to make them more difficult by withholding information.

Comment posted by zx485

I explicitly asked you if you could use XSLT-2.0, and you said “YES”. Running this stylesheet in Firefox is impossible, because Firefox only supports XSLT-1.0.

Comment posted by zx485

Wait for some minutes…. I’m creating an XSLT-1.0 solution that should work in Firefox.

Comment posted by zx485

I added an XSLT-1.0 solution that should work in Firefox. Chrome is dubious, still.

Comment posted by zx485

unit="minutes"

Comment posted by duration

A standard way to codify minutes would be the time

Comment posted by faculty.madisoncollege.edu/schmidt/xml/xmlcond.html

hmm I see. ill try this and see if works. I found this from this website

By