This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Numbering Grouped Child Elements
- To: Jake Stevenson <Jake dot Stevenson at dacg dot com>
- Subject: Re: [xsl] Numbering Grouped Child Elements
- From: Jeni Tennison <mail at jenitennison dot com>
- Date: Wed, 31 Jan 2001 12:54:56 +0000
- CC: "'XSL-List at lists dot mulberrytech dot com'" <XSL-List at lists dot mulberrytech dot com>
- Organization: Jeni Tennison Consulting Ltd
- References: <D44DD97EEEA7D41191340008C75D0F5E169B1C@dahouexch01.dacg.com>
- Reply-To: xsl-list at lists dot mulberrytech dot com
Hi Jake,
> I'm able to group the elements so that the output looks like this:
>
> Complete the following field(s):
> User
> Password
> Click OK.
> Complete the following field(s):
> Item Number
>
> I used the following XSLT to accomplish that:
[snip]
I don't know which processor you're using, but when I try your XSLT
with Saxon, I get:
Complete the following fields:
User
Password
Click OK.
Item Number
So I don't think that the XSLT you provided gives the grouping you
want anyway.
> Now, I need to number the groups so that the output looks like this:
>
> 1. Complete the following field(s):
> User
> Password
> 2. Click OK.
> 3. Complete the following field(s):
> Item Number
>
> Is this possible using <xsl:number/>? Or do I need to seek some
> other solution?
xsl:number is really designed for numbering things according to their
position in the source XML. That isn't particularly what you want to
do here - you're after their position in the result tree. You *can*
use xsl:number to do this, but it may not be worth it...
Basically, you want to have numbered instructions for (a) any
Button_Click elements and (b) any Data_Entry elements that aren't
immediately preceded by a Data_Entry element. The latter is the
trickier to do, but you can find out whether the immediately preceding
element is a Data_Entry element with the test:
preceding-sibling::*[1][self::Data_Entry]
So, if the current node is the Steps element, you can get a node set
of the relevant Button_Click and Data_Entry elements with:
Button_Click |
Data_Entry[not(preceding-sibling::*[1][self::Data_Entry])]
You could apply templates to these elements:
<xsl:template match="Steps">
<table>
<xsl:apply-templates
select="Button_Click |
Data_Entry[not(preceding-sibling::*[1][self::Data_Entry])]" />
</table>
</xsl:template>
In that case, their position() is the number that you're after and
each of the templates has to generate the relevant row(s). Again,
the Button_Click elements are easier to deal with:
<xsl:template match="Button_Click">
<tr>
<td><xsl:value-of select="position()" />.</td>
<td>Click <xsl:apply-templates select="Button_Image" />.</td>
<td />
</tr>
</xsl:template>
For the Data_Entry elements, the stylesheet design so far means you'll
only ever have a template applied to the Data_Entry element (in this
default mode) if it's the first one in a data entry group. You can get
the others in the group by recursing over them, applying templates in
a different mode to give the names of the fields.
<xsl:template match="Data_Entry">
<tr>
<td><xsl:value-of select="position()" />.</td>
<td colspan="2">Complete the following fields:</td>
</tr>
<xsl:apply-templates select="." mode="field-name" />
</xsl:template>
<xsl:template match="Data_Entry" mode="field-name">
<tr>
<td />
<td colspan="2">
<span class="Field_Name">
<xsl:value-of select="Field_Name" />
</span>
</td>
</tr>
<xsl:apply-templates
select="following-sibling::*[1][self::Data_Entry]"
mode="field-name" />
</xsl:template>
If you wanted to take advantage of xsl:number's formatting facilities,
then you can do something like:
<xsl:number value="position()" format="I." />
instead of:
<xsl:value-of select="position()" />
to get the sequence I., II., III., and so on rather than 1, 2, 3.
I hope that helps,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list