|
Subject: RE: [xsl] line numbering From: "Andrew Welch" <ajwelch@xxxxxxxxxxxxxxx> Date: Thu, 5 Aug 2004 15:17:05 +0100 |
> Hi there,
>
> I have some poems marked up something like:
>
> <body>
> <div type="poem">
> <lg type="stanza">
> <l>This is a line of verse</l>
> <l>This is a line of verse</l>
> <l>This is a line of verse</l>
> <l>This is a line of verse</l>
> </lg>
> <lg type="stanza">
> <l>This is a line of verse</l>
> <l>This is a line of verse</l>
> <l>This is a line of verse</l>
> <l>This is a line of verse</l>
> </lg>
> <p>This is something not counted as a line</p>
> <lg type="stanza">
> <l>This is a line of verse</l>
> <l>This is a line of verse</l>
> <l>This is a line of verse</l>
> <l>This is a line of verse</l>
> </lg>
> </div>
> <!-- and multiple poem div's like this here... -->
> </body>
>
> What I want to end up with is for each line to be
> given an @id in the html output like:
> <span id="poem3line10">This is a line of verse <span
> class="number">10</span></span>
>
> <xsl:template match="l">
> <xsl:variable name="linenumber"
> select="count(preceding-sibling::l)+1"/>
> <span class="line"
> id="line{$linenumber}"><xsl:apply-templates /></span> </xsl:template>
>
> But now I need to account for two factors:
> a) that the linenumbering needs to take account of
> the existence of the line-groups (lg) and that it
> should only count back within it's own <div> ancestor.
> b) that I want to number the lines every 5 lines.
>
> Is position() a better way to do this than counting the
> preceding-sibilings?
If you have a large input xml you may find counting preceding siblings
to be expensive, and that its better to do the numbering in a variable
in an initial pass of the xml. For example using this stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output indent="yes"/>
<xsl:key name="lines" match="line" use="@id"/>
<xsl:variable name="lines-rtf">
<xsl:for-each select="/body/div">
<poem number="{position()}">
<xsl:for-each select="lg/l">
<line id="{generate-id()}" number="{position()}"/>
</xsl:for-each>
</poem>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="lines" select="exsl:node-set($lines-rtf)"/>
<xsl:template match="/">
<div>
<xsl:apply-templates select="/body/div/lg/l"/>
</div>
</xsl:template>
<xsl:template match="l">
<xsl:variable name="genId" select="generate-id()"/>
<span>
<xsl:attribute name="id">
<xsl:for-each select="$lines">
<xsl:for-each select="key('lines',$genId)">
<xsl:value-of
select="concat('poem',parent::poem/@number,'line',@number)"/>
</xsl:for-each>
</xsl:for-each>
</xsl:attribute>
<xsl:value-of select="."/>
<xsl:if test="position() mod 5 = 1">
<span class="number">
<xsl:for-each select="$lines">
<xsl:value-of select="key('lines',$genId)/@number"/>
</xsl:for-each>
</span>
</xsl:if>
</span>
</xsl:template>
</xsl:stylesheet>
With your example xml gives this result:
<div>
<span id="poem1line1">This is a line of verse<span
class="number">1</span>
</span>
<span id="poem1line2">This is a line of verse</span>
<span id="poem1line3">This is a line of verse</span>
<span id="poem1line4">This is a line of verse</span>
<span id="poem1line5">This is a line of verse</span>
<span id="poem1line6">This is a line of verse<span
class="number">6</span>
</span>
<span id="poem1line7">This is a line of verse</span>
<span id="poem1line8">This is a line of verse</span>
<span id="poem1line9">This is a line of verse</span>
<span id="poem1line10">This is a line of verse</span>
<span id="poem1line11">This is a line of verse<span
class="number">11</span>
</span>
<span id="poem1line12">This is a line of verse</span>
</div>
(I'm not sure if the line numbering 'every five lines' is correct, I
would guess you would want 1,5,10,15 and so on, so a bit more logic is
required there)
In the stylesheet all the numbering is done using the position()
function as the nested for-each's iterate over xml. The variable is
then queried using a key to maximise performance when accessing the
variable. This minimal stylesheet should be O(2n) complexity, counting
preceding-siblings would be slightly worse in this case.
cheers
andrew
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| RE: [xsl] GUI to Generate Basic XSL, Pieter Reint Siegers | Thread | [xsl] Position() with absolute path, Jeff Cann |
| Re: [xsl] line numbering, Mukul Gandhi | Date | [xsl] Position() with absolute path, Jeff Cann |
| Month |