[xsl] Grouping but not starting at the first element.

Subject: [xsl] Grouping but not starting at the first element.
From: "Kerry, Richard" <richard.kerry@xxxxxxxx>
Date: Tue, 2 Oct 2012 15:58:11 +0000
I have a problem involving groups.  With the advice of the List a few weeks
ago I managed to make a lot of progress on solving a problem by using XSLT
groups.  I'm now back on the issue and have a supplementary problem I need to
solve.

My input XML is shown below.  It represents part of an Excel spreadsheet,
hence the references to rows and columns.

<sheet>
<row row="1">
<column column="1" cell="A1">DDF</column>
<column column="2" cell="B1">AT3G_UP_DN</column>
</row>
<row row="2">
<column column="1" cell="A2">id</column>
<column column="2" cell="B2">name</column>
<column column="3" cell="C2">type</column>
<column column="4" cell="D2">class</column>
<column column="5" cell="E2">caption</column>
<column column="6" cell="F2">value</column>
</row>
<row row="3">
<column column="1" cell="A3">1</column>
<column column="2" cell="B3">Card fail</column>
<column column="3" cell="C3">integer</column>
<column column="4" cell="D3">enum</column>
</row>
<row row="4">
<column column="1" cell="A4"></column>
<column column="2" cell="B4"></column>
<column column="3" cell="C4"></column>
<column column="4" cell="D4"></column>
<column column="5" cell="E4">Card Fail</column>
<column column="6" cell="F4">0</column>
</row>
<row row="5">
<column column="1" cell="A5"></column>
<column column="2" cell="B5"></column>
<column column="3" cell="C5"></column>
<column column="4" cell="D5"></column>
<column column="5" cell="E5">Card OK</column>
<column column="6" cell="F5">1</column>
</row>
<row row="6">
<column column="1" cell="A6">2</column>
<column column="2" cell="B6">SD-SD ARC bypass</column>
<column column="3" cell="C6">integer</column>
<column column="4" cell="D6">enum</column>
</row>
<row row="7">
<column column="1" cell="A7"></column>
<column column="2" cell="B7"></column>
<column column="3" cell="C7"></column>
<column column="4" cell="D7"></column>
<column column="5" cell="E7">Normal</column>
<column column="6" cell="F7">0</column>
</row>
<row row="8">
<column column="1" cell="A8"></column>
<column column="2" cell="B8"></column>
<column column="3" cell="C8"></column>
<column column="4" cell="D8"></column>
<column column="5" cell="E8">Bypass</column>
<column column="6" cell="F8">1</column>
</row>
</sheet>

Rows 1 and 2 are headings.
The subsequent rows are in groups.
Row 3 (with columns 1 to 4) starts a group.  This will generate an "item"
element.
Rows 4 and 5 have columns 5 and 6, and end up as "sub-item" elements which are
children of the most recent "item".
The same relationship holds between row 6 and its children in rows 7 and 8.
ie 6 should generate an "item" and 7 and 8 "sub-item" children.


My stylesheet looks like this :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="xml" indent="yes" />
<xsl:template match="sheet">
<page>
<xsl:for-each-group select="row" group-starting-with="row[column[1][. != '']]"
>
<item name="{column[2]}" row="{@row}" >
<xsl:apply-templates select="current-group()" mode="col-1">
</xsl:apply-templates>
</item>
</xsl:for-each-group>
</page>
</xsl:template>
<!-- row process. Called on row within group. -->
<xsl:template match="row" mode="col-1" >
<xsl:if test="normalize-space(column[5])" >
<sub-item caption="{column[5]}" value="{column[6]}" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>

So I'm grouping based on starting with rows with column[1] not empty.

The result I get is :
<?xml version="1.0" encoding="UTF-8"?>
<page>
<item name="AT3G_UP_DN" row="1"/>
<item name="name" row="2">
<sub-item caption="caption" value="value"/>
</item>
<item name="Card fail" row="3">
<sub-item caption="Card Fail" value="0"/>
<sub-item caption="Card OK" value="1"/>
</item>
<item name="SD-SD ARC bypass" row="6">
<sub-item caption="Normal" value="0"/>
<sub-item caption="Bypass" value="1"/>
</item>
</page>

I understand why I get this.  What I'd like to do is get rid of the items
generated by rows 1 and 2.
These rows represent headings or control information and don't want to get
into the result.

The logic would appear to be something like group-starting-with
row[column[1][. != '']] except for rows 1 and 2.
If this was not using groups I'd just set up a couple of no output templates
for row[1] and row[2], but I'm using a template matching on "sheet" and
scanning the rows using groups so I can't do that (can I ?).

Can anyone advise how to go about achieving this ?  Do I need to add something
to the group spec ?  Do I need to add another template to swallow the unwanted
rows, and if so how, given that the rows are being processed in groups ?

Appreciatively,
Richard.




Richard Kerry
BNCS Engineer
T: +44 (0)20 82259063
M: +44 (0)7812 325518
Room EBX 301, BBC Television Centre, Wood Lane, London, W12 7RJ
richard.kerry@xxxxxxxx
uk.atos.net

This e-mail and the documents attached are confidential and intended solely
for the addressee; it may also be privileged. If you receive this e-mail in
error, please notify the sender immediately and destroy it. As its integrity
cannot be secured on the Internet, the Atos group liability cannot be
triggered for the message content. Although the sender endeavours to maintain
a computer virus-free network, the sender does not warrant that this
transmission is virus-free and will not be liable for any damages resulting
from any virus transmitted.

Current Thread