RE: [xsl] Answers to review questions in "Beginning XSLT": Chapter 10

Subject: RE: [xsl] Answers to review questions in "Beginning XSLT": Chapter 10
From: "Lars Huttar" <lars_huttar@xxxxxxx>
Date: Fri, 21 Mar 2003 15:20:07 -0600
Jeni wrote:
  Lars wrote:
> > 2. What format can the values of ID attributes take?
> >
> > Answer:
> > They have to be XML Names, which means they must start with a
> > letter, underscore, or colon, and contain only "alphanumeric"
> > characters (which include '.' | '-' | '_' | ':' plus other similar
> > punctuation in Unicode). In particular, no spaces are allowed.
> 
> There are a couple of things here. You say "plus other similar
> punctuation in Unicode". Actually, XML names can only include the
> punctuation characters you list: '.', '-', '_' and ':'.

Hmm.  I'm looking at the W3C XML 1.0 spec (Second Edition).  Admittedly
it does say at first, "Definition: A Name is a token beginning with a
letter or one of a few punctuation characters, and continuing with letters,
digits, hyphens, underscores, colons, or full stops, together known as name
characters."  However, that's apparently a simplified summary... 
the production rules for Name and NameChar, shown a couple of paragraphs
later,

  Name     ::=    (Letter | '_' | ':') (NameChar)* 
  NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender 

make it clear that certain other Unicode characters are allowed, e.g. diacritics
(such as #x0300) and punctuation akin to hyphens (such as #x00B7).

> The ':'
> character should not be used in IDs nowadays because the Namespaces in
> XML Rec. stated that you should use NCNames instead of full XML Names.
> NCNames (non-colonised names) can't contain a colon.

Good point.

> > 7. Construct a stylesheet that groups <Film> elements by 
> their <Year>
> >    children and by their rating attributes.
> >
> > Answer:
> 
> That looks good (I assume it worked!). Another challenge is a
> stylesheet that will group first by Year and then (within that) by
> rating. [I think that's what I meant by the question, but I admit that
> it's not worded clearly.]

You don't want much, do you?  :-)

Well, that would make sense given that the chapter takes pains to
explain multi-level grouping.  Guess I chose to interpret the question
the lazy way.  :-)

OK, here's the revised stylesheet.
You're right of course, it was good to have the exercise of putting this
kind of grouping into practice.  My brain feels like it's been stretched.

Lars


<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0">

  <xsl:key name="filmsByYear" match="Film" use="Year" />
  <xsl:key name="filmsByYearAndRating" match="Film" use="concat(Year, '+', @rating)" />

  <xsl:template match="/">
    <html>
      <head>
        <style>
          .filmname {
             font-style: italic
          }
        </style>
      </head>
      <body>
        <h1>Films, by Year</h1>
        <xsl:apply-templates select="Films/Film[generate-id() =
                                     generate-id(key('filmsByYear', Year)[1])]"
                             mode="YearList">
          <xsl:sort select="Year" data-type="number"/>
        </xsl:apply-templates>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="Film" mode="YearList">
    <h2><xsl:value-of select="Year" /></h2>
    <xsl:apply-templates select="key('filmsByYear', Year)
                                 [generate-id() =
                                  generate-id(key('filmsByYearAndRating',
                                                  concat(Year, '+', @rating))[1])]"
                         mode="YearRatingList">
      <xsl:sort select="@rating" data-type="number" order="descending" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="Film" mode="YearRatingList">
    <h3><xsl:value-of select="@rating" /> stars</h3>
    <xsl:apply-templates select="key('filmsByYearAndRating',
                                     concat(Year, '+', @rating))"
                         mode="Detail">
      <xsl:sort select="Name" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="Film" mode="Detail">
    <p>
      <span class="filmname"><xsl:value-of select="Name" /></span>, 
      <xsl:value-of select="Year" />.  Stars:
      <xsl:value-of select="@rating" />
    </p>
  </xsl:template>

</xsl:stylesheet>


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


Current Thread