Wednesday 9 November 2011

Simplifying PDF Document Publishing in the DITA OpenToolkit

In a recent post on the Yahoo DITA Users Group, Mark Griffin described one of "the main things that people want to do and find difficult" as "adjusting the cover page for PDF output" and, as I was working on exactly that, I thought I'd jot down a few notes to help others.

I was working in the DITA OpenToolkit (DITA-OT) version 1.5.3 on Windows 7.

The idea here is to let you get usable output from the DITA OpenToolkit in a little under an hour. Let me know in the comments if you have any difficulties. The ethos of PDF customization is that you should override the configuration files by creating custom files. This is not always possible. In particular I found that front-matter_1.0.xsl cannot be moved or overridden.

As a minimum, I recommend you use a good text editor like Notepad++.

Downloading the toolkit
 

First, download the latest DITA-OT file from sourceforge and unzip it to the root of your data drive.

Testing it works with a publish
 

Note: From here on, all the file and folder paths I use are relative to the inside of the DITA-OT folder.

Make sure the DITA-OT is working the way we need it:
  1. Double-click startcmd.bat.
  2. Change directory, type cd samples\ant_sample
  3. Type ant -f sample_pdf.xml
  4. Wait for the processing to finish then, in Windows Explorer, navigate to samples\ant_sample\out\samples\pdf.
  5. Open file hierarchy.pdf to view the result.
Leave the command prompt open so that you can test your changes as you make them.

Simplifying headers and footers
 

I simplified the headers and footers so that they contained only the product name at the top and page number at the bottom (except the cover). To add the product name to the header:
  1. Copy en.xml from demo\fo\cfg\common\vars to demo\fo\Customization\common\vars

  2. There is no need to update catalog.xml for custom vars. They are used automatically.

  3. Define the variable Product Name in en.xml

  4.  <variable id="Product Name">MyProduct Version 8</variable>

  5. In en.xml, add page numbers to all the footer definitions (search for "footer")

    <variable id="Body odd footer"><param ref-name="pagenum"/></variable>
     
  6. Still in en.xml, simplify the header variables to just show the product name variable

    For example, from:

    <variable id="Body odd header"><param ref-name="prodname"/>&#xA0;|&#xA0;<param ref-name="heading"/>&#xA0;|&#xA0;<param ref-name="pagenum"/></variable>

    To:

    <variable id="Body odd header"><param ref-name="prodname"/></variable>

    Also, the headers and footers were too close to the edge of the page.
     
  7. Copy all the definitions for header and footer positioning from demo\fo\cfg\fo\attrs\static-content-attr.xsl to demo\fo\Customization\fo\attrs\custom.xsl. These appear as follows:

    <xsl:attribute-set name="__body__first__header">
           <xsl:attribute name="text-align">right</xsl:attribute>
           <xsl:attribute name="margin-right">10pt</xsl:attribute>
           <xsl:attribute name="margin-top">10pt</xsl:attribute>
    </xsl:attribute-set>

    And set all the margins (I used search and replace):

    • "margin-left">57pt 
    • "margin-right">57pt 
    • "margin-bottom">35pt 
    • "margin-top">35pt

  8. In order to get the publishing to use the custom.xsl file, enable it in demo/fo/Customization/catalog.xml by removing the commenting around the following line:

    <uri name="cfg:fo/attrs/custom.xsl" uri="fo/attrs/custom.xsl"/>

    I then needed to remodel the header and footer to just show the product name at the top, and the page number at the bottom.

  9. Publish again to check it worked.

    The page numbers and product name should appear on every page except the cover and be further from the edge.

Adjusting the page size
 

I needed A4 paper which is 210mm x 297mm, the DITA-OT default is US Letter size.

To change the paper size:
  1. Copy the global variables for page and margin from demo\fo\cfg\fo\attrs\basic-settings.xsl to demo\fo\Customization\fo\attrs\custom.xsl and change to the following:

    <xsl:variable name="page-width">210mm</xsl:variable> 
    <xsl:variable name="page-height">297mm</xsl:variable>

  2. Publish again to check it worked.

Setting the default font
 

I also needed to make the default font Sans Serif.

To change the default font:
  1. Copy attribute-set __fo__root from demo\fo\cfg\fo\attrs\commons-attr.xsl to demo\fo\Customization\fo\attrs\custom.xsl.
  2. Change font from "Serif" to "Sans".
  3. Publish again to check it worked.

A simple front page
 

I made a simple front page with a logo at the top-right, product name (set in the map @product attribute), map title, and revision (set in the map @rev attribute). The blocks just stack and fill the flow from the top down. Measurements are defined in the attribute sets: __frontmatter__product, __frontmatter__title, and __frontmatter__rev.

Add the following blocks which include the image block in demo\fo\xsl\fo\front-matter_1.0.xsl. They need to go inside template name="createFrontMatter_1.0", in the xsl-region-body flow. They include 2 new blocks before the title and 1 after as follows:


<!-- RP added: frontmatter logo -->
<fo:block margin-left="5.2in">
<fo:external-graphic src="url(Customization/OpenTopic/common/artwork/logo.png)"/>
</fo:block>
<!-- RP added: set the product -->
<fo:block xsl:use-attribute-sets="__frontmatter__product">
<xsl:choose>
<xsl:when test="//*[contains(@class, ' map/map ')]/@product">
<xsl:value-of select="//*[contains(@class, ' map/map ')]/@product"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>Product attribute not set for map</xsl:text>
</xsl:otherwise>
</xsl:choose>
</fo:block>
<!-- set the title --> (this exists unchanged)
<fo:block xsl:use-attribute-sets="__frontmatter__title">
...
...
...
</fo:block>
<!-- RP added: set the revision -->
<fo:block xsl:use-attribute-sets="__frontmatter__rev">
<xsl:choose>
<xsl:when test="//*[contains(@class, ' map/map ')]/@rev">
<xsl:value-of select="//*[contains(@class, ' map/map ')]/@rev"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>Revision attribute not set for map</xsl:text>
</xsl:otherwise>
</xsl:choose>
</fo:block>


Place your logo.png file in folder demo\fo\Customization\common\artwork folder.

Create the attribute sets. Copy the __frontmatter__title block attribute-set from demo\fo\cfg\fo\attrs\front-matter-attr.xsl to demo\fo\Customization\fo\attrs\custom.xsl and duplicate it for __frontmatter__product and __frontmatter__rev. I left aligned __frontmatter then adjusted the vertical spacing as follows:


<!-- front-matter-attr.xsl modifications -->
    <xsl:attribute-set name="__frontmatter">
        <xsl:attribute name="text-align">left</xsl:attribute>
    </xsl:attribute-set>
 
    <xsl:attribute-set name="__frontmatter__product">
        <xsl:attribute name="margin-top">30mm</xsl:attribute>
        <xsl:attribute name="font-family">Sans</xsl:attribute>
        <xsl:attribute name="font-size">18pt</xsl:attribute>
        <xsl:attribute name="font-weight">normal</xsl:attribute>
        <xsl:attribute name="line-height">140%</xsl:attribute>
    </xsl:attribute-set>
 
    <xsl:attribute-set name="__frontmatter__title">
        <xsl:attribute name="margin-top">45mm</xsl:attribute>
        <xsl:attribute name="font-family">Serif</xsl:attribute>
        <xsl:attribute name="font-size">28pt</xsl:attribute>
        <xsl:attribute name="font-weight">bold</xsl:attribute>
        <xsl:attribute name="line-height">140%</xsl:attribute>
    </xsl:attribute-set>
 
    <xsl:attribute-set name="__frontmatter__rev">
        <xsl:attribute name="margin-top">128mm</xsl:attribute>
        <xsl:attribute name="font-family">Sans</xsl:attribute>
        <xsl:attribute name="font-size">10pt</xsl:attribute>
        <xsl:attribute name="font-weight">normal</xsl:attribute>
        <xsl:attribute name="line-height">140%</xsl:attribute>
    </xsl:attribute-set>

Finally, publish again.



No comments:

Post a Comment