Thanks Dimitre for this approach which certainly is more comprehendible
than my original. I can't rely on the number of spaces per indentation
level being consistent, I can only rely on each indentation level having
the same number of spaces. I have made an attempt to adapt your code to
cover that (see below).
Grainne.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:saxon="http://icl.com/saxon"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl saxon">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vSortedRows">
<xsl:apply-templates select="/*/row" mode="sort">
<xsl:sort data-type="number"
select="string-length(substring-before(cell,substring(normalize-space(cell),
1,1)))"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:variable name="vtLevels">
<xsl:call-template name="getLevels">
<xsl:with-param name="pSortedRows"
select="exsl:node-set($vSortedRows)/row"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vLevels" select="exsl:node-set($vtLevels)"/>
<xsl:for-each select="/*/row">
<xsl:variable name="vThisIndent"
select="string-length(substring-before(cell,substring(normalize-space(cell),
1,1)))"/>
<descriptions>
<xsl:call-template name="genDescription">
<xsl:with-param name="pNode" select="."/>
<xsl:with-param name="pRow"
select="position()"/>
<xsl:with-param name="pLevels"
select="$vLevels"/>
<xsl:with-param name="pLevel"
select="$vLevels/level[@indent = $vThisIndent]/@num"/>
</xsl:call-template>
</descriptions>
</xsl:for-each>
</xsl:template>
<xsl:template match="row" mode="sort">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template name="getLevels">
<xsl:param name="pSortedRows" select="/.."/>
<xsl:param name="pLevelNumber" select="1"/>
<xsl:variable name="vThisIndent"
select="string-length(substring-before($pSortedRows[1]/cell,substring(normalize-space($pSortedRows[1]/cell),
1,1)))"/>
<xsl:variable name="vNext"
select="$pSortedRows/following-sibling::row[string-length(substring-before(cell,substring(normalize-space(cell),
1,1))) > $vThisIndent ]" />
<level num="{$pLevelNumber}" indent="{$vThisIndent}"/>
<xsl:if test="$vNext">
<xsl:call-template name="getLevels">
<xsl:with-param name="pSortedRows" select="$vNext"/>
<xsl:with-param name="pLevelNumber"
select="$pLevelNumber + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="genDescription">
<xsl:param name="pNode" select="/.."/>
<xsl:param name="pRow" />
<xsl:param name="pLevel"/>
<xsl:param name="pLevels" select="/.."/>
<xsl:if test="$pLevel > 1">
<xsl:variable name="vindentParent" select="$pLevels/level[@num =
($pLevel - 1)]/@indent"/>
<xsl:variable name="vParent"
select="preceding-sibling::row[ cell[
string-length(substring-before(.,substring(normalize-space(.), 1,1))) =
$vindentParent ] ][1]"/>
<xsl:call-template name="genDescription">
<xsl:with-param name="pNode" select="$vParent"/>
<xsl:with-param name="pRow" select="$pRow"/>
<xsl:with-param name="pLevel" select="$pLevel - 1"/>
<xsl:with-param name="pLevels" select="$pLevels"/>
</xsl:call-template>
</xsl:if>
<description row="{$pRow}" level="{$pLevel}">
<xsl:value-of select="$pNode/cell"/>
</description>
</xsl:template>
</xsl:stylesheet>
<snip/>
Hi Grainne,
It seems to me that the following solution is simpler. It uses a
recursively called named template to generate the descriptions, and
also the fact that the indent for every next level is 3:
<snip/>
=====
Cheers,
Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
__________________________________________________
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list