3

Does somebody know how to achieve this with XSL-FO transformation? The question details should be clear from the codes below.

Input:

<section>
    <title>Section 1</title>
    <orderedlist>
        <listitem><para>item 1.1</para></listitem>
        <listitem>
            <para>item 1.2</para>
            <orderedlist>
                <listitem><para>item a</para></listitem>
                <listitem><para>item b</para></listitem>
            </orderedlist>
        </listitem>
    </orderedlist>
</section>
<section>
    <title>Section 2</title>
    <orderedlist>
        <listitem><para>item 2.1</para></listitem>
        <listitem><para>item 2.2</para></listitem>
    </orderedlist>
</section>

Desired output:

Section 1
1. item 1.1
2. item 1.2
   a. item a
   b. item b

Section 2
3. item 2.1
4. item 2.2

Here is the XSL file for lists:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fo="http://www.w3.org/1999/XSL/Format">

    <!-- templates for lists - supports numbered and itemized types -->
    <!-- the maximum depth is currently 2 -->
    <xsl:template match="orderedlist">
        <fo:list-block start-indent="0.5cm" space-before="0.2cm"
            provisional-distance-between-starts="0.7cm">
            <xsl:apply-templates />
        </fo:list-block>
    </xsl:template>
    <xsl:template match="orderedlist//orderedlist">
        <fo:list-block start-indent="1.2cm" provisional-distance-between-starts="0.7cm"
            padding-top="-0.2cm" padding-bottom="0.2cm">
            <xsl:apply-templates />
        </fo:list-block>
    </xsl:template>
    <xsl:template match="itemizedlist">
        <fo:list-block start-indent="0.5cm" space-before="0.2cm"
            provisional-distance-between-starts="0.7cm">
            <xsl:apply-templates />
        </fo:list-block>
    </xsl:template>
    <xsl:template match="itemizedlist//itemizedlist">
        <fo:list-block start-indent="1.2cm" provisional-distance-between-starts="0.7cm"
            padding-top="-0.2cm" padding-bottom="0.2cm">
            <xsl:apply-templates />
        </fo:list-block>
    </xsl:template>
    <xsl:template match="orderedlist/listitem">
        <fo:list-item margin-top="0.1cm">
            <fo:list-item-label end-indent="label-end()">
                <fo:block>
                    <xsl:number count="listitem" format="1." />
                </fo:block>
            </fo:list-item-label>
            <fo:list-item-body start-indent="body-start()">
                <fo:block>
                    <xsl:apply-templates />
                </fo:block>
            </fo:list-item-body>
        </fo:list-item>
    </xsl:template>
    <xsl:template match="orderedlist//orderedlist/listitem">
        <fo:list-item>
            <fo:list-item-label end-indent="label-end()">
                <fo:block>
                    <xsl:number count="listitem" format="a." />
                </fo:block>
            </fo:list-item-label>
            <fo:list-item-body start-indent="body-start()">
                <fo:block>
                    <xsl:apply-templates />
                </fo:block>
            </fo:list-item-body>
        </fo:list-item>
    </xsl:template>
    <xsl:template match="itemizedlist/listitem">
        <fo:list-item margin-top="0.1cm">
            <fo:list-item-label end-indent="label-end()">
                <fo:block>&#8226;</fo:block>
            </fo:list-item-label>
            <fo:list-item-body start-indent="body-start()">
                <fo:block>
                    <xsl:apply-templates />
                </fo:block>
            </fo:list-item-body>
        </fo:list-item>
    </xsl:template>
    <xsl:template match="itemizedlist//itemizedlist/listitem">
        <fo:list-item>
            <fo:list-item-label end-indent="label-end()">
                <fo:block>&#8226;</fo:block>
            </fo:list-item-label>
            <fo:list-item-body start-indent="body-start()">
                <fo:block>
                    <xsl:apply-templates />
                </fo:block>
            </fo:list-item-body>
        </fo:list-item>
    </xsl:template>
</xsl:stylesheet>
Emiliano Poggi
  • 24,390
  • 8
  • 55
  • 67
user219882
  • 15,274
  • 23
  • 93
  • 138
  • Are you using DocBook? Your input XML looks like it. – mzjn Sep 08 '11 at 16:06
  • @mzjn No, I'm using just DocBook tags (in case we will use DocBook in the future) but I'm using my own transformation. Any ideas how to solve the problem? – user219882 Sep 09 '11 at 08:48

2 Answers2

1

Assuming you input sample is (added the sections topmost element to make the sample well-formed):

<sections>
<section>
    <title>Section 1</title>
    <orderedlist>
        <listitem><para>item 1.1</para></listitem>
        <listitem>
            <para>item 1.2</para>
            <orderedlist>
                <listitem><para>item a</para></listitem>
                <listitem><para>item b</para></listitem>
            </orderedlist>
        </listitem>
    </orderedlist>
</section>
<section>
    <title>Section 2</title>
    <orderedlist>
        <listitem><para>item 2.1</para></listitem>
        <listitem><para>item 2.2</para></listitem>
    </orderedlist>
</section>
</sections>

at a given listitem of first level you can use:

count(
    preceding-sibling::listitem 
    | 
    ../../preceding-sibling::section/orderedlist/listitem) 
    + 1

For example:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output indent="yes"/>

    <xsl:template match="sections">
        <fo:block>
            <xsl:apply-templates select="section"/>
        </fo:block>
    </xsl:template>

    <xsl:template match="section">
        <fo:list-block>
            <xsl:apply-templates select="title | orderedlist/listitem"/>
        </fo:list-block>
    </xsl:template>

    <xsl:template match="title">
        <fo:list-item>
            <xsl:value-of select="."/>
        </fo:list-item>
    </xsl:template>

    <xsl:template match="listitem">
        <fo:list-item>
            <xsl:number 
                value="count(
                preceding-sibling::listitem 
                | 
                ../../preceding-sibling::section/orderedlist/listitem) 
                + 1" format="1.&#x20;"/>
        </fo:list-item>
    </xsl:template>
</xsl:stylesheet>

produces:

<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <fo:list-block>
      <fo:list-item>Section 1</fo:list-item>
      <fo:list-item>1. </fo:list-item>
      <fo:list-item>2. </fo:list-item>
   </fo:list-block>
   <fo:list-block>
      <fo:list-item>Section 2</fo:list-item>
      <fo:list-item>3. </fo:list-item>
      <fo:list-item>4. </fo:list-item>
   </fo:list-block>
</fo:block>
Emiliano Poggi
  • 24,390
  • 8
  • 55
  • 67
  • This nearly works. The problem is that I have another nested `orderedlist` in the first one and the second part counts listitems from the nested list too. I tried to change the level but it made no difference. – user219882 Sep 14 '11 at 08:39
  • Also if I have another orderedlist below, the numbers continue. I just want to have those two numbered together and the rest from 1. – user219882 Sep 14 '11 at 14:00
  • Check my answer now. If still far from your intentions, please provide a better description/sample of the wanted output. – Emiliano Poggi Sep 14 '11 at 23:08
  • 1
    This is great! I tweaked it little bit and it works nice. Thank you! – user219882 Sep 15 '11 at 09:01
0

Do you have a particular reason for not using DocBook and the DocBook-XSL stylesheets? That would give you a lot "for free" (perhaps you know that already).

In DocBook, what you ask for is already implemented. There is a continuation attribute on <orderedlist> that indicates whether the numbering in a list continues from the preceding list. This is supported in the DocBook-XSL styleheets for FO output (check out fo/lists.xsl and common/common.xsl to see how it's done).

mzjn
  • 48,958
  • 13
  • 128
  • 248