Producing Lists


The DTD for these documents provides a number of ways of defining lists. For example, an ordered list looks like this:

  <p>The design goals for XML are:</p>   <olist>   <item><p>XML shall be straightforwardly usable over the   Internet.</p></item>   <item><p>XML shall support a wide variety of applications.</p></item>   <item><p>XML shall be compatible with SGML.</p></item>   <item><p>It shall be easy to write programs which process XML   documents,.</p></item>   <item><p>The number of optional features in XML is to be kept   to the absolute minimum, ideally zero.</p></item>   <item><p>XML documents should be human-legible and reasonably   clear.</p></item>   <item><p>The XML design should be prepared quickly.</p></item>   <item><p>The design of XML shall be formal and concise.</p></item>   <item><p>XML documents shall be easy to create.</p></item>   <item><p>Terseness in XML markup is of minimal importance.</p></item>   </olist>  

The rule for ordered lists is interesting, because it uses a recursive named template. The aim here is to decide automatically what kind of numbering to apply to nested levels of list: «1, 2, 3 » for the outermost level, «a, b, c » for the second level, «i, ii, iii » for the third level, and so on.

  <!-- olist: an ordered list -->   <xsl:template match="olist">   <xsl:variable name="numeration">   <xsl:call-template name="list.numeration"/>   </xsl:variable>   <xsl:variable name="type">   <xsl:choose>   <xsl:when test="$numeration='arabic'">1</xsl:when>   <xsl:when test="$numeration='loweralpha'">a</xsl:when>   <xsl:when test="$numeration='lowerroman'">i</xsl:when>   <xsl:when test="$numeration='upperalpha'">A</xsl:when>   <xsl:when test="$numeration='upperroman'">I</xsl:when>   <!-- What!? This should never happen -->   <xsl:otherwise>   <xsl:message>   <xsl:text>Unexpected numeration: </xsl:text>   <xsl:value-of select="$numeration"/>   </xsl:message>   <xsl:value-of select="1"/>   </xsl:otherwise>   </xsl:choose>   </xsl:variable>   <ol class="enum{$type}">   <xsl:apply-templates/>   </ol>   </xsl:template>   <xsl:template name="list.numeration">   <xsl:param name="node" select="."/>   <xsl:choose>   <xsl:when test="$node/ancestor::olist">   <xsl:call-template name="next.numeration">   <xsl:with-param name="numeration">   <xsl:call-template name="list.numeration">   <xsl:with-param name="node" select="$node/ancestor::olist[1]"/>   </xsl:call-template>   </xsl:with-param>   </xsl:call-template>   </xsl:when>   <xsl:otherwise>   <xsl:call-template name="next.numeration"/>   </xsl:otherwise>   </xsl:choose>   </xsl:template>   <xsl:template name="next.numeration">   <xsl:param name="numeration" select="'default'"/>   <xsl:choose>   <!-- Change this list if you want to change the order of numerations -->   <xsl:when test="$numeration = 'arabic'">loweralpha</xsl:when>   <xsl:when test="$numeration = 'loweralpha'">lowerroman</xsl:when>   <xsl:when test="$numeration = 'lowerroman'">upperalpha</xsl:when>   <xsl:when test="$numeration = 'upperalpha'">upperroman</xsl:when>   <xsl:when test="$numeration = 'upperroman'">arabic</xsl:when>   <xsl:otherwise>arabic</xsl:otherwise>   </xsl:choose>   </xsl:template>  

The recursive call on the «list.numeration » template occurs while calculating a parameter to supply to the «next.numeration » template. The way this works is that if the <olist> element has no <olist> ancestor, it sets the number format to «arabic » . If it does have an <olist> ancestor, it calls the «list.numeration » template supplying the first ancestor as a parameter. The «next.numeration » template supplies the next numbering format in the list: if the input is «arabic » , the output is «loweralpha » , and so on.

I must admit this isn't how I would have written it, though everyone is entitled to their own style. In XSLT 2.0 I would probably define a function:

  <xsl:function name="f:olist-format" as="xs:string">   <xsl:param name="node" as="node()"/>   <xsl:sequence   select="('1', 'a', 'i', 'A', 'I') [count($node/ancestor::olist)   mod 5 + 1]"/>   </xsl:function>  

and then write the template rule for <olist> as:

  <xsl:template match="olist">   <ol class="enum{$f:olist-format(.)}">   <xsl:apply-templates/>   </ol>   </xsl:template>  

A reduction from 53 lines to 10 can't be all that bad.




XSLT 2.0 Programmer's Reference
NetBeansв„ў IDE Field Guide: Developing Desktop, Web, Enterprise, and Mobile Applications (2nd Edition)
ISBN: 764569090
EAN: 2147483647
Year: 2003
Pages: 324

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net