[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Answers to review questions in "Beginning XSLT": Chapter 5


Subject: Re: [xsl] Answers to review questions in "Beginning XSLT": Chapter 5
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Wed, 12 Mar 2003 13:08:53 +0000

Hi Lars,

> For now I'm omitting the questions themselves, since I don't yet
> have explicit permission to copy them. (Jeni, would that be OK?)

Yes, I'm sure that would be fine. It would also mean that people who
don't have the book are able to understand what you're answering.

> 1. No nodes match the select pattern, so no templates get applied,
>    so there is no output for that apply-templates.

That's correct, though it would be more accurate to say that "no nodes
get selected by the select expression". Remember that the select
attribute (on <xsl:apply-templates>, and elsewhere) is for *selecting*
things with an *expression* and the match attribute (on <xsl:template>
and elsewhere) is for *matching* things with a *pattern*.

> 2. Use one template with match="Description//Film", and another with
>    match="Channel/Film".  Or use match="Film" for one of them, and
>    the more specific match for the other.

That's right.

> 3. This code produces a <div> element with contents as follows:
>    if there are Film children of the current node, they are processed
>    with xsl:apply-templates; otherwise, the message "No films..."
>    is included.

Right.

> 4. Rewriting of preceding code using <xsl:choose> instead of <xsl:if>:
>
>   <div>
>     <xsl:choose>
>          <xsl:when test="Film">
>         <xsl:apply-templates select="Film" />
>       </xsl:when>
>       <xsl:otherwise>
>         No films showing on this channel.
>       </xsl:otherwise>
>     </xsl:choose>
>   </div>
>
>     The advantage of the latter form is that if there are no Film
>     children of the current node, <xsl:apply-templates> doesn't get
>     evaluated.  Also, it may be a little more clear to the human reader
>     that there are two mutually exclusive possibilities for the <div>
>     elements contents: the results of applying templates to "Film" children,
>     and the "No films..." message.
>
>     The advantage of the <xsl:if> form is that it is shorter, and for
>     that reason perhaps easier to read.

Yep. Another advantage with the <xsl:choose> form is that it makes it
easier to add an element around the results of processing the <Film>
elements:

  <div>
    <xsl:choose>
      <xsl:when test="Film">
        <table>
          <xsl:apply-templates select="Film" />
        </table>
      </xsl:when>
      <xsl:otherwise>
        No films showing on this channel.
      </xsl:otherwise>
    </xsl:choose>
  </div>

> 5. The given code inserts a 20x20 icon iff there is a flag attribute
>    on the current node.  There is a specific icon for when the value
>    of the flag attribute is 'favorite', and another for when it is
>    'interesting', and a third for any other value.  If the flag attribute
>    doesn't exist, no icon is inserted.

Right.

> 6. Rewriting of the above "as a sequence of <xsl:if> elements" instead of
>    using <xsl:choose>:  (One could take "sequence" to mean "no nesting",
>    but that would hobble the <xsl:if> and I don't think that was the
>    intent of the question, so I'm going to nest them.)
>
>     <xsl:if test="@flag">
>       <xsl:if test="@flag = 'favorite'">
>         <img src="favorite.gif" alt="[Favorite]" width="20" height="20" />
>       </xsl:if>
>       <xsl:if test="@flag = 'interesting'">
>         <img src="interest.gif" alt="[Interest]" width="20" height="20" />
>       </xsl:if>
>       <xsl:if test="@flag != 'favorite' and @flag != 'interesting'">
>         <img src="flag.gif" alt="[Flagged]" width="20" height="20" />
>       </xsl:if>
>     </xsl:if>

The wrapping <xsl:if> is actually superfluous. @flag = 'favorite' and
@flag = 'interesting' obviously cannot be true if there is not flag
attribute, but it is also the case that @flag != 'favorite' cannot be
true if there is no flag attribute. Perhaps you included the <xsl:if>
so that all the instructions are ignored if the flag attribute doesn't
exist.

> 7. test="Film/@year > 1950"

Right.

> 8. Film[starts-with(Title, 'Romeo')]

Right.

> 9. test="number()"
>    This converts the current node's value to a number, which is then
>    converted to true if non-zero, false if zero or NaN.

Right.

> 10. To test whether the current node's value is a number,
>    use test="number() or number() = 0" which gives the desired result.
>    Is there a simpler way?
>
>    I tried test="number() != NaN" but this was always false (Why?  Is
>      NaN not recognized as the numeric constant?  No, I just learned that
>      it's because NaN is not equal to itself!  See the FAQ,
>      http://www.dpawson.co.uk/xsl/sect2/N5846.html);
>
>    test="number() != 'NaN'" was always true;
>
>    test="number() != number('NaN')" also was always true (see above,
>      NaN is not equal to itself);
>
>    test="string(number()) != 'NaN'" worked but this is not necessarily
>     simpler.  (Btw I see from the FAQ that this is a standard way
>     to check whether a node's value is a number.  There Jeni Tennison
>     also suggests test="@value &lt;= 0 or @value > 0" or
>     test="number(@value) = number(@value)".  However, these both rely
>     on properties of NaN that are not covered in ch. 5.)
>
>    Question: is there a way to represent the numeric constant NaN
>    in an expression?  Apparently the unquoted NaN is not recognized
>    as such; I guess it's interpreted as "the value of the child element
>    named NaN."

You've answered a lot of this yourself in your follow-up mail. I don't
think that there's a right answer to this question: it's more a prompt
to get you to explore the properties of NaN, number(), boolean(),
string() and comparison operators. Personally, I usually use:

  string(number()) != 'NaN'

because it makes it clear what I'm actually testing: number() =
number() is a bit esoteric, even if it is neater.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



Current Thread