I am trying to convert a cals table to a series of lists and I am struggling with grouping.
The table consists of a couple of heading rows (thead/row), and a bunch of body rows (tbody/row). There are 2 types of body row: a) a standard data row, and b) a straddle heading row which 'break up' the table visually delineating each section.
I want to create a new list for each section and so am using
<xsl:for-each-group group-starting-with="row/entry/hd4" select="table/tgroup/tbody/row">
I have tried various options in the group-starting-with attribute including
entry/@nameend
entry[@nameend]
entry/hd4
entry[hd4]
From my background reading on this, I note that the value should be a pattern, and not a condition, so I'm guessing the predicates are wrong.
<anch fac="yes">
<p/>
<calstable>
<table frame="none">
<tgroup cols="4" colsep="0" rowsep="0">
<colspec colname="1" colnum="1" colwidth="39pt" align="center"/>
<colspec colname="2" colnum="2" colwidth="39pt" align="center"/>
<colspec colname="3" colnum="3" colwidth="45pt" align="center"/>
<colspec colname="4" colnum="4" colwidth="33pt" align="center"/>
<thead>
<row valign="bottom">
<entry align="center">Anchorage</entry>
<entry align="center">Lat.</entry>
<entry align="center">Long.</entry>
<entry align="center">Draft</entry>
</row>
<row valign="bottom">
<entry align="center">No.</entry>
<entry align="center">(S)</entry>
<entry align="center">(E)</entry>
<entry align="center">(m.)</entry>
<entry> </entry>
</row>
</thead>
<tbody>
<row>
<entry align="left" namest="1" nameend="4">
<hd4>Outer</hd4>
</entry>
</row>
<row>
<entry>O1</entry>
<entry>17° 57.0′</entry>
<entry>122° 04.0′</entry>
<entry>9.5</entry>
</row>
<row>
<entry>O2</entry>
<entry>17° 56.0′</entry>
<entry>122° 04.0′</entry>
<entry>9.5</entry>
</row>
<row>
<entry>O3</entry>
<entry>17° 55.0′</entry>
<entry>122° 04.0′</entry>
<entry>7.0</entry>
</row>
<row>
<entry align="left" namest="1" nameend="4">
<hd4>Gantheaume Bay</hd4>
</entry>
</row>
<row>
<entry>G1</entry>
<entry>17° 56.5′</entry>
<entry>122° 10.0′</entry>
<entry>8.0</entry>
</row>
<row>
<entry>G2</entry>
<entry>17° 55.0′</entry>
<entry>122° 10.0′</entry>
<entry>8.0</entry>
</row>
<row>
<entry>G2</entry>
<entry>17° 56.5′</entry>
<entry>122° 09.5′</entry>
<entry>8.0</entry>
</row>
</tbody>
</tgroup>
</table>
</calstable>
</anch>
and the xslt as follows
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.0"
>
<xsl:output indent="yes" method="xml" standalone="yes"/>
<xsl:template match="/">
<anch>
<xsl:apply-templates select="anch/calstable" mode="cals-to-list"/>
</anch>
</xsl:template>
<xsl:template match="calstable[//thead[count(row) = 2]]" mode="cals-to-list">
<xsl:for-each-group group-starting-with="row/entry/hd4" select="table/tgroup/tbody/row">
<list>
<xsl:apply-templates select="current-group()" mode="cals-to-list"/>
</list>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="tbody/row[entry[@nameend]]" mode="cals-to-list">
<xsl:variable name="lhtype">
<xsl:choose>
<xsl:when test="entry/hd2">2</xsl:when>
<xsl:when test="entry/hd3">3</xsl:when>
<xsl:when test="entry/hd4">4</xsl:when>
<xsl:otherwise>2</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<lh lhtype="{$lhtype}">
<xsl:apply-templates select="entry[@nameend]" mode="cals-to-list"/>
</lh>
</xsl:template>
<xsl:template match="tbody/row[not(entry[@nameend])]" mode="cals-to-list">
<li>
<xsl:apply-templates select="entry" mode="cals-to-list"/>
</li>
</xsl:template>
<xsl:template match="row/entry[@nameend]" mode="cals-to-list">
<xsl:value-of select="*/text()"/>
</xsl:template>
<xsl:template match="row/entry[not(@nameend)]" mode="cals-to-list">
<xsl:variable name="pos" select="position()"/>
<xsl:variable name="thead-rows" select="count(ancestor::*[local-name()='tgroup']/thead/row)"/>
<xsl:variable name="top-line" select="normalize-space(ancestor::*[local-name()='tgroup']/thead/row[position() != $thead-rows]/entry[$pos]/text())"/>
<xsl:variable name="bot-line" select="normalize-space(ancestor::*[local-name()='tgroup']/thead/row[$thead-rows]/entry[$pos]/text())"/>
<xsl:variable name="unit" select="normalize-space(substring-before(substring-after($bot-line,'('),')'))"/>
<xsl:value-of select="$top-line"/><xsl:text> </xsl:text><xsl:value-of select="."/><xsl:text> </xsl:text><xsl:value-of select="$unit"/><xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
This is what I get
<anch xmlns:xs="http://www.w3.org/2001/XMLSchema">
<list>
<lh lhtype="4">Outer</lh>
<li>Anchorage O1 Lat. 17° 57.0′ S Long. 122° 04.0′ E Draft 9.5 m. </li>
<li>Anchorage O2 Lat. 17° 56.0′ S Long. 122° 04.0′ E Draft 9.5 m. </li>
<li>Anchorage O3 Lat. 17° 55.0′ S Long. 122° 04.0′ E Draft 7.0 m. </li>
<lh lhtype="4">Gantheaume Bay</lh>
<li>Anchorage G1 Lat. 17° 56.5′ S Long. 122° 10.0′ E Draft 8.0 m. </li>
<li>Anchorage G2 Lat. 17° 55.0′ S Long. 122° 10.0′ E Draft 8.0 m. </li>
<li>Anchorage G2 Lat. 17° 56.5′ S Long. 122° 09.5′ E Draft 8.0 m. </li>
</list>
</anch>
But I would expect the list to break and restart a new list just before the Gantheaume Bay entry.
Can someone explain where I've gone wrong and what the correct pattern should be?
TIA
You are selecting row
elements with the xsl:for-each-group
and so the group-starting-with
must also be a row
element (representing the first one each in group).
Change your xsl:for-each-group
to this...
<xsl:for-each-group group-starting-with="row[entry/hd4]" select="table/tgroup/tbody/row">