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

Subject: Re: [xsl] Answers to review questions in "Beginning XSLT": Chapter 9
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Thu, 20 Mar 2003 10:39:40 +0000
Hi Lars,

> 4. What order will the <Program> elements be sorted in with the
> following code?
>
>   <xsl:variable name="series" select="'Series'" />
>   <xsl:apply-templates select="Program">
>     <xsl:sort select="$series" />
>     <xsl:sort select="Title" />
>   </xsl:apply-templates>
>
> Answer:
> They will be sorted by the value of the Title child element.
> The first <xsl:sort> select sorts by the constant 'Series', so all
> nodes will sort equally by this criterion.
> Items that have an empty Title will come before those that have
> a non-empty Title, and will be processed in document order
> (guaranteed?).

The sorting in document order of those elements that have the same
sort key is guaranteed. It's not guaranteed that the elements whose
sort key is an empty string will sort before those whose sort key has
characters in it, but I'd expect most processors would sort like that.

> To get the desired result, i.e. to sort by Series then Title,
> change the first <xsl:sort> element to:
>     <xsl:sort select="*[local-name()=$series]" />
> This assumes we don't care about the namespace of the Series element,
> which seems fine to me.  Otherwise we could insert "and namespace-uri()=''".
> or whatever.

Yes, or do:

  tv:*[local-name() = $series]

where 'tv' was bound to the relevant namespace.

> 5. What does the following piece of code do?
>
>   <xsl:variable name="sortType">
>     <xsl:choose>
>       <xsl:when test="$sortBy = 'rating'">number</xsl:when>
>       <xsl:otherwise>text</xsl:otherwise>
>     </xsl:choose>
>   </xsl:variable>
>   <xsl:apply-templates select="Program">
>     <xsl:sort select="@rating[$sortBy = 'rating'] |
>                       Series[$sortBy = 'series'] |
>                       Title[$sortBy = 'title']"
>               data-type="${sortType}" />
>   </xsl:apply-templates>
>
> Answer:
>
> It processes the Program child elements, sorted by the value of
> either their @rating attributes, their Series children, or their
> Title children, as determined by the value of the variable $sortBy
> (which is probably [based on] a parameter passed to the stylesheet).
> The <xsl:sort>'s select attribute unions three nodesets, only one of
> which will be non-empty, since $sortBy cannot be equal to more than
> one of 'rating', 'series', or 'title'. (Even if $sortBy is a
> nodeset?) In effect this is a lot like the x ? y : z operator in C
> or the (cond ...) expression in Lisp (without as much
> short-circuiting).

In XPath 2.0, we'll be able to use:

  if      ($sortBy = 'rating') then @rating
  else if ($sortBy = 'series') then Series
  else if ($sortBy = 'title')  then Title

which is clearer and has the advantage that the values that get
selected don't have to be nodes.

> 6. What two ways can you use to generate a number giving the position
>    of a node within the source tree?
>
> Answer:
> position() and <xsl:number>.

position() will only work if you're processing the nodes in document
order. Can you think of another way that will work even if you're
processing the nodes in a different order?

> 8. What does the following piece of code generate?
>
>     <xsl:for-each select="Program">
>       <xsl:variable name="format">
>         <xsl:choose>
>           <xsl:when test="position() mod 3 = 1">{1}</xsl:when>
>           <xsl:when test="position() mod 3 = 2">[A]</xsl:when>
>           <xsl:otherwise>(i)</xsl:otherwise>
>         </xsl:choose>
>       </xsl:variable>
>       <xsl:number format="{$format}" />
>       ...
>     </xsl:for-each>
>
> Answer:
> It generates a horrible mess where the numbering goes {1}, [B],
> (iii), {4}, [E], (vi), etc. But I'd like to see it switch between
> Greek and Hebrew, Thai and Tamil. :-) (Side note: out of curiosity,
> I tried adding in a fourth format using Unicode Khmer digit one,
> &#x17E1;. XSLT Programmer's Reference says any Unicode digit one
> should work. Saxon processed it properly, generating &#6115; (Khmer
> digit three) for the third item; but IE/MSXML didn't seem to
> recognize &#x17E1 as a digit.)

Hmm... I think that MSXML is non-conformant in that case. The XSLT
spec says:

 "Any token where the last character has a decimal digit value of 1
  (as specified in the Unicode character property database)...
  generates a decimal representation of the number..."

KHMER DIGIT ONE (#x17E1) has a decimal digit value of 1 in the Unicode
character property database, so it should be recognised.

Cheers,

Jeni

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


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


Current Thread