|
Subject: [xsl] Grouping problem. 2.0 From: Dave Pawson <davep@xxxxxxxxxxxxx> Date: Fri, 04 Jul 2008 15:46:34 +0100 |
I want to number the 'blocks' as in 'legal' format 1.1 1.1.1 etc.
Something is wrong with the named template 'number' I'm looking for the set of preceding-siblings between '.' and the preceding-sibling::title with one higher level (@role).
The theory is that recursing on that will enumerate the the 'block' appropriately.
source <book > <title role="1">L1</title>
<title role="2">L1.1</title> <para>This document defines an XML schema for ....</para> <title role="2">L1.2</title> <para>The normative XML Schema for the OpenDoc ....</para> <title role="1">L2</title> <para>This chapter introduces the structure of ....</para> <para>In the OpenDocument format, each structu ....</para>
<title role="2">L2.1</title> <para>A document root element is the primary e ....</para>
<title role="3">L2.1.1</title> <para>The content models of the five root elem ....</para>
<title role="4">L4 test</title> <para>The content models of the five root elem ....</para> <para>The <office:document> root contains a co ....</para>
<title role="4">L4 test 2.1.1.2</title> <para>The content models of the five root elem ....</para> <para>The <office:document> root contains a co ....</para>
<title role="2">L2.1</title> <para>A document root element is the primary e ....</para>
<xsl:template match="title" >
<xsl:variable name='this' select='.'/>
<block role="{@role}">
<xsl:attribute name='sect'>
<xsl:call-template name="number">
<xsl:with-param name='lvl' select='@role'/>
</xsl:call-template>
</xsl:attribute>
<title><xsl:value-of select="."/></title>
<xsl:apply-templates
select="following-sibling::para[preceding::title[1]=$this]"
mode='group'/>
</block>
</xsl:template>
<xsl:template match="para" mode="group"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:copy-of select="*|text()"/> </xsl:copy> </xsl:template>
<!-- Work out the numbering for $lvl n --> <xsl:template name="number"> <xsl:param name='lvl' as="xs:integer"/> <!-- h1..h6 --> <xsl:param name='n' select='0.0' as='xs:decimal'/> <!-- hdg # -->
<xsl:choose>
<!-- Higher levels -->
<xsl:when test="$lvl > 1">
<xsl:variable name='higher'
select="preceding-sibling::title[@role > $lvl][1]" />
<xsl:if test="not($higher/@role)">
<xsl:message terminate='yes'>
Higher is empty
Level is <xsl:value-of select="$lvl"/>
<xsl:text>, content [ </xsl:text>
<xsl:value-of select="."/>
</xsl:message>
</xsl:if>
<xsl:variable name='prev'
select="count(preceding-sibling::title[@role = $lvl]
[ $higher << .])"/>
<xsl:variable name='res' select="dp:dec($lvl, $prev) + $n"/> <!-- Process higher levels -->
<xsl:for-each select="$higher">
<xsl:call-template name="number">
<xsl:with-param name='lvl' select='$lvl - 1'/>
<xsl:with-param name="n" select='$res'/>
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<!-- Level 1 -->
<xsl:when test="$lvl = 1">
<xsl:variable name='prev'
select="count(preceding-sibling::title[@role='1'])"/>
<xsl:variable name='res' select="dp:dec($lvl, $prev) + $n"/>
<xsl:call-template name="number">
<xsl:with-param name='lvl' select='$lvl - 1'/>
<xsl:with-param name="n" select='$res'/>
</xsl:call-template>
</xsl:when>
<!-- Terminating Condition -->
<xsl:otherwise>
<xsl:value-of select="$n"/>
</xsl:otherwise>
</xsl:choose><!-- calculate decimal value from level -->
<!--
Inputs: level (from heading level, 1..4)
count : # of preceding items at this level
@return: decimal, representing a value to be used for this
Note. Since levels are 0 based, 1 is added each time.
heading. Mappings:
lvl count @return
1 0 1.0
2 0 0.1
3 1 0.02
4 2 0.003
5 ? error, fails
-->
<xsl:function name="dp:dec" as='xs:decimal'>
<xsl:param name='lvl' />
<xsl:param name='count' as='xs:integer'/>
<xsl:if test='$lvl < 1 or $lvl > 4'>
<xsl:message terminate='yes'>
Invalid input to dp:dec, <xsl:value-of select='$lvl'/>
</xsl:message>
</xsl:if>
<xsl:variable name='dcount' as ='xs:decimal'
select='($count + 1) cast as xs:decimal'/>
<xsl:variable name='n'>
<xsl:choose>
<xsl:when test="$lvl = 4">
<xsl:value-of select="$dcount * 0.001"/>
</xsl:when>
<xsl:when test="$lvl = 3">
<xsl:value-of select="$dcount * 0.01"/>
</xsl:when>
<xsl:when test="$lvl = 2">
<xsl:value-of select="$dcount * 0.1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$dcount * 1.0"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$n"/>
</xsl:function>-- Dave Pawson XSLT XSL-FO FAQ. http://www.dpawson.co.uk
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Re: [xsl] Is it possible to access , Michael Ludwig | Thread | Re: [xsl] Grouping problem. 2.0, Andrew Welch |
| Re: [xsl] Is it possible to access , XemonerdX | Date | Re: [xsl] Grouping problem. 2.0, Andrew Welch |
| Month |