Pages: 1
Print
Author Topic: How to add leading numbers in headings for PDF output?  (Read 13860 times)
Chartered Ham
Member

Posts: 8

Brevity is the friend of tomorrow


« on: March 13, 2009, 04:37:02 PM »

When generating PDF output from XMetaL, I need the first two main headings to have leading numbers that specify chapter number, section, and sub-section as follows.

For example:

   1.1   Chapter One, First Heading

   1.2   Chapter One, Second Heading

      1.2.1   Chapter One, First Subheading of Second Heading

      1.2.2   Chapter One, Second Subheading of Second Heading

   .....

   2.1   Chapter Two, First Heading

   2.2   Chapter Two, Second Heading

... and so forth.

I know that I need to edit the "topic.topic.title" and "topic.topic.topic.title" attribute sets in custom.xsl to do this, but I'm not sure what code to use or where to start.

Can anyone suggest how I might implement this paradigm?

Many thanks,
Chartered Ham
« Last Edit: March 13, 2009, 04:47:54 PM by Chartered Ham » Logged
Chris
Solutions Consultant (XMetaL)
Member

Posts: 18


« Reply #1 on: March 16, 2009, 05:24:59 PM »

Hi Chartered,

To add numbering to topic titles, you will have to override two XSL templates from [xmfo]/xsl/fo/commons.xsl:

"processTopicTitle" from ~line 580, and "getTitle" from ~1220.

The "getTitle" override controls display in the body text and TOC, and "processTopicTitle" renders the link text for inline xrefs.

Copy both of these templates into your customization file: [xmfo]/Customization/fo/xsl/custom.xsl

1. For "getTitle", add a variable called "level":

<xsl:variable name="level" select="count(ancestor::*[contains(@class,' topic/topic ')])"/>

Now you can use the value of "level" in the choose statement - add this just before the <xsl:otherwise>:

<xsl:when test="$level = 2 or $level = 3">
  <xsl:number
    count="*[contains(@class, ' topic/topic ')]"
    level="multiple"/><xsl:text> </xsl:text>
  <xsl:apply-templates/>
</xsl:when>


2. For "processTopicTitle", add a variable called "level" after the "element" variable:

<xsl:variable name="level">
  <xsl:for-each select="$element">
    <xsl:value-of select="count(ancestor::*[contains(@class, ' topic/topic ')]) + 1"/>
  </xsl:for-each>
</xsl:variable>

Further down in the template, just before the <otherwise> element, modify the topic/title match:

<xsl:when test="$element/*[contains(@class, ' topic/title ')]">
  <!-- Add numbering here -->
  <xsl:for-each select="$element">
    <xsl:number count="*[contains(@class, ' topic/topic ')]" level="multiple"/><xsl:text> </xsl:text>
  </xsl:for-each>
  <xsl:value-of select="string($element/*[contains(@class, ' topic/title ')])"/>
</xsl:when>

This should get you started - you may have to tweak some of the xsl:number attributes (@from, @level, etc.) to get the exact numbering you're after.

HTH,

- Chris
Logged

Chris Johnson
XMetaL Services
Chartered Ham
Member

Posts: 8

Brevity is the friend of tomorrow


« Reply #2 on: March 16, 2009, 05:59:08 PM »

Chris,

Thank you so very much for taking the time to do this. It was very much appreciated.

Regards,
CH
Logged
Chartered Ham
Member

Posts: 8

Brevity is the friend of tomorrow


« Reply #3 on: March 26, 2009, 06:55:21 PM »

Hi Chris,

Once again, thanks for the solution to my question. Unfortunately, it turned out to be only a partial solution, for a couple of different reasons.

Just to recap briefly, my question was about how to add leading numbers to first- and second-level headings in PDF output, as follows in this example:

   1.1   Chapter One, First Heading

   1.2   Chapter One, Second Heading

      1.2.1   Chapter One, First Subheading of Second Heading

      1.2.2   Chapter One, Second Subheading of Second Heading

   .....

   2.1   Chapter Two, First Heading[/quote]

You responded as follows:

Quote
To add numbering to topic titles, you will have to override two XSL templates from [xmfo]/xsl/fo/commons.xsl:

"processTopicTitle" from ~line 580, and "getTitle" from ~1220.

The "getTitle" override controls display in the body text and TOC, and "processTopicTitle" renders the link text for inline xrefs.

Copy both of these templates into your customization file: [xmfo]/Customization/fo/xsl/custom.xsl

1. For "getTitle", add a variable called "level":

<xsl:variable name="level" select="count(ancestor::*[contains(@class,' topic/topic ')])"/>

Now you can use the value of "level" in the choose statement - add this just before the <xsl:otherwise>:

<xsl:when test="$level = 2 or $level = 3">
  <xsl:number
    count="*[contains(@class, ' topic/topic ')]"
    level="multiple"/><xsl:text> </xsl:text>
  <xsl:apply-templates/>
</xsl:when>

The first part about modifying the getTitle template worked. We modified our Custom.xsl file using this suggestion.

For the second part of your tip, however, you wrote:

Quote
2. For "processTopicTitle", add a variable called "level" after the "element" variable:

<xsl:variable name="level">
  <xsl:for-each select="$element">
    <xsl:value-of select="count(ancestor::*[contains(@class, ' topic/topic ')]) + 1"/>
  </xsl:for-each>
</xsl:variable>

Further down in the template, just before the <otherwise> element, modify the topic/title match:

<xsl:when test="$element/*[contains(@class, ' topic/title ')]">
  <!-- Add numbering here -->
  <xsl:for-each select="$element">
    <xsl:number count="*[contains(@class, ' topic/topic ')]" level="multiple"/><xsl:text> </xsl:text>
  </xsl:for-each>
  <xsl:value-of select="string($element/*[contains(@class, ' topic/title ')])"/>
</xsl:when>

This is a problem because the "processTopicTitle" template in Commons.xsl does not contain a variable called "element" -- nor does it contain an <otherwise> element.

Luckily, we were able to work around this by partially implementing your fix by modifying the end of my Custom.xsl file as follows:

 <xsl:template name="getTitle"><!-- get fully-processed title content by whatever mechanism -->
        <xsl:variable name="level" select="count(ancestor::*[contains(@class,' topic/topic ')])"/>
        <xsl:choose>
            <!--             add keycol here once implemented-->
            <xsl:when test="@spectitle">
                <xsl:value-of select="@spectitle"/>
            </xsl:when>
            <xsl:when test="$level = 2 or $level = 3">
                <xsl:number count="*[contains(@class, 'topic/topic')]" level="multiple"/>
                <xsl:text> </xsl:text>
                <xsl:apply-templates/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

... so it still works. The first- and second-level headings in my PDF output have leading numbers.

This breaks, however, when inserting a subtopic or section within a topic that turns out to be at the first- or second-level heading within the ditamap. The subtopic or section title inherits the leading number -- something we don't want to happen.

For example, if I have a second-level heading topic at a numbering level of, say, 2.3.4, any subtopic or section within that topic will also have the same numbering level "2.3.4" appended onto the front of it. Like this:

   2.3.4. Topic Title

      2.3.4. Subhead Topic Title

         [text]

      2.3.4 Second Subhead Topic Title

         [text]

      2.3.4. Section Topic Title

         [text]

Not good, obviously.

My questions are:

  • Can you clarify what you meant in item 1 about the "element" variable and the <otherwise> element?
  • Can you suggest how I might fix the coding so that subtopic and section titles don't inherit the leading numbers of their parent topics?

I know this is asking a lot, so I appreciate any response you might be willing to offer.

Thank you!

Sincere Regards,
C.H.
Logged
Chris
Solutions Consultant (XMetaL)
Member

Posts: 18


« Reply #4 on: March 30, 2009, 06:50:53 PM »

Sorry Chartered - copy/paste error - I meant the "insertReferenceTitle" template, not the "processTopicTitle" template:

For "insertReferenceTitle", add a variable called "level" after the "element" variable:

<xsl:variable name="level">
  <xsl:for-each select="$element">
    <xsl:value-of select="count(ancestor::*[contains(@class, ' topic/topic ')]) + 1"/>
  </xsl:for-each>
</xsl:variable>

Further down in the template, just before the <otherwise> element, modify the topic/title match:

<xsl:when test="$element/*[contains(@class, ' topic/title ')]">
  <!-- Add numbering here -->
  <xsl:for-each select="$element">
    <xsl:number count="*[contains(@class, ' topic/topic ')]" level="multiple"/><xsl:text> </xsl:text>
  </xsl:for-each>
  <xsl:value-of select="string($element/*[contains(@class, ' topic/title ')])"/>
</xsl:when>


For your second question, I'd need more info - can you post a zip with a map and topic files that show the problem?

- Chris
Logged

Chris Johnson
XMetaL Services
WinstonRV
Member

Posts: 9


« Reply #5 on: February 18, 2011, 11:15:49 AM »

was trying your solution but can't find "insertReferenceTitle"  in my commons.xsl.
With the gettitle i'm able to get numbering upto second level.
Logged
keesvandewal
Member

Posts: 1


« Reply #6 on: May 09, 2011, 04:32:32 AM »

Hi chartered,

I've almost the same question. I want to number my headings on level 1, 2 and 3 and the section titles:
1.
1.1.
1.1.1.
and so on.

I've tried to implement the solution from Chris, but in this discussion your last question is not answered.

Maybe you can tell me how you, if you have, solved the problem.

Kind regards,
Kees


Logged
IF
Member

Posts: 80


« Reply #7 on: August 24, 2011, 11:35:12 AM »

I have been able to number headings successfully by making the template changes described here:
http://tech.groups.yahoo.com/group/dita-users/message/19154 

Now, I would like to revise this a bit and start numbering at the second topic. I am struggling with the syntax. I have tried to use the topic position, the topic title, or the number of preceding siblings. But I'm doing something wrong...
Any ideas? Thanks.
For example - adding the following to the GetTitle  template does not work

<!-- Suppress numbering of revision history-->
<xsl:when test="parent::*[contains(@class,'topic/topic')][1]">
<xsl:apply-templates />
</xsl:when>

<!-- Suppress numbering of revision history-->
<xsl:when test="parent::*[contains(@class,'topic/topic')][@title = 'Revision history']">
<xsl:apply-templates />
</xsl:when>


Logged
Pages: 1
Print
Jump to:  

email us